I have something to admit. I love C. I've known it for a while, but it's easy to forget. I've gone away to Ruby, Haskell, OCaml, C++, Java, and C# - I spend time with many languages, but when I go back to C, it's like coming home.

I remember flipping through the Kernighan and Ritchie book decades ago, trying to pick up the language. I remember a lot of frustration, but I also remember a lot of satisfaction. C has its quirks, but in retrospect, they are a lot less mysterious than the quirks of many other languages. They don't require deep reasoning. The behavior of a construct is either defined or it isn't, and since undefined behavior has such a high cost, people are careful. They have to be.

A friend of mine, Kevlin Henney, talks quite a bit about affordances in software. An affordance is, essentially, the envelope of perceived action possibilities that a thing offers. People often think about this in terms of "what the software allows you to do" but I think there is a more expansive way of looking at this that explains C. C is prickly, so its affordance is care. If you don't approach your C code with care, you're dead in the water. C's conceptual simplicity and its prickliness are a powerful combination.

Another nice thing about C, from my perspective, is recovery. I don't like repeating this over and over, but I think it gives a bit of perspective to say that I spend most of my time visiting extremely ugly code bases and helping people get past issues in them, and of all of the languages that I frequently encounter code in, the one which is hardest to recover in is C++. There are quite a few reasons, and I won't go into them here but, really, at certain point in a degenerated C++ code base, the language is actively fighting you. I can't count the number of dependency nightmares I've seen - systems where any attempt at a build takes any insane amount of time - where the cure is at least as painful as the path to disease. C, on the other hand, seems to be more recoverable. Or, maybe I've just been lucky.

The problem with C++ (and it's not unique to C++ by any means) is that it tried hard to make things better within an existing framework rather than jumping into a new one. It tried to tune toward better and often that is a disaster. Yet we keep trying. We try to mutate languages like Java and C# into things that they aren't - and, without knowledge or respect for what is there, we fail.

There's something deep in software development that not everyone gets but the people at Bell Labs certainly did. It's an undercurrent of "the New Jersey Style", "Worse is Better", and "the Unix philosophy" - and it's not just a feature of Bell Labs software either. You see it in the original Ethernet specification where packet collision was considered normal.. and the same sort of idea is in the internet protocol. It's deep awareness of design ramification - a willingness to live with a little less to avoid the bigger mess, and a willingness to see elegance in the real rather than the vision.

I was reading a magazine article a few weeks ago whose author implied that the designers of the internet had just stumbled across an approach that embodied sound systems design principles. It really bothered me. I wanted to throw the article across the room. No, those guys knew. They had deep systems thinking skills and they acquired them the hard way. That sort of design only happens when you reflect deeply on a problem and figure out how to work with its grain. C is a language that works with a grain.

I've never met Dennis Ritchie, Doug McIlroy, Ken Thompson, or any of the other pioneers but my impression from afar is that they didn't believe in the perfectibility of man or software - they were beyond that trap. They saw limitations and they worked with them - they didn't over extend.

The fact that C embodies that style, is one of the things that makes it special to me. It's a style that deserves more recognition and emulation.