Purposeful Software Development
The post is a quick response to mtelligent’s post on “The Cargo Cult of Test Driven Development”. Somebody referred me to this link and while reading, something struck a nerve (not a bad one… just one).
In the post it talks about how there is a feeling that Test-driven Development (TDD) is a form of Cargo Cult Programming. This can be interpreted to mean that the process of where you write tests in hopes of driving out the production code, has turned into another ritualistic software development process where the meaning of doing such actions is lost.
First off, this phenomena is something we all fall victim to now and again. What use to have real purpose has now become more habit than anything else and we forget why we even started. I have seen this happen first hand with TDD and will be the first to admit guilt. However, let me take you back to when it really meant something.
About 5 years ago I was placed on a project that was completely foreign to me… new team, new code, new technology, new everything. Prior to that I had worked with a team that practiced a modified form of Extreme Programming. In this version, there was no pair programming, there was no test-driven development. There were user stories, iterative development, refactoring, etc. With this new team I decided that I would give this TDD a try as I was hearing that a big piece of the agile benefit(s) were being missed by not unit testing.
I ended up doing a best attempt at TDD… actually writing tests before doing the development: i.e. making the test fail; implementing the code to make the test pass; ensuring the test passes. Holy crap! This took some serious brain tweakage. I mean, my mind was not supposed to work that way and it was some kind of miracle that I didn’t throw the whole idea out the window within the first week. However, I kept following it in hopes that I would start seeing the light. And then it finally happened! There was something absolutely amazing taking place… my code was slowly becoming more robust, testable (obviously), architecturally sound, etc.
This is something that I did not realize though while actually going through the pain. From what I could tell, I was just experiencing a new method of development that was preventing me from being truly effective. It took a while before enlightenment finally took place and I could see that what had happened was something quite magical. It’s kind of like that scene in The Karate Kid where Daniel LaRusso gets all pissed off at Mr. Miyagi because he felt that the only thing he’s been learning how to do is some old guys chores (paint the fence, wax that car, etc). This ain’t no Karate! It was at that moment in time that Mr. Miyagi reveled what was really happening. While performing these seemingly mundane chores, Daniel had learned Karate’s foundational body movements of self defense. He was on his way to becoming a wicked Karate Kid.
Sorry for the jaunt there… Anyway, from that day on I would tell whoever asked on what I felt about TDD and how I was convinced (and still am) it changed the way I did software development. However, time goes by and I we tend to slip into our old habits quite easily. Plus, at this point in time the TDD philosophy had permeated throughout the entire team and it was easy to see the bad habits that we all had picked up. Writing tests, just for the sake of writing tests was a common problem. Feeling things like, “Well Bob, I guess before we can start any real coding we need to write a test first.”
What really happened here is that we fell into the trap. We forgot why we started doing TDD in the first place. We forgot the purpose behind our actions. It’s not to mindlessly fill our test suite with a plethora of tests. It’s not to get 100% code coverage. It’s not to merely improve the quality of the product. All of these things cannot be accomplished through the sole act of TDD. These are usually things that we get for free as a result of reflecting on our code. Test-driven development is something that is chosen to be followed because it simply helps us write better software. While performing continuous analysis on the code our minds engage and we are able to operate at a level where we relentlessly make the code better.
With all that being said it seems a bit unfair to state that TDD as a whole is a form of Cargo Cult Programming. There are many flawed theory’s of testing out there. There always will be. However, if we as programmers can try and remember the purpose behind the methods we follow we can limit our chances of becoming part of the Cargo Cult.
-
If you enjoyed this post, it would be totally righteous if you subscribed to future posts via rss.
David San Filippo 06:45 on July 3, 2008 Permalink |
Great Post. In my original blog post, I probably went a bit off track discussing my own problems with TDD instead of dealing with the Cargo Cult aspect of some developers. You did a good job of addressing that as we need to really understand the practices we perform, not just with TDD, but with everything we do.
I also really like your description of your “A ha” moment, where you no longer felt like you were just flailing. I am curious to how long it took for you to reach that point.
Scott 07:47 on July 3, 2008 Permalink |
Hi David,
Thank you for commenting. If I remember correctly, there were glimpses of progress early on in the game, probably within a few hours. However, these glimpses were not enough to convince me that what I was doing was helping.
For me, I think the “lights went on” after a week or two when I ended up re-writing some of the code I had written earlier in the project. This was the result of the tests pointing out flaws in the implementation. It was definitely a strange feeling at first. I don’t believe I would have realized the benefits unless this happened.
All I can say is that it was a very liberating experience and I feel fortunate that for some reason I suffered through the pain early on. It would have been very easy to just throw out the whole concept.
Best regards,
Scott
Philip Schwarz 12:56 on July 5, 2008 Permalink |
Scott,
you said: …a modified form of Extreme Programming. In this version, there was no pair programming, there was no test-driven development.
Was there any automated unit testing?
you said: There were user stories, iterative development, refactoring, etc. With this new team I decided that I would give this TDD a try as I was hearing that a big piece of the agile benefit(s) were being missed by not unit testing.
Do you mean by not doing automated unit testing?
Automated testing is an essential part of XP because it is needed to guarantee the key technical premise of XP: that it is possible to experience a flattened cost of change curve. Let me explain with a collage of excerpts from Kent Beck’s Extreme Programming Explained (1st edition):
Traditional approaches to software development are careful to make big decisions early and little decisions later.
XP is an entirely different approach to software development that makes each decision quickly, but backs each decision with automated tests, and that prepares you to improve the design of the software (refactor) when you learn a better way to design it.
The XP approach is not possible if the cost of changing a program rises exponentially over time, a universal assumption of software engineering, but it is possible if the cost of change rises slowly over time, eventually reaching an asymptote.
XP says that with a combination of technology and programming practices, it is possible to experience a curve that is the opposite of the exponential cost of change curve: a flattened cost of change curve.
Here are the practices:
* A simple design, with no extra design elements no ideas that weren’t used yet but were expected to be used in the future.
* Automated tests, so we had confidence we would know if we accidentally changed the existing behavior of the system.
* Lots of practice in modifying the design, so when the time came to change the system, we weren’t too afraid to try it.
With these elements in place—simple design, tests, and an attitude of constant refinement of the design we experience the flattened curve, and so the XP approach to software development becomes viable.
Scott 10:30 on July 7, 2008 Permalink |
Thanks for the comment Phillip. I’m not sure I understand your question/comment. The post is not saying that TDD is bad or useless. I completely agree that it’s an essential part of XP. I was just trying to say that sometimes we forget why we are testing because we fall into habits that make it more of a ritual than something useful.
Please let me know if I can clarify anything if it doesn’t make sense.
Philip Schwarz 14:07 on July 7, 2008 Permalink |
Scott,
You said:
I had worked with a team that practiced a modified form of Extreme Programming. In this version, there was no pair programming, there was no test-driven development.
OK, there was no TDD. Was there any automated unit testing?
BTW: nice post. Really liked reading about your experience in applying TDD.
Philip
Philip
Scott 16:22 on July 7, 2008 Permalink |
Hi Philip,
Yes, we did have a form of automated unit testing, where all tests that we had written would run with our automated build system. The practice of writing our tests first prior to actually developing production code was something that was done only once in a great while.
Thanks for the generous comment on the post.
Happy coding!
Scott