finnikk

The blog of a thinkerer.
By @finnikk

All rights reserved.

"Working with Unix Processes" Review (By Jesse Storimer)

The last thing I want to do is dealing with low-level operating system things. That's one of the reasons why I like Ruby, because it keeps me from having to deal with all that. So why the hell would I read "Working with Unix Processes"? Well, first, it was the book of choice for the (fantastic) Ruby Rogues podcast, episode 058. And second: It was a really amazing ride! Jesse managed to get down to the lowest level and still managed to explain everything in terms I actually understand! You can get the book on Amazon for around 17.00€ ($21.00). Side note: "Working with Unix Processes" was first self published by Jesse Storimer over at workingwithunixprocesses.com, but has now been picked up by The Pragmatic Programmers.

Content

Working with Unix Processes concentrates on the rarely used Ruby module Kernel#fork and its companions. Jesse Storimer starts out with a gentle introduction to processes, process IDs and everything else you didn't know you wanted to know about processes. Did you know, for example, that processes belong to a process group? And that a whole process group can be killed at the same time? And that that's basically how a terminal emulator works? No? Neither did I! After he explains everything about processes, he goes on and explains that processes can fork. This is actually a very important feature of all operating system. All processes are spawned from one process, which is created at boot. And so he introduces us to process parents, children, and orphaned processes, and what that means. After forking, the next important thing is joining processes together again (for example to enable multicore processing). Of course, now that we have multiple processes, another important aspect is communication between processes. This is done either through signals or interprocess communication. He then ends "Working with Unix Processes" with an extensive Appendix, where he digs deeper into the inner workings of such gems as Resque or Unicorn.

The good

One part I loved about the book is that each chapter has a short note on "Use in the real world". Here Jesse Storimer highlights projects that use the aforementioned technique. Another nice thing he did was include a Spyglass server. This is a heavily documented server in Ruby that he developed specifically for the book, to highlight how his techniques can be leveraged. Reading through it is pure joy! A very nice feature of the book is that it is a living book. Since Jesse released it (Dec 20, 2011) he released 14 new version (some just fix typos, but others added full new chapters or new and extended explanations for the things he explained.

The bad

For one, the name. It is called "Working with Unix Processes", but a better name would have been "Working with Unix Processes in Ruby". A lot of the advise he gives is very Ruby specific, and all examples are in Ruby. I'm not saying it isn't applicable if you use other languages, but this book focuses on Ruby. Of course, this was the audience he had in mind, but it is something that everyone should remember when buying this book. I am also not sure what the target audience for the book is. A system programmer (which doesn't know Ruby) doesn't need to be told how fork works, or what process IDs are. For a Ruby programmer that just tries to leverage some more programming near the system, the book was a bit too terse, and the examples were too abstract.

Conclusion

Besides its shortcoming, I found it a great book to read. You can read it in 3 hours (aka a rainy Sunday afternoon) and get through it pretty quickly. If you want to dive deeper, the source code to Spyglass and the other mentioned open source projects are right at your fingertips. I recommend this book to everyone who is interested in a more systems programming approach, and wants to know the basics so he can see when they could help. Ruby knowledge is required though, or else the book won't make that much sense. The topic sounds boring, mundane even, but I think if you are at least a bit curious you should give it a chance and read it. Sparked your interest? Then don' wait and get the book! If you liked this post, you should follow me on Twitter and signup for the RSS feed!

How do CSS grids work?

When I started with a new web page I, like (probably?) most of us, didn't start from the very beginning. Why? Because there is a lot of ceremony involved in setting up the basic structure of a web app. We need a navigation. A content area. A header. A footer. And we probably arrange them in a grid. And of course we need to apply standard styling to buttons, forms, tables, and typography. Luckily, we have CSS frameworks that take out most of the guess-work and lay a good foundation for us. While it works, I always wondered how to these grids work? Is it magic?

It' (not) magic!

Let me give you an example. In Twitter's Bootstrap we can arrange content with a few divs:
<div class="row">
  <div class="offset2 span4">
    I'm offset two columns and four columns wide
  </div>
  <div class="span4">
    I'm also four columns wide
  </div>
</div>
<div class="row">
  <div class="offset2 span8">
    And I'm on a new row!
  </div>
</div>
Other frameworks use similar syntax. So... how do they work?

Bootstrap, 960 Grid System

There are a few CSS frameworks around, but I will compare Twitter's Bootstrap and 960 Grid System. I already showed a basic example with Bootstrap. Now let's compare it with 960.gs:
<div class="grid_4 prefix_2">
  I'm offset two columns and four columns wide
</div>
<div class="grid_4">
  I'm also four columns wide
</div>
<div class="clear"></div>
<div class="grid_8 prefix_2">
  And I'm on a new row!
</div>
It works similar to Bootstrap, in that we define the length with "grid_4" compared to "span4". Also we can define the offsets with "prefix_2" ("offset2" in Bootstrap). But there is a difference how we define a new row. Whereas Bootstrap uses an outer div with class "row", 960.gs relies on a clearfix div on the same level. Here I like Bootstraps approach better, because it is easier to walk through the HTML when I can collapse a whole row and don't have to search on possibly hundreds of divs on the same level to find the cell in the middle of the document.

How these grids actually work

Thanks for all the syntax, but I still didn't talk about how the magic happens. Let's look at Bootstrap first.

Bootstrap SPAN

If we take a look at bootstraps source code, we can find a file called grid.less*. The only thing this file does is call the #grid core mixin. There is also an import for the responsive version of the grid, but we will ignore that one for this walk-through.
// Fixed (940px)
#grid > .core(@gridColumnWidth, @gridGutterWidth);
(See also on Github) We can find the core mixin under, surprise, surprise, mixins.less. Bootstrap defines a mixin called .spanX (@index). It recursively creates all the .span12 .span11 etc. classes in the compiled CSS.
    .spanX (@index) when (@index > 0) {
      (~".span@{index}") { .span(@index); }
      .spanX(@index - 1);
    }
    .spanX (0) {}
(On Github) The line (~".span@{index}") { .span(@index); } uses Javascript Evaluation to define the class. The rules will be the LESS mixin .span (line 2), so lets look at this next.
.span (@columns) {
    width: (@gridColumnWidth * @columns) + (@gridGutterWidth * (@columns - 1));
}
(On Github) This sets the width of the .spanX to the width of the columns plus the gutter in between the columns it spans. But wait! That can't be all! We can define multiple spans in a single row! So we have some more CSS!
[class*="span"] {
      float: left;
      margin-left: @gridGutterWidth;
}
(Github) All classes that start with .span will be floated to the left. Additionally, the gutter is applied as margin on the left, so the columns have a bit distance between each other. So that about covers the .span. What about .offset?

OFFSETing Bootstrap

Offsetting works roughly the same as spanning the grid elements:
.offsetX (@index) when (@index > 0) {
      (~".offset@{index}") { .offset(@index); }
      .offsetX(@index - 1);
    }
    .offsetX (0) {}

    .offset (@columns) {
      margin-left: (@gridColumnWidth * @columns) + (@gridGutterWidth * (@columns + 1));
}
(Github) Again, we have the .offsetX-mixin that creates the possible offsets. This will load the .offset mixin (note the missing 'X'), which calculates the, well, offsets (highlighted lines). All the classes I used in the example except .row have been explained. Let's look at the rows.

Bootstrapping rows

This one will be easy:
.row {
      margin-left: @gridGutterWidth * -1;
      .clearfix();
}
(Github) It adds a margin to each row and then loads the .clearfix mixin. The clearfix code requires some trickery since clearfix and browsers tend to hate each other (as described in the comment).
.clearfix {
  *zoom: 1;
  &:before,
  &:after {
    display: table;
    content: "";
  }
  &:after {
    clear: both;
  }
}
(Github)

The Bootstrap Conclusion

So how does bootstrap generate the grid? Four steps are needed:
  • Create all possible .spanX classes, where the length is calculated based on column width and gutter. Also float them to the left.
  • Create all possible .offset classes with the length calculated from column width and gutter.
  • Create a .row class that acts as a clearfix.
And now we have a grid system!

So what about 960.gs?

I didn't forget! So let's do a check if they use the same system. Go to the 960.gs demo page and see for yourself. .grid_2 is defined as width: 140px and all grid classes are floated to the left and have a gutter applied. The only difference is that 960.gs seems to apply the gutter to left and right, whereas Bootstrap just applies it to the left margin. The "clear" class is a simple clearfix (who would have thought?). The .prefix_X classes have a .padding applied to the left. Again a small difference, 960.gs applies a padding, but Bootstrap relies on margin. So which one is right? ;)

So there you have it

Both systems work roughly the same, with small differences. Both use floated cells with a clearfix to make rows. Both define a cell length and a cell offset. One uses margin, the other padding. Did I miss something interesting? And are there any CSS frameworks out there which use a different system? * Which means Bootstrap is written with LESS, a CSS preprocessor like SASS.

Why the Rails Conventions Are Great

One of the best features of Rails is that is has an opinion. A strong one at that. Anyone coming from the world of Java and J2EE can tell you that having a lot of options isn't always the best thing. Sometimes, a simple convention might be a lot easier to follow than defining hundreds of XML files.

I Love Convention Over Configuration

For example, Rails' ORM, ActiveRecord makes it possible to add columns to the database without changing the model. Which makes it a lot easier to program with. Of course today J2EE has JPA annotations, which come close to that, but I think they still are trying too hard to fit into legacy databases.

Rails is made for the 99% of all use cases, and it doesn't hide that fact. Which isn't wrong, because, well, 99% is a lot after all.

Ease Of Use

One of the amazing things that all this convention gives us is that picking up a new app is really easy. If I look at a Rails app, and a form is wrong, I can simply look at it and change it, there is no need to search where the form is in the app. In J2EE everyone is OK with using something totally different in their stacks. No app looks like the next, so picking it up is really hard and requires a lot of time. J2EE does have "Enterprise" in its name for a reason. I have worked on a huge J2EE app with a huge team, and it was great! But the knowledge needed to write one such app is immense, the overhead big. It is just not made for small development teams.

Think About the Developers

The structure also helps the 501 developers (and, to be honest, all the rest of us), because a huge amount of knowledge backs all this convention about how web apps should be developed. Something one person alone, or a single group, can never match. You don't know where this piece of code should go? No problem, search for it on the web, someone will know (or at least have seen that problem before. Maybe even solved it in a better way that you are thinking about now). This makes everything so much easier. Today, speed is really king. And Rails is fast. Really fast. Getting a site up and running isn't a problem, because there is no need to first assemble the stack yourself. Solving dependency problems. Find out how these two libraries can work together. Everything just works! A demo app will be up in no time.

Your own stack (probably) sucks!

Making your own web development stack is a lot of work. Library X only works with version 2.3 - 3.1 of library Y? But you need 3.2 for library Z? What should you do? How do you keep all the libraries up to date? What about vulnerabilities? Your glue code between two libraries breaks, what now? How should this new guy know all the guidelines you never wrote down? Having your own stack gives you a lot of freedom, but it is also a lot of work. And a mess is already coming... If you have tried it, what are your experiences? I really think, after having done both, but having such well-defined standards and conventions as Rails has does make it a lot easier. Often I thought "This is easier if I do it this way" only to find out later why others didn't do it this the hard way. I'm still waiting for others to pick up what Rails did instead of just copying it. Using the language and tools surrounding it to the fullest advantage. Is there such a thing in beside Rails?