Stop Overusing Interfaces (2017) (opens in new tab)

[Illustration from simpleprogrammer.com]

Do you use Dependency Injection? Of course you do, you’re a responsible programmer, and you care about clean, maintainable, SOLID code with low coupling. You know perfectly well that New is Glue, and you understand the value of programming to interfaces, not implementations.

So do I, but please note that none of this means you should pair each and every one of your domain classes with a more or less identical interface. I suggest that you should prefer working with your concrete domain classes instead. This may sound like a dirty hack to you, but my claim is that doing this will in fact improve the quality of your code. Pairing every class with an interface, on the other hand, is an anti-pattern.

Programming to interfaces means you should try to use the most generic abstraction available to you when you program. If you have a queue of people and you need a utility method to find the tallest person, you should not do this:

public int Tallest(Queue<Person> people)
{
return people.Max(p => p.Height);
}

That method does not need to care whether the collection of people is a Queue or something else, so you follow ReSharper’s advice and do this:

public int Tallest(IEnumerable<Person> people)
{
return people.Max(p => p.Height);
}

However, this does not mean that if you have a domain class Foo that you need to handle somewhere, you must first create the interface IFoo and handle that:

public void ProcessFoo(IFoo foo)
{
...
}

Perhaps you do this because you think it is dictated by SOLID, DDD or DI, but the reality is that you are in fact introducing unnecessary complexity and duplication of code, violating YAGNI, and lowering readability and maintainability of the codebase.

So what’s actually the problem? Well, the thing is that all classes already expose interfaces to begin with. The set of all non-private class members is an interface. If you decide to create an interface IFoo definition that matches the public members of Foo, you will simply have duplicated the interface of Foo and added no real abstraction and zero value. Browsing code like this is no fun whenever you go to a definition, expecting to get to a class implementation, and just ending up in an interface, where you need to do another step to go to the implementation.

But I need this interfaces to make Dependency Injection work, I hear you say. No, you don’t. Let me demonstrate. Let’s say you have a method that needs to call a domain object in order to create an order:

Loading more...

Keyboard Shortcuts

Navigation
Next / previous item
j/k
Open post
oorEnter
Preview post
v
Post Actions
Love post
a
Like post
l
Dislike post
d
Undo reaction
u
Save / unsave
s
Recommendations
Add interest / feed
Enter
Not interested
x
Go to
Home
gh
Interests
gi
Feeds
gf
Likes
gl
History
gy
Changelog
gc
Settings
gs
Browse
gb
Search
/
General
Show this help
?
Submit feedback
!
Close modal / unfocus
Esc

Press ? anytime to show this help