Unix and Node

09 Feb 2012 | By Alex Young | Tags node tutorials essay unix

Recently, Node has received a huge amount of development effort to improve its Windows support. However, most of us probably run Node on some flavour of Unix – whether it be a Linux, Mac OS, Solaris, or a non-fruit BSD.

As JavaScript enthusiasts we can do a lot in Unix with just a little bit of Node. This new essay series is a collection of tips and observations I’ve made about Unix and Node. If you’re interested in writing command-line tools or networking daemons, Node is a good choice, and you’ll see why over the next few weeks.

Folklore and Tradition

If you’re a solid programmer but lack fundamental Unix knowledge, I won’t hold it against you. The important thing to realise is learning Unix requires knowledge of traditions and philosophies. As stated by Eric S. Raymond in The Art of UNIX Programming:

If you are not a programmer, or you are a programmer who has had little contact with the Unix world, this may seem strange. But Unix has a culture; it has a distinctive art of programming; and it carries with it a powerful design philosophy. Understanding these traditions will help you build better software, even if you’re developing for a non-Unix platform.

This means learning to write Unix programs that behave the way seasoned Unix users expect isn’t always a case of looking up standards and best practices. One of the most famous comments on the philosophy of Unix is by Doug McIlroy:

Write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface.

Does that sound familiar? Try changing the word “program” to “module”:

  • Write modules that do one thing and do it well.
  • Write modules that work together.
  • Write modules that handle events and streams.

In The Art of UNIX Programming, Raymond summarises many of these ideas and philosophies into a set of design rules that are readily available on Wikipedia: Unix philosophy.

Rule of Diversity: Distrust all claims for “one true way”.

Coming to Unix development from a web developer’s background requires a change in thinking. When working as a client-side developer, one may regularly refer to W3C specifications. However, when writing Node software for Unix, it’s likely that the philosophy of Unix developers will shape the application more than standards and specifications. To see why we need to take a look at Node’s relationship to POSIX.

POSIX

The family of standards that helps us write portable code is known as POSIX. This covers the C Standard Library, process creation and control, signals, pipes, and a lot more. In addition, the core Node developers have their own philosophy and concerns. For example, Node has to maintain portability with Windows. Certain aspects of POSIX don’t necessarily fit in with Node’s philosophy, hinted at here by Ryan Dahl while discussing the possibility of a Node POSIX library:

dup, dup2, fork are out of the question and will never be added. They do not coincide node’s philosophy. chroot is not useful but is a posix thing. The posix module I suggested was to support random user/permissions stuff like getpwnam(). I’d rather not have that if we can get away with it.

Ryan Dahl on an official POSIX library

This comment by Isaac Schlueter is also interesting:

So far, in any of the cases where we’d thought we’d need to split out a posix library, we’ve been able to find sane approaches for both Windows and Unix. Who knows if that’ll continue, but it’d be nice to not have to do require(“posix”) ever.

Isaac Schlueter on an official POSIX library

How does this affect us as developers interested in writing Unix software? The implications are that Node provides an opaque API layer that sits on top of the operating system, but this isn’t quite true. Differences in Node’s API between Windows and other operating systems are documented in Node’s API documentation. One example is path.join, which will correctly use backslashes in Windows and forward slashes elsewhere.

Design Principles

Extrapolating Raymond’s principles to Node development is an inspirational way to look at Node development. In my experience, writing monolithic applications with Node isn’t a sound architectural approach. I’ve found breaking applications down into small modules and binaries that do one thing well is a good idea. Remember that npm modules don’t have to be publicly released: set that private property to true in your package.json to ensure it isn’t published.

I’d add another rule to Eric’s list:

  • Rule of Sharing: Make supporting documentation, licensing, and tests clear and easy to find. Tests should be easy to run.

To allow people to easily run tests, include a "scripts": { "test": "make test" } so npm test can be used. Also, clearly license Node modules by adding something like this to package.json:

"licenses": [
  {
    "type": "MIT +no-false-attribs",
    "url": "http://github.com/isaacs/npm/raw/master/LICENSE"
  }
]

– From npm’s package.json

The Twelve-Factor App

Unix philosophy reminds me of The Twelve-Factor App by Adam Wiggins. This methodology is inspired by working on Heroku’s platform, which runs hundreds of thousands of applications. Remember how I mentioned POSIX defines signals? Well, knowledge of signals comes in handy when writing applications that behave correctly on a platform like Heroku:

Processes shut down gracefully when they receive a SIGTERM signal from the process manager. For a web process, graceful shutdown is achieved by ceasing to listen on the service port (thereby refusing any new requests), allowing any current requests to finish, and then exiting.

– From Disposability, The Twelve-Factor App

Running software “in the cloud” ultimately means running it on a platform with some level of POSIX compliance.

Conclusion

Unix might have its own culture and principles, but its philosophies can make us better Node developers. Write your next command-line application or daemon with Node, and you might be pleasantly surprised.


blog comments powered by Disqus