Clean Code, A review

legit | 20 February 2010

A few months ago I was working on some code that someone else had written. I was trying to add a feature into a class and couldn’t seem to figure out how the class worked, and thus couldn’t figure out where or how to implement my addition. After reviewing the code for a while I started to understand what was going on in the code and had a good enough understanding of it to then implement my new feature. The problem was since I then understood what the code was doing and how it worked I also felt compelled to restructure it, perhaps in a more logical order, or just change it so that it would be easier to understand later on. My problem was that after thinking about a new way to structure that class I wasn’t really certain about why that would be a better alternative, it just seemed better. So after wondering why it seemed like a good idea I decided to do some research into how to write “better” code, and why “better” code is “better”. My research ended pretty quickly as I remembered a few of my workmates talking about the book “Clean Code” a while back and how it discussed what makes “better” code. So I went to my local bookstore, picked up a copy, and started reading it.

Clean Code: A Handbook of Agile Software Craftsmanship was written by Robert C. Martin who has previously published books (which I have not read) on software engineering. He opens up Clean Code with the classic “WTF” comic of software quality, you know, the one that describes good code as code that produces the least “WTF’s per minute”. This is a really good example, since, that is exactly the kind of experience that got me to pick up the book. Martins purpose for the book is to present ideas on how to clean up code, and reduce the “WTF’s/Minute”, and make it easier for others and you to understand and modify later on. The first thing that Martin discusses is the problem of bad code, what it is, how it happens, and what the long term results are (maintenance, lots of maintenance). He then quickly transitions into a discussion of what clean code is, he asked several senior and well recognized software engineers what clean code is, and then lists their responses to get things started. After a brief overview of what clean code is, its off to the races, in depth analysis of clean code techniques and plenty of code examples to go along with it.

By far this book is not a quick read, or at least it shouldn’t be, most of the code examples that Martin gives are given first in the difficult code to understand context and then cleaned up into a clean code example. This method of actually showing the before and after code samples, if actually read and understood, gives immense meaning to the ideas that Martin gives on how to produce clean code. That being said, it is because of these code samples that this book is a bit of a slower read. Martin also encourages his readers to take the time to understand the code changes, warning that by not doing so you will miss out on the real understanding of why these code changes are occurring.

Martin begins the clean code concepts with fairly cosmetic issues, naming conventions, class and method sizes, comments, and formatting. These issues are fairly light on the technical scale (with class and method sizes being a bit more difficult) however, Martin does a good job of showing the benefits of implementing these clean code concepts. Then Martin goes into a discussion of more technical issues, error handling, objects and data structures, crosscutting concerns, system wide organization, testing, and even some discussion of concurrent programming. All the while he discusses not only good principles but why they are good principles, and gives examples of how to apply them. On some issues Martin admits controversy surrounding issues and clarifies why he came to his conclusion, as well as what others think. Martin then finishes the book with three chapters which take entire classes from well know API’s and dissects them into better, cleaner code, using the principles previously discussed in the book. These sections, as Martin states, are necessarily slower to read, given the large amounts of code and the complex changes. However, by slowly reading through them and understanding the changes being made it helps to bring together all the concepts of the book and shows how large sections of code can be understood and cleaned.

In the end of the book are several appendices, one is an in depth chapter long analysis of some concurrent clean code concepts, which an excellent discussion of what makes concurrent code difficult to debug and how to clean it up. There is also an appendix that cross references the principles of clean coding with the code transformations made in the last three chapters of the book. This appendix makes the book a great reference to keep on the shelf after reading it.

Overall the book is incredibly helpful, especially to software engineers who are earlier in their career (such as I). Held within the book are many useful techniques that senior engineers have taken a long time to hone, and if you read and absorb the concepts I think everyone can learn something from the book. That being said, several of the concepts that Martin discusses are controversial. His opinion that comments are unnecessary if the code is well organized and named, and in general clean, is definitely something that could be hard to swallow (depending on your stance with commenting). Martin isn’t completely against comments though, just unnecessary comments (he still supports comments in API’s). One of Martins main arguments against comments is that they simply produce one more thing that has to be maintained later on, a valid point. But despite the few controversial ideas that Martin discusses, none of which does he force on you, the book is filled with many highly useful concepts and excellent descriptions of why they are good ideas.

In the end I really only had one major complaint about the book, which is the subtitle “A Handbook of Agile Software Craftsmanship”. It is my opinion that clean code can and should be produced in non-agile environments as well, which I don’t think Martin would disagree with. Clean code is by far easier to modify than unclean code, and so its applicability may be higher within an agile environment, but it is certainly still applicable in non-agile environments (where the requirements are more static). My favorite concept of the book is also in the title, the idea of software engineering as a craft, too much of the time it seems that software engineering is seen as “coding”. The idea that software engineering is just hacking up something that does what your manager asked for is outdated and I think this book gives a nice introduction to software engineering as a true craft that should be treated with care and responsibility. Instead of just writing code, we as software engineers should write code that is of high quality, something that is truly well-crafted.

After reading the book my coding style has changed, I try to write clean code the first time, instead of just getting it to work. I also have a better understanding of why certain coding changes are better than others, which is why I picked up the book in the first place, so it fulfilled my needs and then some. I highly recommend it for anyone that is doing any programming.

Next on the bookshelf is “Data Visualization: Principles and Practice” by Alexandru C. Telea.

The Zune Bug and the if/else Statement

legit | 12 January 2009

For those that haven’t heard, the Microsoft Zune’s OS recently ran into trouble relating to 2008 being a leap year.  The Operating System got stuck and was unable to operate for an entire day due to a bug in the code, thankfully without a patch the Zune started right back up the next day happy as ever.

Over at “Freedom to Tinker” they wrote up a nice overview of the bug (including code):

On December 31, some models of the Zune, Microsoft’s portable music player, went dark. The devices were unusable until the following day. Failures like this are sometimes caused by complex chains of mishaps, but this particular one is due to a single programming error that is reasonably easy to understand. Let’s take a look.

Here is the offending code…

Read the full post here “Debugging the Zune Blackout“.  This particular bug represents the problem of not covering all of the cases involved in a particular if/else; in this case the else was left out.  The problem could have been solved by breaking out of the while when it was a leap year but not over 366 days.

This reminded me of the Gaurded Command Language(PDF) written by Dijkstra in 1975 (wikipedia article).  In this theoretical language Dijkstra presented the If statement with a unique twist.  The if statement consisted of several boolean conditions and their subsequent code to be executed.  So for a very simple example:

if
  if A then AX
  if B then BY
  if C then CZ
fi

The twist comes on evaluation of the if statement, unlike most modern languages (I don’t know of any that aren’t like this) in which when none of the statements in an if/else are evaluated to true the program simply continues executing, Dijkstra’s Guarded Command Language was different.  Three basic rules existed for the if statement:

1. All of the boolean conditions are evaluated.
2. If one or more are true then one (and only one) is arbitrarily chosen to be executed.
3. If however, none of the boolean conditions are true the program aborts (crashes).

This is certainly much more strict than modern languages, thankfully, but it presents the nice idea that unless all of the cases of a given circumstance are covered then the program will not be capable of continuing.  Furthermore by preventing the continuation of the program when no true conditions exist the language makes it easier to debug because the problem does not cascade down into some other section of code but rather crashes exactly where the problem originates (the if).

On a more philosophical level the Guarded Command Language deals with if’s in this way:  When a child is asked by their mother if they want an ice cream cone and the mother only expects the answers ‘yes’ or ‘no’ then the mother is ill-equipped to deal with the scenario that the child may say ‘later’.  Granted we humans are smart and can on the fly deal with situations like this (ie. the mother wouldn’t “crash”) it presents the problem that when dealing with programming in a highly logical environment the fact that when not all possible answers to a problem exist it means that something is not being dealt with, which can cascade down into other problems.

The Zune bug presents a nice example of this, and while it is fairly small its an interesting and yet important issue involved in programming.