What Role TDD plays in Systems Design
Opinions from Pioneering Programmers
Programming is more of a craft than it is a science. One of the reason I agree with this is because there is not always a definite truth to a given problem. As an apprentice it is enlightening to hear the various perspectives from pioneering programmers. Their diverging views is a great source for knowledge. This week I came across a few articles and videos that debated the different approachs to designing software systems and the role that Test Driven Development play into the emergence of design. Here are my takeaways.
“Capitalize on what you know up-front, and take some hard decisions up front, because that will make the rest of the decisions easier later… You do things ‘just in time,’ but you want to get the structure up front, otherwise you risk driving yourself into a corner.”
James Coplien believes that the emergent design that comes from TDD can result in an application that is built “completely wrong.” It makes a lot of sense to have the design of the system be informed by what we know. However, there can be a cost of “Big Design Up Front” as this requires a lot of resources and can potentially lock in an inflexible solution. The key is to striking the right balance of a high level design informed by current knowledge but also flexible for change.
“The most important part is where to place the emphasis. If you have a very simple model layer, but your UI is complex, then you should indeed be system-test heavy, and model-test light…Do not let your tests drive your design, you let your design drive your tests…Stop obsessing about unit tests, embrace backfilling of tests when you’re happy with the design, and strive for overall system clarity as your principle pursuit.”
I think DHH’s advice is practical if we know the design of the application from the get-go, but sometimes that is not always the case. I just recently finished up a Rails project where the scope and requirements were changing through each iteration. It would have been difficult to imagine what the project would look like in the first two sprints (of a five sprint project) as responsibilities were shifted from vendor to vendor. We started with what we knew and developed with TDD. The benefits of doing so meant that our code was more decoupled than what it would have been if we developed it without TDD. Furthermore, we were not afraid to implement changes as requirements became clear. The test was there to guide us and let us know that the application is still working.
“It is not TDD that causes good or bad design. You do that…TDD is a discipline. It’s a way to ensure test coverage.”
This is an obvious statement but TDD alone will not guarantee a well preforming, decoupled, and readable application. TDD is one approach that can be used to set the pace and drive the development of the application. Uncle Bob says it is best, we as programmers are responsible for the system and it is up to us to deploy all the knowledge, discipline, and tool kit to deliver a well-crafted system.
My takeaways from hearing from this experienced programmers is that we need to make informed strategic decisions but also stick to a discipline that would enable us to execute tactically. It is definitely helpful to be cognizant of the end goal and aware of the components that should be emphasized but that does not mean tossing TDD out the door.