Published on ThoughtShapes (http://thoughtshapes.com) © ThoughtShapes, Inc.

TDD and Comments

By Steve Seymour
Created 12/31/2006 - 12:00am

Man, this is a particularly sensitive topic to me, I must admit. That's mostly because "you must comment all your code" is usually a directive that comes from one of three kinds of people--each non-exclusive of the other:

  1. Someone who was a "developer" at one time but has now "moved up the ladder" and is controlling an aspect of your career they should not have control over. Do you think Major League Baseball is filled with ex-player managers that force their talented shortstop to field a ground ball a certain way? Can you imagine Whitey Herzog telling Ozzie Smith [1], "You're doing it all wrong, Oz!"
  2. Someone who has great intention but doesn't understand OO and therefore is misguided in their attempt to do something good. Such a person attempts to lay down the comment rule with the intention of creating a great project, so it's hard to get upset with him (although suffering through this time-and-time again decreases your capacity for tolerance). This is analogous to a father forcing his son to follow some "fundamental" of a sport, without the father having any true experience in doing what he prescribes. "Son, you should always practice with weights tied around your ankles," the father says, only to eventually observe his son with bad knees and hips at the age of 16. Yeah, good ol' dad had good intentions, but he clearly took control over something he never really understood.
  3. Someone who, at most, fooled around with automated tests--but either were never good enough to get them right or never had the drive to excel at them. In my personal experience, the people I know that excel at unit testing are people that excel at other aspects of their lives and have learned how to get over the initial pain of learning something difficult to master.

When I say, "The code is the documentation," people take that way too literally. This statement does not mean there isn't a hint of comments in the system; sure, I use comments here and there, but only where there is a reason to do so. For instance, if I code a method that is called "Add" and it really subtracts the two arguments passed to it, I'll write a comment saying that's what it does. On the other hand, if I've coded such a method I should seriously consider giving software development up, no?

Okay, so what if my "Add" method has two parameters of type "Number" (a non-primitive type)? Do I need to add a comment saying that it adds the two numbers? Do I need to add a comment saying that ikf one of the arguments is null it will throw a null reference exception? Just as I don't want to see ultra-wordy sentences when reading a book, I don't want to see useless comments when reading source code.

Even if you still aren't with me, my main argument against writing comments is that--yep, you guessed it--the tests reveal a lot more about the code than any comments do. I'd like to rephrase the original, tattered phrase to "The code and the tests are the documentation." I'd also like to mention that like all rules, this isn't completely written in stone. If you're a junior developer--or even a senior one that writes hard-to-follow code--then perhaps you should be writing more comments to help those that have to deal with your code. On the other hand, who the hell is this honest about their own skill? And, if you're going to be spending time doing anything, I'd much rather see you devoting it toward 100% code coverage.

Here are some basic guidelines to eliminate the need for comments:

  1. Write tests, and come as close to 100% code coverage [1] as possible.
  2. Of all patterns and principles I can think of, the most important contributor to minimizing comments is SRP [2]. This is because if you follow this principle it keeps class responsibilities very easy to understand (not to mention keeping the implementation very easy to change).
  3. Use objects all the time. Don't pass primitives all over the place, to be consumed by some huge algorithm that has gnarly if/else logic scattered throughout. Pass objects to objects, and then segregate responsibility to these objects and others.
  4. Chop algorithms into neat, concise, appropriately named methods.

I foraged around the 'Net and found this feisty post written by someone at Slashdot.org [3]:

Yeah, the code is the documentation and the requirements and the business definition. Of-course it is if you have nothing else. That's what it becomes if noone bothers to update the docs.

Let me tell you something about that. I have worked on way too many projects (including the current one) where this was the case - there was only code, or the docs were so out of date that really, there was only the code. It's horrific in most cases. Certainly there are horror levels but I am serious, it is just freaky.

Do you know what happens to a project without documentation? Let me tell you what happens: the only way someone can maintain it, given strict deadlines and/or budget constraints is by fixing the bugs without actually understanding the design. So your fix becomes just a special rule for a special case and in the worst scenario it is also a fix that only works for a special kind of data. So what happens at the end with such a project? A 30 year old COBOL program situation - too many rules that are not generalized all over the place with all kinds of side-effects. Good luck supporting that shit.

I will take a high level document describing the system any time instead of jumping into the code right away. I prefer to know the components of the system, the main players, where the configurations are, what patterns are used to develop the system before jumping into the code. It is just too damn bad that it does never happen that way.

Let's imagine that I had tests in place for the entire system this person above describes. If I did, I claim that all his thoughts are no longer valid:

  1. there was only code, or the docs were so out of date that really, there was only code. Yeah, so what? Go look at the tests dummy!
  2. His entire third paragraph rings hollow because the tests will tell him what the code does and will provide him with automated regression testing.
  3. I prefer to know the components of the system, the main players, where the configurations are, what patters are used to develop the system before jumping into the code. What's my answer to this? Yep, go look at the tests! Why are you complaining to me before you looked at the tests?

Another important point to think about is who you are building the software for. If you are building it for a client that is paying you to build a product for them, you better ask them if they want documentation. If they say yes, then you better include it in your project plan and have them sign off on it because anything in the plan is technically a risk of some sort. I'd argue that the documentation is always near the bottom of the totem-pole in terms of deliverable-value, but it's really the client's call. I'll do my best to educate them, though, so they can make what I consider an informed decision.


Source URL:
http://thoughtshapes.com/TDD/Comments.htm