As a developer, there is a high chance that you had a debate on the value of TDD in building software, especially if you apply it!
I had a lot of those debates!
A couple of months ago, I came across such a debate between Jim Coplien and Robert Martin (Uncle Bob). I found this discussion kind of interesting especially that it involves two leaders in software engineering.
You can watch the debate here:
Here are my takeaways from the discussion:
Three Rules of TDD
Uncle Bob defines the following three rules for applying TDD:
- Don’t write a line of production code without having a corresponding failing test
- Don’t write too many failing tests without writing production code
- Don’t write more production code than is sufficient to pass the currently failing test
Architecture is Important
Jim points out that he has no problem with those rules, his concerns are more architecture related. Jim and Uncle Bob would argue for more than ten minutes to finally reach an agreement on the importance of architecture. The below five points summarizes what they agreed on:
- Architecture is very important
- It is entirely wrong to assume that the code will assemble itself magically just by writing a lot of tests and doing quick iterations
- Design evolves with time and should be assembled one bit at a time
- An Object should have properties to give it meaning. At the beginning, those properties should be minimal.
- Architecture shouldn’t be created based on speculation
TDD and Professionalism
Probably the only disagreement you can sense from this debate is what defines a professional software engineer. For Uncle Bob, it is irresponsible for a software engineer to deliver a single line of code without writing a unit test for it. Jim, on the other hand, considers ‘Design by Contract’ to be more powerful than TDD.
My Point of View!
Personally, I have been applying TDD since I joined my team three years ago. After experiencing the benefits of this practice, we got to a point where we don’t write or refactor any line of code without having a corresponding unit test!
In addition to that, I had the chance to coach other developers by running coding dojo sessions at work.
All that makes me say that I agree more with Uncle Bob on the topic of professionalism!
“Design evolves with time and should be assembled one bit at a time”. I’ve been thinking about this point for a while now. In a TDD + agile mode, one might not foresee the long term end result and focus more on the small tasks in-hand.
I am a bit skeptical on the idea that “[design] should be assembled one bit at a time”. I think in this approach one is constantly rethinking the architecture of the solution, refactoring the parts of the solution, and might reach a point were the sub-solutions are optimal but the whole design is not and realize that maybe it was a good idea to think of the general design first.
My question is how do you think of the solution design for your micro-tasks when you follow an iterative TDD (“Don’t write more production code than is sufficient to pass the currently failing test”) approach, and the general solution architecture in an agile methodology? Those might be two different questions so you can address them separately.
Glad to hear from you!
Doing incremental design doesn’t mean that you shouldn’t think of the whole design. The idea is that your design will evolve and change as you write your code and as the requirements change. Thus, you need to keep your design ready and easy to change.
Here is how we do it in our team:
1. Plan the requirements for the coming 3 months with our Product Owner during a Business Priorities meeting. In that meeting we agree on the epics to work on for the next period. This will make us focus our design on small parts of the big design
2. Another activity we do is an Architecture meeting every 6 months. During that meeting the team looks at the current whole design and plans the next steps, like whether we need to remove, edit or add pieces to it.
3. When faced with a complex story (micro-task), the pair working it suggests a design to the team before starting the coding phase.
With those 3 steps, we guarantee that our design is evolving as our product is growing and at the same time we are sure the pieces are well connected in the whole design.
I hope this answered your question!