16

I hear a lot from TDD practitioners that one of TDD's advantages is that it forces developers to follow SOLID principles (Single responsibility, Open-closed, Liskov substitution, Interface segregation and Dependency inversion). But as for me it is enough to just write some tests (unit test primarily) to understand it is important to follow SOLID (and thus create testable architecture).

Does TDD force developers to follow SOLID more actively than just writing unit tests?

3
  • 1
    TDD is mainly about forcing developers to write tests. So if you say writing unit tests makes you write SOLID code, I guess that says that TDD forces you to write SOLID code. This is just based on what you've said, though, and does not accurately reflect my opinion, which you can see in my answer. Oct 1, 2011 at 19:04
  • 1
    Yam: I will disagree, TDD is not about writing unit tests. TDD is about coming to a minimally complex and correct solution for the problem at hand. Tests are just a by-product of the procedure Oct 2, 2011 at 4:29
  • TDD by definition is about writing tests before code. Theoretically you can create a minimally complex and correct solution even without tests. The tests simply give you instant feedback and regression awareness. Since it is still possible to create an over-complex solution with tests, TDD is not about creating minimally complex solutions per se. It's the opposite of what you've said. Elegant solutions are a by-product of the procedure, not the other way around. Oct 2, 2011 at 11:59

4 Answers 4

26

First of all, TDD does not strictly force you to write SOLID code. You could do TDD and create one big mess if you wanted to.

Of course, knowing SOLID principles helps, because otherwise you may just end up not having a good answer to many of your problems, and hence write bad code accompanied by bad tests.

If you already know about SOLID principles, TDD will encourage you to think about them and use them actively.

That said, it doesn't necessarily cover all of the letters in SOLID, but it strongly encourages and promotes you to write at least partly SOLID code, because it makes the consequences of not doing so immediately visible and annoying.

For example:

  1. You need to write decoupled code so you can mock what you need. This supports the Dependency Inversion Principle.
  2. You need to write tests that are clear and short so you won't have to change too much in the tests (which can become a large source of code noise if done otherwise). This supports the Single Responsibility Principle.
  3. This may be argued over, but the Interface Segregation Principle allows classes to depend on lighter interfaces that make mocking easier to follow and understand, because you don't have to ask "Why weren't these 5 methods mocked as well?", or even more importantly, you don't have a lot of choice when deciding which method to mock. This is good when you don't really want to go over the whole code of the class before you test it, and just use trial and error to get a basic understanding of how it works.

Adhering to the Open/Closed principle may well help tests that are written after the code, because it usually allows you to override external service calls in test classes that derive from the classes under test. In TDD I believe this is not as required as other principles, but I may be mistaken.

Adhering to the Liskov substitution rule is great if you want to minimize the changes for your class to receive an unsupported instance that just happens to implement the same statically-typed interface, but it's not likely to happen in proper test-cases because you're generally not going to pass any class-under-test the real-world implementations of its dependencies.

Most importantly, SOLID principles were made to encourage you to write cleaner, more understandable and maintainable code, and so was TDD. So if you do TDD properly, and you pay attention to how your code and your tests look (and it's not so hard because you get immediate feedback, API and correctness wise), you can worry less about SOLID principles, in general.

1
  • Also unless you follow Open/closed and Liskov substitution your mocks will break later on. So even if TDD might not help you enforce OCP and LSP the tests created will let you know when you break it. More an effect of testing in general, but still worth mentioning. Jun 1, 2015 at 8:40
9

No

TDD can make it easier to follow good practices because of the continuous refactoring, but it doesn't force you follow any principle. All it does is make sure the code you write is tested. You can follow whatever principles you like when writing code to satisfy the test; or no principles at all.

2

My understanding of the SOLID Principles expanded by an order of magnitude when I started doing TDD. As soon as I started thinking about how to mock dependencies I realized virtually every component in the code base had a potential alternate implementation. And how much easier it is to test a simple public API.

It also provided a much stronger understanding of most design patterns. Especially the Strategy Pattern.

0

Yes: TDD is mainly a good design technique (and only secondary a testing technique). It helps very much to achieve the solid principles, though (pathological) examples of TDD with a lot of code smells are still possible.

The connection between TDD and the solid principles are disputed (with the conclusion above) in this great hanselminute podcast named "Test Driven Development is Design - The Last Word on TDD".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.