25 Apr
2010

If Self-Documenting Code is the What, Unit Tests are the Why

It is not enough to just write code that is clean and self-documenting.? Eliminating comments and replacing them with clear variable and method names, will tell the reader of your code clearly what it is doing, but it will not properly express why it is doing it.

If you recall from my original post on Elegant code, I stated that elegant code is:

Something that is simple yet effective, delivered with grace.

By writing self-documenting code we are hopefully able to achieve some of the aspects of simplicity and grace, but it tells us nothing about the effectiveness of the code.

Bringing the dead to life

zombies

Throwing out comments is a debatable topic.? It raises quite a bit of controversy, as you can see from some of the comments on my post about the subject.? The reason, perhaps, that so many people are so staunchly opposed to the idea, is because they are worried, and rightly so, that throwing out comments will reduce the documentation of what the code is doing.

Think about that for a second.? Is documentation of what the code is doing important?? It better be.? What we are trying to accomplish by writing self-documenting code instead of comments, is to take the vessel, which is the code itself, and make that same vessel be the documentation of what the code does.? It is by doing this that we creating a living representation of the functionality of the code.? Comments are akin to a dead representation of the functionality of the code because they do not change automatically with the code.

I diverge to talk about comments so that I can draw a parallel to another form of documentation which is valuable and should be considered necessary.? That other set of documentation is requirements.? Have you ever written requirements documents?? Have you ever captured requirements from the customer and put them into UML diagrams, or perhaps plopped them into some templated Word document, which is never updated again, and no one reads, because no one trusts it is correct?? Wouldn?t it be great if we would replace that dead document or set of documents, with a living one?

The good news is we can, and some of us have.? And I fully expect this recommendation will be just as controversial, because I am suggesting that we don?t have to write low level specifications of the system at all, instead we can write good unit tests. When we do this, we are taking a dead form of document and bringing it to life.

Unit tests tell us why and how our code is effective

If

i = 5;  // Widget count defaults to five.

is replaced with

widgetCount = DEFAULT_WIDGET_COUNT;

then

1.1.5 When a new widget is created, the widget count should be increased by one.

is replaced with

public void When_NewWidgetIsCreated_Then_WidgetCountIsIncreasedByOne()
{
     WidgetFactory.Count = 3;
     WidgetFactory.CreateNew();
     assertEquals(4, WidgetFactory.Count);
}

The unit test is replacing the low level requirement, which is somewhat open to interpretation and untied to the code, with an absolute and completely tied-to-the-code, specific requirement.

The unit test is telling us why our code is built the way it is.? It is telling us what requirement that particular structure of code is trying to address.? It is telling us what end result that code is trying to accomplish and what the expectations are on the results of a given condition.

The unit test is telling us how the code is to be used in order to achieve its result.? It is serving as a living reference to the syntax and use of the code we built.? Instead of providing instructions on how to use our API, we are providing a living example, and proof that it will indeed work. Examples are often much more effective than instructions anyway.

What exactly are we replacing?

At this point we are not trying to replace all the documentation of the system (at this point).

With self-documenting code, we sought to eliminate comments, and replace them with good variable and method names.

With unit tests, we seek to eliminate technical documentation and requirements of the system, that is targeted at a developer or technical audience.

We are NOT trying to eliminate high level specifications of the system, or use cases. Unit tests DO NOT replace that kind of documentation! We will talk about replacing that kind of documentation when we talk about automated functional or system tests.

Simply put, any kind of documentation that you would give to a developer so they understand how the system works and how to use the code or APIs, can be easily replaced by writing good unit tests.

Our simple goal is to replace the ?dead? documentation (meaning that it does not update automatically with the thing it is documenting), with ?living? documentation in the form of unit tests.

One last point.? I want to be clear that I am not saying that having unit tests automatically results in the ability to replace technical documentation.? Just like having long-named methods and variables doesn?t automatically replace the need for comments.? It is a matter of the quality of the unit tests that are written, just as it is a matter of the quality of the self-documenting code.

As always, you can subscribe to this RSS feed to follow my posts on elegant code.? Feel free to check out my main personal blog at http://simpleprogrammer.com, which has a wider range of posts, updated 2-3 times a week.? Also, you can follow me on twitter here.

6 thoughts on “If Self-Documenting Code is the What, Unit Tests are the Why

  1. Interesting and I fully agree. But on the other hand, I should say 90% (or more) of the programmers have not read about “clean code”(the book), nor even they heard about removing comments. I personally know some ones who is still writing codes like:
    // fix bug ticket XXXX start
    some code
    // fix bug ticket XXXX end

    so how do we handle them? Normally if there is just one guy like this in a team, then everything will be polluted sooner or later.

  2. That’s a signature old-school development style, pre-VCS. I’ve had to ween several developers out of the habit of commenting change history, or worse, commenting out old, replaced code when they’re using a perfectly good code repository. The comments about why something was changed are best served as comments in the change log. A simple diff says a hell of a lot more about “what” changed than any comment could.

    The best way to break this habbit is to show them something better. Demonstrate how meaningful comments in Subversion or TFS change history say how code is evolving ever so much more clearly than a comment in code. Of course, if everyone else *isn’t* writing meaningful check-in comments then you’re up a crik without a piddle.

  3. @tcmaster
    Thanks for your comments mate, however I think that you are barking up the wrong tree, if you are using a case tool or some other design tool to design your system then this is the place to put your serious comments in that will clarify your design to the developer, comments in text boxes, assocations, aggregations etc in UML diagrams are very important to give a developer a quick description of your ideas.
    Other comments in code can be useful where you think this will clarify the code, after all this is implementation detail that can be very cryptic. I am rather suspicious of people who want to get rid of things that normal people normally do, this sounds like some sort of religious fundamentalism. Here is an example, what about a truth table, if this is in the design then I would expect to see this as a comment in the code.
    Regards,
    Alistair

Comments are closed.