Comment-Driven Development

    James Edwards
    James Edwards
    Share

    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.

    Frequently Asked Questions (FAQs) about Comment-Driven Development

    What is the main purpose of Comment-Driven Development (CDD)?

    Comment-Driven Development (CDD) is a programming approach that emphasizes the importance of writing comments before writing the actual code. The main purpose of CDD is to improve the clarity and maintainability of the code. By writing comments first, developers can outline their thought process and the intended functionality of the code, making it easier for others (or themselves in the future) to understand the code’s purpose and how it works.

    How does CDD differ from other programming methodologies?

    Unlike other programming methodologies that focus on writing code first, CDD prioritizes writing comments before the actual code. This approach encourages developers to think through the logic and functionality of the code before implementing it. It also promotes better documentation and understanding of the code, which can be particularly beneficial in collaborative environments or when maintaining legacy code.

    Can CDD be used in conjunction with other programming methodologies?

    Yes, CDD can be used in conjunction with other programming methodologies like Test-Driven Development (TDD) or Behavior-Driven Development (BDD). In fact, combining CDD with these methodologies can enhance the clarity and maintainability of the code. For instance, using CDD with TDD can help developers understand the purpose of the tests and the expected behavior of the code.

    What are the potential drawbacks of CDD?

    While CDD can improve code clarity and maintainability, it may also increase the time required to develop software, as developers need to spend additional time writing comments. Additionally, if the comments are not updated when the code is modified, they can become outdated and misleading.

    How can I start implementing CDD in my projects?

    To start implementing CDD, begin by writing comments that outline the intended functionality and logic of the code before writing the actual code. These comments should be clear, concise, and informative. Over time, this practice can become a habit, making it easier to implement CDD in your projects.

    Is CDD suitable for all types of projects?

    CDD can be beneficial for any project, but it may be particularly useful for complex projects or projects involving multiple developers. By outlining the logic and functionality of the code in comments, developers can ensure that everyone on the team understands the code, reducing the potential for misunderstandings or errors.

    How does CDD improve code maintainability?

    CDD improves code maintainability by providing clear documentation of the code’s intended functionality and logic. This makes it easier for developers to understand the code, making it easier to update or modify the code in the future.

    Can CDD improve code quality?

    Yes, by encouraging developers to think through the logic and functionality of the code before implementing it, CDD can lead to better-designed and more efficient code. Additionally, the clear documentation provided by CDD can reduce the potential for errors or misunderstandings.

    How does CDD affect code readability?

    CDD can significantly improve code readability. By providing clear, concise comments that outline the code’s intended functionality and logic, CDD makes it easier for developers to understand the code, even if they are not familiar with the project or the specific section of the code.

    Can CDD be used in any programming language?

    Yes, CDD is a methodology that can be applied to any programming language. The key is to write clear, concise comments that outline the intended functionality and logic of the code before writing the actual code.