Coding Horror

programming and human factors

Vive la Programming Revolution!

viva le programming rvolution! Jonathan Edwards' Manifesto of the Programmer Liberation Front is an inspiring call to arms for programmers who are fed up with the status quo of Java and C#. Maybe it is time to open your window, stick your head out and yell, "I'm as mad as hell and I'm not going to take this anymore!"

Or you could just read his blog post. Here are a few highlights:

Compared to every other field of design and engineering, programming is an embarrassment and a failure. The "software crisis" has dogged us from almost the beginning. We who have made programming our life will no longer tolerate this.

Programming languages are the fundamental technology of programming. To make fundamental improvements in programming you need a fundamentally better programming language.

There is a widespread belief in both industry and academia that working on new programming languages is pointless. This is short-sighted. Historically, all sciences and technologies undergo revolutionary change. The lack of meaningful progress in the last 20 years means that there is an enormous pent-up potential for change, and the lack of interest in it means there is an enormous opportunity for the intrepid. It is a good time for a revolution.

To fully embrace adaptation as the essence of programming will require a change of attitude that is quite difficult: discarding elegant yet fragile constructions in favor of messy but flexible ones. One case in point is copy-and-paste programming. This violates all the accepted rules of modularity and hygiene, yet everyone still does it routinely. Either most programmers are stupid and evil, or the accepted rules are idealistic and impractical. The latter is the case. It is necessary to embrace copy-and-paste as a first-class "semi-modularity" mechanism in the language – to track it, manage it, and eventually refactor it into "proper" modularity. This may be heretical, yet an honest appraisal of how programmers really work requires something like it. Usability is a subversive idea.

In Science and Math, formulas are typically one-liners. Even small programs are far larger than any mathematical statement. Expression-based languages attempt to scale up formulas to hundreds or thousands of lines. One reason this does not work is that people can not easily handle more than about 2 levels of nesting. We are not stack machines! Natural languages rely on linear narrative flow and avoid deep nesting. This may be the real problem with LISP: people complain about parentheses, but they are really complaining about deep nesting.

Commercial considerations often dictate that compatibility and performance have the highest priority, with disastrous consequences (witness C++). As the Open Source movement has demonstrated, progress requires overthrowing the economics of software. We will need to go even further, freeing our minds of traditions established with the very first programming languages. Usability is the guiding light to rationally reinvent programming from scratch.

Programming is at a dead-end. The only way things will get better is with a complete revolution. More conservative attempts over the years have repeatedly failed to make a difference, leading to the widespread abandonment of hope. We have nothing to lose.

You might say it's a street corner preacher rant. But that's what makes it so good.

Discussion

Text Columns: How Long is Too Long?

Ian Griffiths recently wrote a proof of concept WPF browser for the MSDN online help. One of the improvements cited is multi-column text:

This is why WPF offers a column-based reading experience. We know from experience in the print world that breaking text into columns can make it much easier to read. Indeed, once you've got used to reading in columns, going back to the long unbroken lines offered by the standard SDK viewer feels like punishment!

Code is a highly specialized form of writing, but the same sort of questions always come up. Should we use short lines or long lines? A recent comment from Buggy Fun Bunny* describes this conundrum well:

What I've found amusing for the last 20 years is this insistence, by people who should know better, on 80 column (or less) line limits. That was invented by COBOL (which only has ~66 characters available after you subtract the line number from 73) around 1960. It's just silly. I remember how wonderful it was when the VT-220 came along and I could use 132 character lines. If nothing else, formatting a report both in code and as output was a piece of cake.

Beyond the character world, we have wide screen taking over, and folks still think that 80 columns is King. There's more horizontal real estate, and always was. Use it well.

And as to scanning narrow: not everybody does; I've had the Great Books set and can't read them because those narrow double columns drive my eyes over the edge.

Hey, I'm a Great Books fan from way back in the day. Nothing blows a seventh grader's mind quite like reading Graham Greene's The Destructors, or Carson McCuller's Sucker. No wonder people want to burn books. They're subversive.

So what's the best way to structure columns of text on a computer screen? How long is too long? Luckily, the Software Usability Research Laboratory at Wichita State has already researched – and answered – this question.

But before I reveal the answer, what do you think? Which of these passages is easier to read and comprehend?

Single column, left aligned

Alice was beginning to get very tired of sitting by her sister on the bank and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, “and what is the use of a book,” thought Alice, “without pictures or conversations?”

So she was considering, in her own mind (as well as she could, for the hot day made her feel very sleepy and stupid), whether the pleasure of making a daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly a White Rabbit with pink eyes ran close by her.

There was nothing so very remarkable in that; nor did Alice think it so very much out of the way to hear the Rabbit say to itself “Oh dear! Oh dear! I shall be too late!” (when she thought it over afterwards it occurred to her that she ought to have wondered at this, but at the time it all seemed quite natural); but, when the Rabbit actually took a watch out of its waistcoat-pocket, and looked at it, and then hurried on, Alice started to her feet, for it flashed across her mind that she had never before seen a rabbit with either a waistcoat-pocket, or a watch to take out of it, and burning with curiosity, she ran across the field after it, and was just in time to see it pop down a large rabbit-hole under the hedge.

Single column, justified

Alice was beginning to get very tired of sitting by her sister on the bank and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, “and what is the use of a book,” thought Alice, “without pictures or conversations?”

So she was considering, in her own mind (as well as she could, for the hot day made her feel very sleepy and stupid), whether the pleasure of making a daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly a White Rabbit with pink eyes ran close by her.

There was nothing so very remarkable in that; nor did Alice think it so very much out of the way to hear the Rabbit say to itself “Oh dear! Oh dear! I shall be too late!” (when she thought it over afterwards it occurred to her that she ought to have wondered at this, but at the time it all seemed quite natural); but, when the Rabbit actually took a watch out of its waistcoat-pocket, and looked at it, and then hurried on, Alice started to her feet, for it flashed across her mind that she had never before seen a rabbit with either a waistcoat-pocket, or a watch to take out of it, and burning with curiosity, she ran across the field after it, and was just in time to see it pop down a large rabbit-hole under the hedge.

Double column, left aligned

Alice was beginning to get very tired of sitting by her sister on the bank and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, “and what is the use of a book,” thought Alice, “without pictures or conversations?”

So she was considering, in her own mind (as well as she could, for the hot day made her feel very sleepy and stupid), whether the pleasure of making a daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly a White Rabbit with pink eyes ran close by her.

There was nothing so very remarkable in that; nor did Alice think it so very much out of the way to hear the Rabbit say to itself “Oh dear! Oh dear! I shall be too late!” (when she thought it over afterwards it occurred to her that she ought to have wondered at this, but at the time it all seemed quite natural); but, when the Rabbit actually took a watch out of its waistcoat-pocket, and looked at it, and then hurried on, Alice started to her feet, for it flashed across her mind that she had never before seen a rabbit with either a waistcoat-pocket, or a watch to take out of it, and burning with curiosity, she ran across the field after it, and was just in time to see it pop down a large rabbit-hole under the hedge.

Double column, justified

Alice was beginning to get very tired of sitting by her sister on the bank and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, “and what is the use of a book,” thought Alice, “without pictures or conversations?”

So she was considering, in her own mind (as well as she could, for the hot day made her feel very sleepy and stupid), whether the pleasure of making a daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly a White Rabbit with pink eyes ran close by her.

There was nothing so very remarkable in that; nor did Alice think it so very much out of the way to hear the Rabbit say to itself “Oh dear! Oh dear! I shall be too late!” (when she thought it over afterwards it occurred to her that she ought to have wondered at this, but at the time it all seemed quite natural); but, when the Rabbit actually took a watch out of its waistcoat-pocket, and looked at it, and then hurried on, Alice started to her feet, for it flashed across her mind that she had never before seen a rabbit with either a waistcoat-pocket, or a watch to take out of it, and burning with curiosity, she ran across the field after it, and was just in time to see it pop down a large rabbit-hole under the hedge.

The answer is more complex than you might think. The SURL paper first summarizes past findings of previous research:

  • Longer line lengths generally facilitate faster reading speeds.
  • Shorter line lengths result in increased comprehension.
  • The optimal number of characters per line is between 45 and 65.
  • Paging through online text generally results in better comprehension than scrolling.
  • Reading speed is faster for both single and multiple columns, but preference is for multiple short columns.
  • Left-justified text is read faster than full-justified text.

And here's what they found in their study:

reading speed results graph

The results of this study suggest that there is not one best way to present text online. Although fast readers performed best at the two-column full-justified condition, slow readers benefited from a single column non-justified layout.

Personally, I was surprised that justification had such a strong influence on the results. Simply breaking up text into columns actually hurts reading speed noticeably for both slow and fast readers. However, if you fully justify the columns, then – and only then – reading speed increases dramatically for everyone. And clearly, three column layouts aren't worth it, no matter how you align the text.

So what conclusion can we draw for coders? Probably not much. Code is always left aligned, and in a single column. A related SURL study examines the effect of line length alone which might be more relevant:

This study examined the effects of line length on reading performance. Reading rates were found to be fastest at 95 cpl. Readers reported either liking or disliking the extreme line lengths (35 cpl, 95 cpl). Those that liked the 35 cpl indicated that the short line length facilitated "faster" reading and was easier because it required less eye movement. Those that liked the 95 cpl stated that they liked having more information on a page at one time. Although some participants reported that they felt like they were reading faster at 35 cpl, this condition actually resulted in the slowest reading speed.

Furthermore, line length had no effect on comprehension. Although I'm hesitant to draw broad parallels between source code and a news article, perhaps arbitrarily short lines aren't always necessary in source code to achieve good readability and comprehension.

* I just write this stuff down. I don't make it up.

Discussion

When Object-Oriented Rendering is Too Much Code

Let's say you wanted to generate and render this XML fragment:

<status code="1" />
<data>
<usergroup id="usr" />
</data>

Here's a fully object-oriented way of building it:

System.Text.StringBuilder sb = new System.Text.StringBuilder();
XmlWriterSettings xs = new XmlWriterSettings();
xs.ConformanceLevel = ConformanceLevel.Fragment;
xs.Indent = true;
XmlWriter xw = XmlWriter.Create(sb, xs);
xw.WriteStartElement("status");
xw.WriteAttributeString("code", "1");
xw.WriteEndElement();
xw.WriteStartElement("data");
xw.WriteStartElement("usergroup");
xw.WriteAttributeString("id", "usr");
xw.WriteEndElement();
xw.WriteEndElement();
xw.Flush();
return sb.ToString();

That seems like a tremendous amount of code to do something relatively simple. I could abandon the pure object approach and do it in two lines of code:

string s =
@"<status code=""{0}"" />
<data>
<usergroup id=""{1}"" />
</data>";
return String.Format(s, "1", "usr");

It's far less code. And it's much easier to read!

I've worked with developers who insisted that everything had to be generated through an object model, even if the object-oriented way required many times the amount of code. Although I haven't worked with Daniel Cazzulino, he typifies this attitude:

If you're using Response.Write, you're a dreadful citizen of the ASP.NET world.

As my friend Victor said, "Response.Write is there just for compatibility reasons and for old script programmers to not feel lonely".

An app written in such a way will not only be difficult to maintain and evolve, it will be almost impossible to customize (specially its layout), will never catch up with the upcoming mobile features and just hurts the eye. Everytime I see a Response.Write, and specially if it's not even kind enough to use HtmlTextWriterTag, HtmlTextWriterAttribute and HtmlTextWriterStyle, the developer who wrote it is instantly removed from my in-memory list of good ASP.NET programmers.

Like Rick Strahl, I'm not convinced the verbosity of objects like HtmlTextWriter and XmlTextWriter are warranted.

The idea of "write once, run anywhere" via a complex set of objects and adapters is a pleasant one, but it also adds a heavy burden of verbosity and complexity to your project. And you probably aren't gonna need it anyway. Sometimes it's simpler and clearer to render the HTML or XML directly to the page without all that OO cruft gunking up the works.

Discussion

Is Writing More Important Than Programming?

The unofficial wikipedia blog entry The Future of Open Source Five Years Ago makes some fascinating comparisons between the adoption rate of Linux and the adoption rate of Wikipedia.

Server-side Linux is still a powerful force, but what happened to the desktop utopia that was supposed to unseat Windows? And will the same developed-world disenchantment hit Wikipedia as it grows?

While in principle anyone can contribute to an open source project, Linux's barriers to entry are higher than Wikipedia's. Even correcting minor Linux bugs is well beyond my expertise, but my grandmother could edit Wikipedia. All you need is an internet connection and literacy (mid-level literacy, at that; other people will fix your grammar and spelling).

Wikipedia can draw on half a billion potential contributors; only about 100,000 people can code Linux.

It's hard to overstate this difference.

To illustrate this point, it's accompanied by an amusing graph.

Wikipedia vs. Linux user base, small version

I've resized the graph to a more manageable size. Click through to see it full size. The writing on the bars is hard to make out. On the left, it's..

Number of programmers who can contribute to Linux, including minor bugfixes.

And on the right?

Number of people in the world who speak English well enough to edit Wikipedia and who have access to the internet. (This includes non-native speakers. It omits potential contributors to non English-language wikipedias only because this bar is already absurdly tall. (Okay, and because wikipedias of seperate languages are, to some degree, islands, and don't function as a cohesive whole.))

It's probably not fair to compare programming and writing in this manner, but I am reminded again of Joel Spolsky's classic advice for computer science college students:

The difference between a tolerable programmer and a great programmer is not how many programming languages they know, and it's not whether they prefer Python or Java. It's whether they can communicate their ideas. By persuading other people, they get leverage. By writing clear comments and technical specs, they let other programmers understand their code, which means other programmers can use and work with their code instead of rewriting it. Absent this, their code is worthless. By writing clear technical documentation for end users, they allow people to figure out what their code is supposed to do, which is the only way those users can see the value in their code. There's a lot of wonderful, useful code buried on sourceforge somewhere that nobody uses because it was created by programmers who don't write very well (or don't write at all), and so nobody knows what they've done and their brilliant code languishes.

Programming, like all writing, is just another form of communication. Writing code that the compiler understands is easy. Writing code that other people understand is far more difficult. And that's assuming you're persuasive enough to convince other people that your code, in a world positively overflowing with free code, is worth looking at in the first place.

Good luck. You're gonna need it.

Over the next few years, Wikipedia (and some of its Wikimedia sister sites) will become comparable to Linux in economic and social significance. Maybe Linux will catch up again a few decades later, if schools start teaching as many kids to program as they teach to write.

This quote was originally written in August 2005. I'd argue that Wikipedia was already more significant to the average internet user than Linux at that time. Now there's no question.

Technical programming skills are certainly important. But general writing and communication skills are far, far more important. Even if you're merely a humble programmer.

Discussion

Pretty Code, Ugly Code

Christopher Seiwald's Seven Pillars of Pretty Code argues that code that looks good, works good:

  1. Code changes should blend in with the original style.

    It should not be possible to discern previous changes to a file without seeing the previous revisions. Nothing obscures the essential visual cues more than a shift in style. This practice should be applied as wide as possible: absolutely within functions, generally within a file, and if you're lucky across the system.

  2. Keep columns narrow.

    Just as with books and magazines, code should be narrow to focus the gaze. As I mention in "Overcome Indentation," the left edge of the code holds the structure and the right side holds the detail, and big long lines mix zones of structure and detail, confusing the reader.

  3. Break code into logical blocks so that each does a single thing or single kind of thing.

    This principle should apply within functions, and in a larger sense, among separate code blocks. A reader can only avoid a total reading if a cursory inspection can reveal the whole block's nature.

  4. Set off code blocks with whitespace and comments that describe each block.

    Comments should rephrase what happens in the block, not be a literal translation into English. Even if your code is inscrutable and your comments jibberish, the reader can at least attempt to triangulate on the actual purpose.

  5. Reduce, reduce, reduce. Remove anything that will distract the reader.

    Use short names (like i, x) for variables with a short, local scope or ubiquitous names. Use medium length for member names. Use longer names only for global scope (like distant or OS interfaces). The tighter the scope, the shorter the name. Long, descriptive names may help the first time reader but hinder him every time thereafter.

  6. Two or more pieces of code that do the same or similar thing should be made to look the same.

    Nothing speeds the reader along better than seeing a pattern. These similar looking pieces of code should be lined up one after the other. Grouping reduces the number of entities the reader has to grasp, a critical approach to simplifying the apparent complexity of code.

  7. The left edge of the code defines its structure, while the right side holds the detail.

    You must fight indentation to safeguard this property. Code which moves too quickly from left to right (and back again) mixes major control flow with minor detail. Forcibly align the main flow of control down the left side, with one level of indentation for if/while/for/do/switch statements. Use break, continue, return, even 'goto' to coerce the code into left-side alignment. Rearrange conditionals so that the block with the quickest exit comes first, and then return (or break, or continue) so that the other leg can continue at the same indentation level.

It's an entirely reasonable set of advice. Until you realize that Christopher is using his very own jam/make.c as a shining example of the pillars of pretty code.

And make.c is extremely ugly to me.

I don't know if I'd ever consider C code pretty, per se. Maybe it has a nice personality. But pretty? No way. And I'm sure Ruby, Lisp, and Smalltalk aficionados feel the same way about C# code. I know most C# developers can barely force themselves to even look at VB.NET code.

Clearly, pretty code is in the eye of the beholder.

Besides the fact that it's C, I have a few other problems with Mr. Seiwald's make.c code:

  • It embeds source control information in the comments. Isn't this why we have source control systems?
  • It uses complex, difficult to maintain block alignments in the comments, variables, and function declarations. Unless your IDE does this for you, this is the formatting equivalent of a house of cards.
  • There are functions named make and make0. Ouch.

The code formatting, as promised, is pretty. But the emphasis on formatting does make me wonder-- rather than focusing on the external, cosmetic attributes of the code, shouldn't we be searching for something prettier on the inside? Such as a higher level language?

Discussion