As consultants, we are often asked to review the work of others. One of the things we review is the quality of the design of some part of the system. Is it cohesive, decoupled, non-redundant, encapsulated, open-closed, and so forth? Often the developers understand and agree that these qualities are important, but they are not certain they have achieved them adequately.
I often start like this, “I don’t know. Can you write a good test for it?”
I can ask this even before I look at their work because I know that bad designs are notoriously hard to test. It’s a great way to start an evaluation. Continue reading ““Good” Tests in TDD”
One aspect of strong design is that separation is created between the various concerns of the system. This adds clarity, promotes re-use, improves cohesion, and in general adds value to the work.
It can be difficult to know, however, if one has separated things sufficiently, or perhaps has overdone it. This is one area where TDD can help.
Example: An object with asynchronous behavior has, at minimum, two categories of concerns.
In previous posts, I discussed that the first leg of emergent design is TDD, which provides code quality and sustainability. The second leg is design patterns, which provides insights into handling variation. The third leg is ATDD, which provides us a way of discovering and clarifying the value we will get. Continue reading “The Third Leg of Emergent Design: Acceptance Test-Driven Development (ATDD)”
TDD is the first leg of emergent design or what could be called Agile Design. Design patterns are the second. They’re often described as “solutions to recurring problems in a context.” In this way they can be thought of as recipes that have been learned. But patterns open the door to much more; they are examples of ways to think. Patterns hide varying behavior, structure or which objects to use. Continue reading “Design Patterns: The Second Leg of Emergent Design”
I am heartened by the surge in TDD training. To me, TDD is the second most important thing for devs to learn. ATDD is the first.
TDD is not just the automation of unit testing. It’s also intended to improve design and sustainability.
TDD’s formulation of tests, prior to code, drives design. High quality code is easy to test. The reverse is also true. Code that is easy to test is higher quality than code that isn’t. I labeled this quality, “testability,” in my book Design Patterns Explained. Test-First is a process where deciding on your tests before writing your code improves your design. Continue reading “Test-Driven Development (TDD): The First Leg of Emergent Design”
With a name like TEST-driven development you’d expect TDD is mostly about testing. Especially when the end result is tests. In our book Design Patterns Explained we discussed how testability (how easily code can be tested) is an intrinsic property of software and is highly correlated with good design. This is why the 1st mantra of design patterns is to design to the behavior of the objects being written. These behaviors being described as tests.
One of the characteristics of good design is that it is modifiable with less effort than poor design. So testing first give us both better design of the code & increase its sustainability-enabling emergence. This is the big difference between test-FIRST and unit testing.
But we now have the added burden of the tests which often add to maintenance costs. The cause of this is insufficient focus on the quality of the tests. An ideal test will validate only one behavior. The intent is to decouple the tests so that when one behavior changes only one test needs to change. This requires attending to the coupling of tests as future enhancements are made. Coupling of tests inform coupling in design.