If you are a believer in Agile methods, but don't like Test-Driven Development (TDD), this site is for you!
Many people in the Agile community feel that TDD is a niche technique that works really well for some people but is awful for others.
Sometimes TDD fans go too far by insisting that everyone should use TDD - even saying that if you don't use TDD, you are not fully Agile, or have not given it a chance. We disagree. We explain why here.
Be Agile without TDD!
What is a design?
What is a design? (a) taxonomy; (b) decisions, in the form of choices, relationships, strategies, roles, etc.; (c) rationale for the decisions. Decisions may be specified graphically.
An architecture is the outermost and most abstract level of design. That’s all.
A design view focuses on a particular set of behavioral aspects. A design is often expressed as a collection of views.
A design view has a purpose, and as such, it need not contain aspects or elements that are not relevant to that purpose. E.g., a full class diagram might be unnecessary for a design view that describes a particular set of features. Thus, completeness, in the form of details that are irrelevant to what a view explains, is the enemy of simplicity, clarity, and focus. Completeness also gets in the way of rapid decision-making and rapid refinement, which are important today. One generally does not need to wait for a design to be “done” in order to make refinement decisions: one only needs for the main parts of a design to be firm enough to start to make tentative refinement decisions. Design needs to be a living collaborative process of refinement (a verb) – not a static artifact (a noun). The design artifacts merely capture the current state of the process of design.
There is no boundary between design and implementation. Implementation is lowest level design.
Design expresses intention – the rationale. The rationale is the argument that a design choice meets a requirement.
If you have to infer intention, the design is incomplete – it is missing rationale. That is why tests do not constitute a design: they are missing the taxonomy, the decisions, and the rationale. What they provide is a set of specific cases. That is not a design. Tests also do not specify behavior: that is, they are not a valid view of a design’s intended behavior. This is because they do not specify rationale – the argument of how the design’s choices implements the intended behavior. Tests are also a very poor description or specification of behavior, because tests do not define clearly specified abstractions: they are a collection of detail behavioral scenarios; to obtain the intended behavioral rules as an abstraction, one must derive them by inferring how the many test cases relate to each other. One might infer incorrectly; and if the tests are incomplete, one will likely infer a behavioral abstraction that is too simple. Tests are nothing more than an incomplete program for partially verifying that behavioral intention is met: they do not define the behavioral model or abstractions.
A clear low level design – the “code” – must be annotated (commented) because code is not sufficiently expressive to capture intention. Merely naming methods is not enough: a method name cannot be expressive the way that a comment can be, which explains why the method is needed and how it is intended to be used. That’s right: an effective method comment is not a spec for the method’s behavior, but instead should say how one intends that the method will be used. That is the most powerful way to convey the intention for why the method exists, from which it becomes obvious what the method must do. A comment should capture design decision rationale – the “why we need it” and “how to use it”, not just the “what it does”.
Design must be progressive. An implementation is a lowest level design. One cannot design at the lowest level from the outset – one cannot skip the refinement process, because each level of abstraction has its own concerns, and so one must progress through each level. Also, many concerns are emergent and so they cannot be predicted: one must simulate or create a prototype so that those concerns are revealed. An example is a vibration mode in a machine: unless one performs a molecular level full physics simulation, one cannot be sure to identify all vibration modes, and so prototypes are needed to discover them. Similar situations exist with software, particularly real time software.
Design should be minimal: don’t include details that are not necessary for the next level of refinement, except possibly as hints or examples. This ensures that the design is maintainable, and that design only contains the abstractions that pertain to that level, so that the focus can be fully on those and not on distracting details.
It is essential to keep the important information as compact as possible. More information is not better.