To TDD, Or Not?

One of the things bouncing around the Internet around the time I began to consider starting a blog was the debate over test driven development (TDD) as a measure of professionalism. I find I am an empiricist when it comes to arguing about development methodology after so many years of doing devleopment, which means I consider much of what is debated as vain efforts in convincing people to have the “correct opinion.” Yet, as with most things, I do have to make a decision about what I personally am going to practice in my personal effort to produce high quality code.

In addition, because of the type of code I tend to write, I have issues with some practices such as code reviews since reviewing the multithreaded, concurrent programs and data structures I write requires a skill set and level of expertise that is not common among my peers or developers in general. It isn’t that code reviews don’t help, but I find that most of the value comes not from others input, comments, or finding errors, but, rather, from the effort I have to undertake to explain the code which causes me to examine it in depth in order to be able to explicate it to others. So I am constantly looking for techniques that help me to examine, analyze, and force me to thoroughly walk through my own code in order for it to be as correct as possible. With my current project, I find I am even more on my own since it hasn’t attracted much attention, and I find myself even more dependent on my own self review.

So as I previously alluded, I find the arguments over TDD largely evidence free, and, therefore, largely arguments over opninions and preferences. To make TDD a hallmark of professionalism, I find a ridiculous assertion that reduces the practice of programming to mere domatic religion. The only measure of professionalism I find that makes sense is the actual production of high quality, error free code, regardless of how it was produced. That does not mean don’t find value in unit testing and some value in writing tests before writing code, but there is very little actual evidence that TDD itself produces well-designed and correct code over and above any other practice. Frankly, the more I listen to some of Leslie Lamport’s recent presentations about specifying systems and thinking before coding, I find his views on what should be practiced much more compelling as a measure of professionalism, even though I question how well they would scale as formal methods haven’t proven economical in practice for most development efforts.

As it stands, my current practice is to mix writing unit tests both before and after coding. I find that writing some simple, initial unit tests to exercise the major functions on their “happy path” the fastest way to get something working, which gives that initial, positive feedback I think that programmers find so motivating. I also find, though, a lot of value in writing most of my unit tests after writing the majority of the code as it forces me to examine the various paths through the code in a thorough fashion. I find the activity of writing thorough unit tests that exercise especially the error paths a valuable exercise as a form of self-directed code review.

Code Aesthetics

As I have stated in a previous post, this blog and the associated code project are a kind of experiment or exploration to satisfy my curiousity about ways to actually build applications using multiple languages. Because the code is open source available on Github, I have altered my personal style that I have used for much of my career. Some of the changes are because they are just better options and my changing is just long overdue. Most though are adjustments to accomodate what is common or recommended practice in open source projects, and at least one change is an outright innovation on my part which may not survive.

The first major change I have undertaken relates to exiting from functions. I was educated in the 1980’s at a time when formal methods were under development and seen as the future direction for development. At that time, in order to facilitate formal analysis, we were trained to have a single entry and exit point for all functions. In spite of the fact that I personally never tried to perform a formal proof of my code, I continued to code in this style and reason about my code in that fashion. With the processors of that era, it also made sense in that you could actually reason about execution order and code a straight line path of likeliest path through the code in order to be more performant. Admittedly, that hasn’t been true probably at least a decade with out-of-order execution and pipelining, but it had become an ingrained habit. So lately, in my code I have moved more to the style seen in more modern code bases like the Linux kernel where multiple return statements are used to exit a function as soon as possible as conditions merit to minimize nesting levels.

A rather simpler change is to use the Kernighan technique for brace placement that places the opening brace at the end of a line. For years, I practiced aligning braces in the same column, but for this project I adopted the reasoning that it is more important for understanding to get more lines of code on screen. So I am cutting down on lines by placing braces at end of lines and reducing the number of empty lines, as well as, trying to keep functions at 40-50 lines so they fit on one screen.

The other formatting change that I made was to accomodate recommended practice to limit line length to 80 characters. In my daily work, I wouldn’t pay that much attention to it since screen width hasn’t been an issue for some time. I would never create a line that was a totally unreasonable 200 or 300 characters long, but if a long function declaration or an if statement with multiple tests went well over 80 columns I wouldn’t worry about it. I have to say that for the most part limiting myself to 80 columns has been easier than I would have thought using these practices, and I have to say for the most part I am pleased with the clean appearance of my code.

The one innovation I am experimenting with based on the 80 column limitation is putting arguments in function declarations on separate lines. After trying it for a while, I quite like the technique for being able to comment each argument in line, adding and removing arguments, and for the effect of making the arguments similar to local variable declarations. I can now see how the original function declarations in C came about, even though when I learned about them I thought them rather archaic. The one downside that will probably cause me to move away from this style and revert back to my normal practice is that when I set breakpoints in gdb the function name doesn’t show up when the breakpoint is reached and all I see is the closing paren/opening brace line. So much for “good ideas”.

The one thing that I did not change was the use of spaces rather than tabs. I entertained moving to tabs rather than spaces, but the rules for formatting things across multiple lines such that things would not be a mess no matter what the tab width was seemed like more mental overhead than I felt like taking on. Set space width is just simpler and guaranteed to produce a clean layout with no extra thought, so I am sticking with it.