Comment-Driven Development

You’ve probably heard about Test Driven Development, a programming methodology which focusses on test cases as a framework for designing and developing code. You may also have heard of Behavior Driven Development, a more holistic approach which focusses on the behavior of an application before and during the development process.

Well let me tell you about my programming methodology — Comment Driven Development. Start by writing a comment, in plain language, that explains what a piece of code is supposed to do, and why. Then write the code.

Sometimes this is the most direct way to approach a problem; if it’s easy to explain but difficult to express in logic, the internal discourse you get from writing it down in this way can help clarify your thinking towards a logical solution. Conversely, sometimes it’s easy to write the code but much harder to explain it; in that case writing the comment can help you clarify the purpose of the code in such a way as to make it explainable to other people. The act of writing the comment is like a pre-cursor to documentation.

And indeed, there are times when I’m writing a comment and I find that my thinking on the code in question changes. Because the explanation sounds ridiculous, or because I have to explain a flaw or undesirable compromise. The act of explaining it to someone else — which is what a good comment should do — helps you to better understand it yourself, and sometimes that leads to changing or scrapping it entirely.

When I was writing my accessible drag and drop script, dbx, there were several occassions where I simply couldn’t work out what to do next — how to express in logic the behavior that looked and felt right. So I took to this technique, by beginning with an explanation:

//if - the direction of movement is positive; and
//	clone left/top plus clone width/height is greater than box left/top; and
//	clone left/top is less than box left/top
//or - the direction of movement is negative; and
//	clone left/top is less than box left/top; and
//	clone left/top plus clone width/height is greater than box left/top

Once I had that, it was simply a case of writing the code to implement what I’d explained:

if
(
	(this.positive
		&& cloneprops.xy + cloneprops.wh > boxprops.xy
		&& cloneprops.xy < boxprops.xy)
	||
	(!this.positive
		&& cloneprops.xy < boxprops.xy
		&& cloneprops.xy + cloneprops.wh > boxprops.xy)
)

Conversely, there were situations where I knew immediately what code to write, but I also knew that I’d quickly forget what it was for:

var sibling = dbx.getSiblingBox(this.box, 'nextSibling');
if(this.box == sibling || this.boxes[i] == sibling) { return; }

So in comes a comment to spell it out:

//look for a next sibling of this box
//and don't continue if there isn't one,
//or it's the same as the box we're inserting before
//so that we're not doing an action that would result in no change
//this filtering improves efficiency generally,
//and is necessary specifically to stabilize the animation
//otherwise the multiple unecessary calls would overload the animation timers
//and the result would be snap movement with no apparent transition

I’ve learnt the hard way how frustrating it is to come back on a script after time, only to have no clue how it works. Have a look at this example, for a chess analysis script I wrote many years ago:

sqR=new Array(vmr,vmr);
for(j=0;j<sqid[vmr][1];j++){
	if(sqid[(vmr-1)]&&(sqid[vmr][1]-sqid[(vmr-1)][1]==1)){
		sqR[2]=vmr-1;
		com(vmn,sqR[2]);
		}
	if(sqid[(vmr-9)]&&(sqid[vmr][1]-sqid[(vmr-9)][1]==1&&sqid[vmr][0]-sqid[(vmr-9)][0]==1)){
		sqR[3]=vmr-9;
		com(vmn,sqR[3]);
		}
	}

Don’t ask me what it’s doing — I have no idea!

So now I comment like it’s going out of fashion, with at least one line of comment for every line of code, and typically two or three. Sometimes my comments are mini-epics, like this monster:

/*
use offleft positioning instead of display/visibility,
so that the menus are still accessible to screenreaders
the height and overflow:scroll is to reduce the amount of rendered output,
which speeds up the onload process
(using clip or overflow:hidden would also hide them from screenreaders)
but there are rendering or positioning problems
in mac/ie5, old gecko and opera < 7.5
in fact it screws up opera 7.23 completely - parts of the browser UI freeze up (!?)
so the styles are hidden from opera < 7.5 using the html[xmlns] selector

http://www.dithered.com/css_filters/css_only/xmlns_attribute_selector.html

this means that it won't happen on pages without an xmlns attribute
in other words - on HTML 4 pages, any browser-based screenreader using Opera 7.5-8 won't get the submenus
opera 9 and other browsers aren't affected because all are included in later selectors somewhere
opera's own speech/reading capabilities are not affected either,
because it generates events that open the menus, resetting all of this
and afaik there isn't any other browser-based reader that uses opera
so the likelihood is that this hole won't affect anybody at all
nonetheless it's still unfortunate, but it's practicably unavoidable -
the only other way to differentiate opera versions like this is the selector:lang(xx) pseudo-class,
but then we'd need a new custom varible to specify the user's language code
the styles are also hidden from old gecko builds using the commented selector hack
and from konqueror < 3.2 using the backslash hack, because it makes the navbar collapse
*/

All of which documents a single line of CSS:

html/**/[xmlns] .udm u\l{position:absolute;left:-10000px;height:0;overflow:scroll;}

So, okay, this is all a bit tongue in cheek. But nobody will ever complain at you for writing too many comments! My colleagues have even complemented me on the quality and thoroughness of my commenting. Maybe it’s stretching the point to call this a methodology, but it’s still a good idea.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://dtracorp.com dtra

    yep, definitely helps
    i was typing away trying to get this seemingly complicated piece of code to work
    then went over to a colleague’s desk, he started by putting in a comment of what was trying to be achieved
    and the easiest solution immediately struck me

  • Matt Wilcox

    Ahh, good post!

    I’ve tried this before and found that it helps a lot. I don’t do much programming any-more, but it’s still the method I use when I do. It definitely helps me to think things through properly.

  • http://www.deanclatworthy.com Dean C

    I personally wouldn’t do this on a regular basis, but when I have advanced cases of logic, I do logic diagrams on paper :)

  • http://www.lookwhostoxic.com/ craiga

    Amen.

    I do try to do something similar whenever writing a particularly complex code, but I should do it far more often.

  • Tim

    Thats all fair enough, but you have created another problem that is as old as the hills. You now have 2 “tracks” to maintain: the code, and its documentation. You can put the documentation anywhere you like, but when you figure out a way of guaranteeing parity between it and its documentation – please blog it!

  • malikyte

    When I was in college, this is what my college professors would call a plan-of-action, and sometimes, depending on the language used, pseudocode. ;) But yes, it can very well work for simpler and/or smaller chunks of code.

  • FallenJehova

    This isn’t a very DRY approach.

    As Tim said, commented code is very hard to maintain.

    If someone changes code, and it breaks, you know that someone changed the code. But you have no way of knowing when someones changes the comments or not, and if he doesn’t, how does the next developer that has to change the code will find himself with a text saying that the code should do something and a code that does something else.

    Now, who’s right?

    Solving this issue is trivial.

    Quoting Martin Fowler’s Refactoring:
    “If you need a comment to explain what a block of code does, try Extract Method. If the method is already extracted but you still need a comment to explain what it does, use Rename Method. If you need to state some rules about the required state of the system, use Introduce Assertion.”

    That basically means that if you have a block of code that have a comment, extract the code to a method and name it according to what it does. If it’s already a method, rename it to better explain it’s purpose.

  • Dr Livingston

    > Conversely, sometimes it’s easy to write the code but much harder to
    > explain it;

    Some would say, myself included that the code it’s self should explain what it does, which is far better than any commenting system you could have.

    Conversely, this is but one reason as to WHY you should have unit tests, which are their own documentation, that being one of many benefits. I could argue all day as to why your idea is bad but I’m not going to.

    In any case if you were to unit test you wouldn’t be dependent on comments to the extent that your now implying.

  • http://www.twice21.com ParkinT

    I have always approached a development problem by writing comments first (pseudo-code). Many times, after looking over the outline I have created, I will then make a decision about which language to use. I don’t code in just one language, but try to find the best tool for the job.

  • http://www.brothercake.com/ brothercake

    I don’t see how commented code is harder to maintain – if you change the code, change the comment – how hard is that?

    The Refactoring approach is fair enough – certainly it helps to use method and property names that are as self-explanatory as possible, but that doesn’t address the key purpose of commenting, which is to explain *why* you’re doing something, not just what. Somehow, this just doesn’t cut it for me:

    function useStaticPositioningForInternetExplorer-BecauseItHasZIndexBugThatCreatesErroneousNewContexts-InPositionedElementsWithPositionedParents()

  • rokpok

    I also follow this approach when I write complex code, but I delete the comment, when I finnish writing code.

  • PatrickGA

    As a relatively new developer, I have a bit of a problem with your methodology.

    I agree wholeheartedly that uncommented code can be a nightmare. There are actions that are just too complex to read in code. Watching a piece of code toss around ambiguously named variables often leaves me tearing my hair out trying to follow them.

    However, overcommented code is also frustrating to read as a new developer because instead of “what?”, “why?” or “how?”, I start having to ask myself “where?” In my opinion, that’s a question that shouldn’t come up when I’m reading code. When I’m trying to understand the hows and whys of a program, I’m not interested in looking for Waldo in the land of ASCII.

    Comments also expand the size of a document to somewhat ridiculous proportions if you’re counting one line of comment per line of code. We’re talking at least double the length of the actual code document. There’s nothing more intimidating to a learning developer than to open up someone’s program to see how it works and having to use a magnifying glass to find the scroll bar on the right side of the screen!

    I think the important thing is to find a balance between using explicit naming conventions and commenting your code. Let your code speak for itself where it can, and give it a hand with good, clean comments where it can’t. Try to bear in mind that the people reading your code are probably also proficient in the language you’re using to at least some extent.

  • steve_friend_of_brothercake

    I fully agree with the commenting paradigm outlined and laugh in the face of (insert hearty mmmwwaahhah!) the feeble protests offered above!

    the comments in the document – thats where they are supposed to be! Comment size is the least of my worries, 20k vs 10k vs my 500GB drive?..vs..2hrs @ $120/hr figuring out exactly why we used a linked list or not?

    “#

    That basically means that if you have a block of code that have a comment, extract the code to a method and name it according to what it does. If it’s already a method, rename it to better explain it’s purpose.

    #”

    that only works if your naming convention is totally logical AND the procedure/method only does one thing (and one thing only ) throughout the life of the code…

    The real issue is that code editing systems are only just beginning to find the issues and needs for commenting and editing code!

    After all these years, we have only recently gotten color syntax highlighting and brace matching. .NET allows you to collapse/expand blocks and new addons allow you to mark a block of text and then specify the block of code the comment refers to.
    A checksum is generated for the code block, and as subsequent revisions take place, the icon beside the comment block changes color and shape to indicate its diverging relevance to the code it comments!

    also, like Microsoft word, we can now see different revisions from other people (or yourself) as markup tags within the document.

    …popup and insertable “to-do lists” and reviewer notes/comments embedded in the code are really items that need the support of the Code IDE and the poor developer shouldnt be forced to keep track of all this :)

  • http://www.mittineague.com Mittineague

    I usually do block diagrams containing pseudocode. Sometimes my logic lines expand from “Do this here” to “does this in the following steps”, and sometimes they disappear altogether. What’s left when done stays.

  • dsfdsf

    圆盘注塑机and insertable “to-do lists” and reviewer notes/comments embedded in the code are really items that need the support of the Code IDE and the poor developer shouldnt be forced to keep track of all this

  • zzz

    I have been using both paper diagrams as well as your way of approach – Comment driven deployment. But what suits me more is drawing in paper. I would like to call that scribbling… ;)