BT

Does TDD Harm Architecture?

| by Andrew Morgan on Mar 31, 2017. Estimated reading time: 2 minutes |

Bob Martin, also known as Uncle Bob and co-author of the Agile Manifesto, has recently published an evaluation on whether TDD harms architecture. Most of the discussion centres around whether following a test driven approach has a negative impact on both the high level design and general maintainability of implementation code. Martin concludes that TDD is an important discipline, but it's the principles such as decoupling, separation and isolation which lead to good design.

One notion that Martin explores is Test Induced Design Damage, originally from David Heinemeier Hansson, creator of Ruby on Rails. Essentially it is a comparison between a design which Hansson prefers, and a more testable design which is produced by Jim Weirich, a Ruby contributor and speaker. Martin encourages the reader to conclude which design they prefer, and writes:

The argument, boils down to separation and indirection. DHH’s concept of good design minimizes these attributes, whereas Weirich’s maximizes them.

Martin also writes about the Fragile Testing Problem. This is where a minor refactoring of implementation code could break hundreds of dependant tests, forcing them to all be updated.

As Martin starts to convey his opinion, he first points out that just like production code, tests need to be designed. This is regardless of whether TDD has been followed or not:

Principles of design apply to tests just as much as they apply to regular code. Tests are part of the system; and they must be maintained to the same standards as any other part of the system.

Martin also explains that a common mistake in TDD, is to end up with a one-to-one correspondence between tests and implementation. This could mean there is a single test class per implementation class, and a single test method per implementation method. The main negative result of this is a tight coupling between tests and implementation, leading to code that is difficult to refactor and reason about.

In terms of higher level architecture and design, Martin believes that it does not emerge from TDD:

The idea that the high level design and architecture of a system emerge from TDD is, frankly, absurd. Before you begin to code any software project, you need to have some architectural vision in place. TDD will not, and can not, provide this vision. 

However, Martin does believe that lower level design, closer to the code, does emerge from practicing TDD. In other words, whilst tests remain the same, the implementation code can be refactored and be structured into something that is more maintainable. Martin believes this leads up to two streams of evolution: "As the tests get more specific, the production code gets more generic."

Despite these differences, Martin's main thought is that TDD is a discipline. He concludes that it's up to the developer to produce a good design, regardless of whether they are doing TDD or not:

You see, it is not TDD that creates bad designs. It is not TDD that creates good designs. It’s you. TDD is a discipline. It’s a way to organize your work. It’s a way to ensure test coverage. It is a way to ensure appropriate generality in response to specificity.

By giving this summary, it means that in his view, the design produced by TDD is in reality a design produced by a developer. Whilst the main benefits of TDD are the test coverage and reliability of the application - it's the principles such as decoupling, separation and isolation that produce good design.

Rate this Article

Relevance
Style

Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Tell us what you think

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Testing is not trivial by Kristof Szabados

Testing is not trivial.
Even if we put aside how tests and the production systems work together and look at tests in themselves, we will find complexity.
So far research has shown that creating tests might be an endeavour very similar to product development in scale/complexity/evolution.
Source: bit.ly/2orQrhB

Maybe it is not "just" TDD that is harming the architecture, but the way we think on testing.

Bursting the bubble of TDD and emergent design by Ian Fairman

I think Martin hits the nail on the head. After being told for years that TDD isn't about testing but about design we now have an acknowledgement of the true situation - that design is a bigger process than can be encapsulated by red-green-refactor. Good design involves many aspects - domain modeling, patterns, usability, robustness and, yes, testing and refactoring.

Hopefully we are beginning to put TDD in it's true place as a useful technique some of the time but not the primary driver of development.

Re: Testing is not trivial by Andrew Morgan

Interesting paper. I agree, tests are complex too, and they can cause a build up of technical debt just like production code.

Re: Bursting the bubble of TDD and emergent design by Andrew Morgan

From a testing perspective, I've seen lots of testing anti-patterns which prove this point. One that hit me hard in the blog is one test method per production method. This is horrible and leads to unmaintainable code.

Another I've run into is over-mocking. This leads to situations where the test ends up testing the implementation and not the behaviour. It makes refactoring a nightmare, and of course leads to badly designed production code.

I can relate to Martin's blog - design principles need to be thought about properly, and don't come for free with TDD.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

4 Discuss
BT