While reading through Martin Fowler’s Patterns of Enterprise Application Architecture, I came across this sage advise regarding when and why to use interfaces while reading about the Separated Interface pattern.
I come across many developers who have separate interfaces for every class they write. I think this is excessive, especially for application development. Keeping separate interfaces and implementations is extra work, especially since you often need factory classes (with interfaces and implementations) as well.
For applications I recommend using a separate interface only if you want to break a dependency or you want to have multiple independent implementations. If you put the interface and implementation together and need to separate them later, this is a simple refactoring that can be delayed until you need to do it.
I know that I have been guilty of using too much abstraction and I have felt the pain of doing so. When you use too many interfaces, you substantially increase the overhead and boilerplate necessary to implement any given feature. A more pragmatic approach is to rely upon the implicit interface that is attendant with every class. The truth is that it is easy to refactor an interface away from an implementation using modern IDEs.
Robert C. Martin says that it is best to delay making some architectural decisions for as long as is reasonably possible. Delaying the decision to add interfaces for some implementations is one of those decisions.
Fowler provides these guidelines on when to use a separated interface:
- Abstract framework code that needs to call application code
- Code in one layer that needs to call code in another layer that it shouldn’t see
- When you need to call code developed by another group but don’t want a dependency on it
This research led me to do a bit more searching and inquire a bit further as to “when to interface.” Matthias Noback wrote an excellent article on the pragmatic usage of interfaces.
His guidance on when to interface is:
- If you foresee that the user wants to replace part of the object hierarchy
- If you want to introduce an abstraction for multiple specific things
- If the class depends on third-party code
- If the class uses I/O (including network calls)
- If not all public methods are meant to be used by regular clients (i.e. the Interface Segregation Principle)
However, there are several types of classes where it doesn’t make sense to add interfaces to them. They mainly have to do with your application. Adding interfaces to these classes often makes little sense because of the increased overhead. Mathias provided additional guidance here:
What these types of classes have in common is that it’s not at all needed nor desirable to swap their implementations out. More specifically, some good examples of these classes are:
- Value objects
- Domain services
- Application services
The reason is that these are classes from the domain or application layer.