DEV Community

Cover image for Death by Interfaces?

Death by Interfaces?

Matt Eland on January 19, 2020

This might be an unpopular opinion, but we might be doing more harm than good with interfaces in object-oriented programming languages. Let me exp...
Collapse
 
softchris profile image
Chris Noring

Yea in my experience Base classes has been horrendous. Because ppl walk all over Liskov substitution principle. First, they have an inheritance in 20 levels and somewhere in that chain they simply don't implement all methods, they become empty or have NotImplementedException as only code line.. This is way worse than fat interfaces imo.. We just need to keep fighting this in code reviews in my opinion, don't just mindlessly extract interfaces but defend why it's needed. Or if base classes is your go to then cap the limit of 2 levels of inheritance before it spirals out of control.

Collapse
 
baskarmib profile image
Baskarrao Dandlamudi

One benefit to use Interface is it provides good support for writing mock tests and today’s dependency injection is tied to interfaces. These are the reasons for their increased usage in today’s applications. 100% agree to your thoughts.

Collapse
 
integerman profile image
Matt Eland

I agree. I thought of this when writing my article but forgot to work it into the base class vs interface discussion - many mocking frameworks can work with base classes instead of interfaces and some can even work with concrete classes.

Collapse
 
makdeniss profile image
Deniss M

There are so many things wrong in the article, I don't even know where to start.

Advising against using interfaces and using the base abstract class? Are we going back to the 90s?

Collapse
 
timothymcgrath profile image
Timothy McGrath

I think in general, interfaces are the right choice over base classes. However, putting an interface on every class you write isn't necessary. Only add them when they provide value for testing, DI, or architecture.

But the tooling has improved enough to quickly go to the implementation of the interface. In VS, you can use CTRL + F12.

Collapse
 
scotthannen profile image
Scott Hannen • Edited

If we're misusing interfaces - which we are - the questions are how should we use them, how are we using them incorrectly, and perhaps when are we using them without needing them?

Death by.... We're doing more harm than good with ... We can fill in the blanks with pretty much anything.

The underlying problem I see behind the abuse of interfaces is that we don't understand what abstractions are for. We don't design abstractions and then implement them. We build whatever classes we're going to build and keep them wrapped in 1:1 corresponding interfaces. We get the benefit of mocking but not much else.

I get more benefit from interfaces when I use them to describe what another class must depend on, from the perspective of that class. That leads to small, cohesive interfaces.

It also leads to writing the code I need, as opposed to creating dependencies first and then creating their consumers around them.

Collapse
 
rolfstreefkerk profile image
Rolf Streefkerk

This discussion probably ties in well with unit testing. Imo, creating fine grained unit tests is a waste of time and a maintenance nightmare.

Here the interfaces come in very handy, we test against the interfaces only and we get decent code coverage and a good handle on code quality without going overboard.

Collapse
 
seankearon profile image
seankearon

There is certainly a place for interfaces in any good design. However, I completely agree that they are overused and that we should think twice about whether we really need them when we add them.

Sure, this goes against "accepted wisdom" and does not sit well for a lot of people. But, it's good to question what we do and why we do it. Cargo cult driven development is a very easy habit to slip into!

In particular, I absolutely hate introducing an interface just to be able to write some unit tests for some component. I avoid doing that whenever possible.

I think I remember someone blogging or tweeting to say "every time I add an interface to my code I feel like I've failed". I might be wrong but I think was Paul Stovell aka Mr Octopus Deploy.

Thanks for a great article!

Collapse
 
djnitehawk profile image
Dĵ ΝιΓΞΗΛψΚ

would like to share a few awesome videos regarding this subject matter:

i personally try to avoid di, mocking and interfaces as much as possible and only use them when absolutely necessary.

as long as my intergration tests are on point then maintenance and evolving my apps is a breeze.

Collapse
 
jeastham1993 profile image
James Eastham

Fascinating article Matt sand really interesting points.

I love interfaces and think the decoupling they bring are a huge plus to refactoring without worry.

That said, I do massively agree with your point on legibility. Being able to jump to the definition of an object is really useful, with interfaces you lose that.

I find myself jumping between interfaces, the DI creation (startup.cs) for example and actual definitions which can be a pain.

I try to minimise interfaces where possible, only using them where I think there is a true need for easy substitution (database interactions being a primary candidate).

Collapse
 
macsikora profile image
Pragmatic Maciej

Instead of changing something in one place, I have to navigate to the interface and change it there as well. If there were any other implementations of that interface, I need to seek them out and make sure they’re changed as well.

Interface does not define the implementation so change naturally is less often as it's more generic. I think the case when one specific implementation effect the interface used in many other places is in most wrong approach.

Interface defines behavior of some group of objects then change of the interface should effect all, and it is a good thing.

If we have that one member is different from others then we need to think if the member fits the group, maybe not, maybe group was wrongly defined.

My biggest issue with class inheritance is method overload where we can have multiple level of inheritance with overloaded implementations. That means that probably our group is totally broken and the original class has nothing to it's members.

Collapse
 
happydevops_mx profile image
Gustavo Sánchez

Well, I like your opinion about design implications when you implement interfaces. There is no silver bullet when you are building a system architecture, only implications. All styles, paradigms, frameworks, languages, all of them have good and bad implications.
The real metrics about good design are a system cheap to maintain, build, test and deploy.

Collapse
 
integerman profile image
Matt Eland

I think you hit the nail on the head with my central point. This piece struck a nerve and got dog piled on, but what I really want is for people to recognize the tradeoffs we make and the prices of things. Use what works, but make conscious choices about it.

Collapse
 
donut87 profile image
Christian Baer

Stop putting capital Is in front of your interface name. I don't care whether my type is from interface definition or a base class. This just clutters code. If you need to emphasise, that this type is an interface, you are already on the track of being doomed.

Collapse
 
ashoutinthevoid profile image
Full Name

🤣
The article doesn't make me too hopeful, but maybe some time in Rust or Go would alter his opinion. I'm certainly mildly curious about his experience with either language and how he might approach architecture there.

Collapse
 
burdier profile image
Burdier

i disagree, what about test?

Collapse
 
riscie profile image
riscie

I disagree with almost every point in the article. But we don't need to be all the same right :) Thanks for writing it down.