Delimiter Collision

Clean(er) Code

Who Made This Mess?

"Clean Code" by Robert C. Martin -- a.k.a. "Uncle Bob" -- is part of the canon of essential programming books. There is no shortage of posts summarizing its points or debating its merits. Yet few seem to focus on the book's core underlying principle: that we are responsible for the quality of our code.

This seems obvious on its face, and perhaps that's why it seems to get glossed over. But on page 5, Martin goes on at some length to underscore this point. Here's an excerpt:

Why does good code rot so quickly into bad code? We have lots of explanations for it. We complain that the requirements changed in ways that thwart the original design. We bemoan the schedules that were too tight to do things right. We blather about stupid managers and intolerant customers and useless marketing types and telephone sanitizers. But the fault, dear Dilbert, is not in our stars, but in ourselves. We are unprofessional.

This, the author acknowledges, may be a "bitter pill to swallow." And indeed it is. But Martin argues that it is our job to defend the quality of the code with equal zeal to how managers defend the timeline and requirements. (I'd recommend reading the rest of the chapter on this, which you can find here.)

Embracing this notion of professional responsibility as a software engineer has helped me grow, and prompted me to change my thinking about how to work even in the face of pressure.

Just Ship It?

Several years ago, I was pulled into a project with a timeline that might have generously been called "aspirational." Nevertheless, my team and I moved quickly, and we delivered the system in time to meet the launch deadlines. But while a fair amount of thought went into design, along the way I made decisions and compromises that I have been paying for with longer development cycles since.

The biggest mistake I made was in failing to keep the system cohesive. Functionality was duplicated with slight alterations, rather than cleanly extended, to accommodate evolving requirements. I engaged in speculative engineering in an attempt to get out ahead of things, violating another principle Martin mentions in the book, "You aren't gonna need it".

Some would argue that I did exactly what I was supposed to do -- got things running, and on time. In fact, that's the accepted answer in an old Stack Overflow post asking about a programmer's responsibility to write clean code:

I would argue that many of us do not write clean code. And generally, that's not our job. Our job as software developers is to deliver a product that works, on time.

The author of that reply cited heavily from a blog post in 2009 (the same year Martin's book was published) titled "The Duct Tape Programmer" that praised this ethos, while also bashing certain technologies and approaches derided as over-complicated.

Uncle Bob wrote a pretty thorough and good-natured response (if you read into the comments, some thought he was being too nice).

I want you to ship, but I don’t want you to ship shit.

If you think I’m contradicting myself, you’re wrong. There is no contradiction in the notion that you must ship, and that you must be proud of what you ship.

Thinking About Messy Code

It can be hard for people who have never written a program to visualize what "messy code" looks like. They may imagine symbols and numbers strewn about in a file like some inscrutable spell that, somehow, works like magic.

A better analogy, I think, is a piece of writing. Two very different documents may technically have all the same information. One is disorganized, has spelling errors, uneven spacing, and incorrect punctuation; the other, meanwhile, is well-structured, polished, and cohesive. The latter could be the start of something larger, perhaps a book. Nobody who is a professional writer would suggest that you should "just ship" the former one to your editor or reviewer.

Rob Pike -- one of the creators of the Go programming language, among other things -- wrote this in his 1989 article, "Notes on Programming in C"

A program is a sort of publication. It's meant to be read by the programmer, another programmer (perhaps yourself a few days, weeks or years later), and lastly a machine. The machine doesn't care how pretty the program is - if the program compiles, the machine's happy - but people do, and they should.

[...] Say what you want to say in the program, neatly and consistently. Then move on.

Pike was chiefly addressing the issue of typography in printed source code; this was well before the days of technicolor rainbow syntax highlighting. But his point was that pretty printers, decorations, and banners in source code wouldn't hide a badly written program.

Second Drafts

Better writing comes through revision. Similarly, a program improves through refactoring and continuous improvement. It is easy for programmers to rush to being "done" when the thing is running.

This is an idea that Martin endorses explicitly, in Chapter 14, "Successive Refinement."

If we have learned anything over the last couple of decades, it is that programming is a craft more than it is a science. To write clean code, you must first write dirty code and then clean it.

This should not be a surprise to you. We learned this truth in grade school when teachers tried (usually in vain) to get us to write rough drafts of our compositions. The process, they told us, was that we should write a rough draft, then a second draft, then several subsequent drafts until we had our final version.

With code, and version control, it is never too late to change. In recent months, I have been bringing Martin's attitude to bear in re-evaluating aspects of the system that I wrote in the rush of that project, years ago. The system is still running, but has evolved clunkily. We can do better.

In a similar vein, it has become clear to me that what makes a code good is not how well it meets the original specification, but how easy it is to change. Code that is brittle -- because we no longer understand how it fits together, or perhaps never understood in the first place -- becomes a hole from which we may never dig out.

Toward the end of his book, Martin writes that what he hopes readers will internalize is not simply a set of rules for writing code, but a "value system" for how to approach the work -- one that emphasizes professionalism and craftsmanship.

We are in an age where both of those values are being devalued, perhaps ironically, by some of the world's biggest software giants. "Vibe coding" is supposedly good enough. But Martin's core principle that we must take responsibility for the code that we write has not changed. It is an empowering idea. We owe it to everyone affected by what we create, not least of all ourselves, to do the job well.