Java – I don’t understand how TDD helps me get a good design if I need a design to start testing it

cjavanettdd

I'm trying to wrap my head around TDD, specifically the development part. I've looked at some books, but the ones I found mainly tackle the testing part – the History of NUnit, why testing is good, Red/Green/Refactor and how to create a String Calculator.

Good stuff, but that's "just" Unit Testing, not TDD. Specifically, I don't understand how TDD helps me get a good design if I need a Design to start testing it.

To illustrate, imagine these 3 requirements:

  • A catalog needs to have a list of products
  • The catalog should remember which products a user viewed
  • Users should be able to search for a product

At this points, many books pull a magic rabbit out of a hat and just dive into "Testing the ProductService", but they don't explain how they came to the conclusion that there is a ProductService in the first place. That is the "Development" part in TDD that I'm trying to understand.

There needs to be an existing design, but stuff outside of entity-services (that is: There is a Product, so there should be a ProductService) is nowhere to be found (e.g., the second requirement requires me to have some concept of a User, but where would I put the functionality to remind? And is Search a feature of the ProductService or a separate SearchService? How would I know which I should choose?)

According to SOLID, I would need a UserService, but if I design a system without TDD, I might end up with a whole bunch of Single-Method Services. Isn't TDD intended to make me discover my design in the first place?

I'm a .net developer, but Java resources would also work. I feel that there doesn't seem to be a real sample application or book that deals with a real line of business application. Can someone provide a clear example that illustrates the process of creating a design using TDD?

Best Answer

The idea of TDD is to start with testing and work from that. Thus, to take your example of "A catalog needs to have a list of products" could be seen as having a test of "Check for products in catalog" and thus this is the first test. Now, what holds a catalog? What holds a product? Those are the next pieces and the idea is to get some bits and pieces put together that would be something like a ProductService that will be born from getting that first test to pass.

The idea of TDD is to start with a test and then write the code that makes that test pass as the first point. Unit tests are part of this yes, but you aren't looking at the overall picture that is formed by starting with tests and then writing the code so that there aren't blind spots at this point since there isn't any code yet.


Test Driven Development Tutorial where slides 20-22 are the key ones. The idea is to know what the functionality should do as a result, write a test for it and then build a solution. The design part will vary as depending on what is required it may or may not be that simple to do. A key point is to use TDD from the start rather than try to introduce late into a project. If you start with tests first this can help and is likely worth noting in a sense. If you try to add the tests later, it becomes something that may be put off or delayed. The later slides may also be useful as well.


A main benefit of TDD is that by starting with the tests, you aren't locked into a design initially. Thus, the idea is to build the tests and create the code that will pass those tests as a development methodology. A Big Design Up Front can cause problems as this gives the idea of locking things into place which makes the system being built to be less nimble in the end.


Robert Harvey added this in the comments which is worth stating in the answer:

Unfortunately I think that this is a common misconception about TDD: you can't grow a software architecture by just writing unit tests and making them pass. Writing unit tests does influence the design, but it doesn't create the design. You have to do that.