TDD: Does it get in the way of good API design?

Viewed 2985

I've never written TDD code, but I've seen a decent amount of discussion about it here on SO. My biggest concern with it is that it seems like general good API design (for flexibility, ease of use, simplicity of interface, and performance) takes a back seat sometimes to making code mockable, ultra-modular beyond what is necessary for any API use case, etc. For example, TDD proponents often suggest that things be passed in as parameters that, from an API abstraction perspective, the method being called should "just know", or that classes and methods be factored in a way that makes testing easy, which is not necessarily the way that relates best to the problem domain.

To people more experienced with both TDD and API design: Do you find that TDD often gets in the way of good API design? If so, how do you counter this?

14 Answers

TDD is an API design technique. Every time you write a unit test, you are either creating an API for the first time, or using a previously created API. Each one of those tests lets you "feel" how easy or difficult the API is to use. Each new test forces you to consider the API from a new point of view. There can hardly be a better way to design APIs than to exhaustively use them the way TDD forces you to.

Indeed, this is the reason that TDD is considered a design technique rather than a testing technique. When you practice TDD, you do not design your APIs in a vacuum. You design them by using them!

If your API is suffering due to internal requirements of your objects, that's what the facade pattern is for. Not all objects need to be public.

A lot of the pain points of TDD are, in fact, signs of pain points in the design. If it's hard to create a class because it requires 18 dependencies to be passed in, the fundamental problem is that the class has too many dependencies and is going to be quite brittle. It also probably does waaaaaay too much. The "TDD pain" in this case is a good thing, as it makes the other issues more obvious.

TDD doesn't get in the way of good API design.

Mocking gets in the way of good API design.

The two are not synonymous - I independently started using TDD before others wrote the books on it, simply because it makes clear whether requirements are testable and designs meet a requirement.

However, I think Mocking is bad because it affects the design and implementation and introduces other, artificial requirements. It also exposes internals of an implementation that shouldn't be, and makes the testing brittle. It tests how something is done, rather than what is done.

How to counter it: Use TDD, but don't use mocking.

Related