Usage driven interface, test driven semantics

The problem

I need a class A to provide service a for me. First I create ATest and specify some of the wanted behaviour of A there. Then I start implementing A. All is well, I let ATest drive all the development.

Then, during the implementation of A I start to realize that in order to fulfill its task A needs to delegate a subtask to a new class, B. Now, it's clearly the implementation of A that drives the development of B. But, according to the principle of test driven development, shouldn't I first create BTest that drives the development of B?

If I do, which one is driving the development of B, A or BTest? (Of course, ultimately it's ATest that's driving, but if A and B are big enough units, that's not enough.)

If the former, I'm not doing test driven development. If the latter, how can I make sure the resulting B satisfies the needs of its client A? Or should they both drive at the same time, which means a lot of context-switching (both mental and concrete) and duplicating code between A and BTest?

The question isn't just theoretical, it's very practical. When applying the principle of coding by need , it's the driving code from which I create and navigate to the production code under modification.

Where should I press ctrl-1 to create B or one of its methods? Where should I ctrl-click to navigate to it so I can make it work?

Fortunately the two questions above give a hint to a solution: two driver candidates and two questions...

The solution

The primary need that justifies the creation of B is in A. So I code by intention and write the algorithm in A that needs B, using ctrl-1 to create a stub B, never really mentally leaving A. Eclipse will create TODO comments in the stub B so that I won't forget to test and fix B even if the default "return null" happens to work for A.

So far A has driven the creation of the B interface (in this context interface is more or less a synonym for signature).

Now when I have one client for the new service that B provides, it's time to think more about the service and try to find the general contract its interface implies. This is where BTest takes over and starts to drive the semantics or implementation of the newly created interface.

Put another way, A serves as a prototype that sketches one usage scenario for B. Most of the do-undo-redo work probably happens here. This prototype gives enough insight of the nature of B so it's straightforward to make all assumptions as general and explicit as possible by writing them as tests in BTest.

Originally published on 2006-06-13 at under category Art of programming