Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

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?

share|improve this question
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. –  Yam Marcovic Oct 1 '11 at 19:04
    
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 –  Amit Wadhwa Oct 2 '11 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. –  Yam Marcovic Oct 2 '11 at 11:59
add comment

4 Answers

up vote 19 down vote accepted

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.

share|improve this answer
add comment

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.

share|improve this answer
add comment

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.

share|improve this answer
add comment

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 "TDD is design".

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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