DEV Community

Discussion on: Code Smell 135 - Interfaces With just One Realization

Collapse
 
explorer14 profile image
Aman Agrawal

Testing needs often drive the decisions to put an implementation behind an interface. Main reason being the ability to isolate the system under test from its runtime dependencies by creating appropriate test doubles that follow the same interface. Anymore coupling, and we are talking about integrated tests which though valuable can also be expensive to maintain in the long run as the system scales and can also get flaky over time. Any valuable system with reasonably high essential complexity better be designed with a modular/component architecture and then it's only right that these components be testable in isolation from their runtime dependencies. The way to achieve that then is putting abstractions that you can create test doubles out of.

If a component is testable with its runtime dependencies without increasing the testing effort or cost significantly, then I'd forego interfaces in those narrow cases and test with the real dependencies for e.g. classes that mostly have algorithmic logic executed in memory with other algorithmic dependencies that don't do I/O or interact with external systems.

Reusable libraries is another place where interfaces are very useful as extensibility hooks for consumers to provide their own implementations for.

Indiscriminately creating an interface for every class in your code without critically thinking, is wrong! There I agree with you!

Collapse
 
mcsee profile image
Maxi Contieri

I agree with you testability is one of the most important quality attributes of a system.
Test doubles decrease the confidence of a system since you are not testing a real one.
If you need to isolate your system you can build an interface and have two implementations: one for real and one for testing. Therefore you don't have just one realization. You have two. And you are no longer in code smell scenario

That said. Your last paragraph is the most important

Collapse
 
explorer14 profile image
Aman Agrawal • Edited

How is creating an implementation for testing, not a test double?

Thread Thread
 
mcsee profile image
Maxi Contieri

You need to use real objects for testing, not mock or test objects

Thread Thread
 
explorer14 profile image
Aman Agrawal

Interfaces for external dependencies allow you the flexibility of using either a test double or a real implementation without much overhead. Arguing about that is a moot point.

There is a lot to be said about levels and granularity of testing but that's not this post!

Thread Thread
 
mcsee profile image
Maxi Contieri

Right! there also a lot of test smells, many on this series and many others to come!