Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to deal with interface overuse in TDD?

Tags:

I've noticed that when I'm doing TDD it often leads to a very large amount of interfaces. For classes that have dependencies, they are injected through the constructor in the usual manner:

public class SomeClass {     public SomeClass(IDependencyA first, IDependency second)     {         // ...     } } 

The result is that almost every class will implement an interface.

Yes, the code will be decoupled and can be tested very easily in isolation, but there will also be extra levels of indirection that just makes me feel a little...uneasy. Something doesn't feel right.

Can anyone share other approaches that doesn't involve such heavy use of interfaces?

How are the rest of you guys doing?

like image 650
Chris Avatar asked Mar 23 '11 21:03

Chris


1 Answers

Your tests are telling you to redesign your classes.

There are times when you can't avoid passing complex collaborators that need to be stubbed to make your classes testable, but you should look for ways to provide them with the outputs of those collaborators instead and think about how you could re-arrange their interactions to eliminate complex dependencies.

For example, instead of providing a TaxCalculator with a ITaxRateRepository (that hits a database during CalculateTaxes), obtain those values before creating your TaxCalculator instance and provide them to its constructor:

// Bad! (If necessary on occasion) public TaxCalculator(ITaxRateRepository taxRateRepository) {}  // Good! public TaxCalculator(IDictonary<Locale, TaxRate> taxRateDictionary) {} 

Sometimes this means you have to make bigger changes, adjust object lifetimes or restructure large swaths of code, but I've often found low-lying fruit once I started looking for it.

For an excellent roundup of techniques for reducing your dependency on dependencies, see Mock Eliminating Patterns.

like image 191
Jeff Sternal Avatar answered Sep 28 '22 19:09

Jeff Sternal