The number of ‘correct’ ways to develop software are almost too many to number. While some are all-encompassing for a (multi-person) project, others apply mostly to the engineering of the code itself. This article is about a method in the latter category.
In recent years, all-encompassing methods that have become popular include ‘Waterfall’ and ‘Agile’. For the ensuring of code quality, so-called ‘test-driven development’ (TDD) is often enforced.
Personally, I have been doing software development since I was about 7 years old, starting with QBasic (on MSDOS) and trying out many languages before settling on using C++ and VHDL as my preferred languages. What I have come to appreciate over these decades is a) to start with a plan, and b) writing out the code flow in comments first before committing any lines of code to the structure.
I hope that I do not have to explain here why starting off with a set of requirements and a worked-out design is a good idea. Even though software is often easier to fix afterwards than a hardware-based design, the cost of a late refactoring can be higher than one may be willing – or can afford – to pay. And sometimes one’s software project is part of a satellite around a distant planet.
The same is true of documenting APIs, classes, methods and general application structure, as well as protocols. Not doing this seems like a brilliant idea until you’re the person doing the cursing at some predecessor or previous developer who figured that anyone could figure out what they were thinking when they wrote that code.
As I mentioned earlier, I prefer to first put down comments before I start writing code. This is of course not true for trivial code or standard routines, but definitely for everything else. The main benefit of this for me is that it allows me to organise my thoughts and consider alternate approaches before committing myself to a certain architecture.
Recently I became aware of this style of developing being called ‘comment-driven development’, or CDD. While some seem to take this style as a bit of a joke, more and more people are taking it seriously these days.
When I look back at my old code from years ago, I really appreciate the comment blocks where I pen down my thoughts and considerations. Instead of reading the code itself, I can read these comments and use the code merely for illustrative purposes. This to me is another major benefit of CDD: it makes the source code truly self-documenting.
The steps of CDD can be summed as follows:
- Take the worked out requirements and design documents.
- Implement basic application structure.
- Fill in the skeleton classes and functions with comment blocks describing intent and considerations.
- Find any collisions and issues with assumptions made in one comment relative to another.
- Go back and fix the issues in the design and/or architecture which caused these results.
- Repeat steps 4 through 5 until everything looks right.
- Start implementing the first code blocks.
- When finding issues with the commentary, return to step 4.
- Perform tests (unit, integration, etc.). If an error in the commentary text is found, go back to step 4. Code implementation errors are okay.
- Final integration, validation, documentation and delivery.
What is very valuable about CDD is that it necessitates one to consider the validity of assumptions made, or more simply put: whether one truly wants to write that code one was thinking of writing or should reconsider some aspects or all of it. It also forms a valuable bridge between requirements and design documents, as well as source code, tests and documentation.
CDD doesn’t supersede or seek to compete with Waterfall, Agile, TDD or such, but instead complements any development process by providing an up-to-date view on the current status of a design and its implementation. When combined with a file revision system such as SVN or Git one can thus track the changes to the design.
It’s also possible to add tags to the comments to indicate questions or known defects. Common here is to use the ‘TODO:’ and ‘FIXME:’ strings, which some editors also parse and display in an overview. Using such a system it’s immediately clear at a glance which issues and questions exist.
One thing which I often hear about comments is that one should not use them at all, that the ‘working documentation’ for code is contained in file revision system commit messages and kin. Also that comments are always out of date.
The thing there is that even the best commit messages I have seen cannot provide the in-context level of detail which comments can provide. Commit messages also rarely contain questions, remarks and the like. Where they do it’s not easy to provide a central overview in an editor of outstanding issues even with access to the repository.
Out of date comments is merely a sign of lack of discipline. CDD isn’t unlike TDD in that if one doesn’t maintain the comments or tests, the whole system stops working. As both systems are complementary, this isn’t too surprising.
A good reason to complement TDD with CDD is that it can drastically reduce the number of test cases. By strategically testing only specific cases which came forward as being ‘important’ during the CDD phase, only a limited number of unit tests are required, with integration testing sufficient for further cases. CDD improves test planning.
Writing documentation is made infinitely easier with CDD, as all one has to do is to take the commentary in each source and header file and turn it into a more standard documentation format. Accuracy and completeness are improved.
The above are mostly just my own thoughts and experiences on the subject of CDD. I do not claim that the above is the end-of-be-all of CDD, just that it’s the form of CDD which I have used for years and which works really well for me.
I welcome constructive feedback and thoughts on the topic of CDD and other ways in which it can improve or support a project. If CDD is an integral part of your personal or even professional projects I would like to hear about it as well 🙂