12

I'm writing a game in Typescript, and decided going in that I was going to try to adhere to the idea of "interface based programming", where you write code based on an interface, instead of the implementation, of an object.

I wrote up a good number of interfaces, and classes that implement them, then took a step back and realized that the classes were simple enough that I'll likely never need to change the implementation, since there's really only one way to do what the class does (moving a Phaser.Sprite in a restricted way to act like a tank).

Then I remember reading a few years ago about the idea of YAGNI, which is basically that you shouldn't over-engineer your code to include things you may never use.

Following best practices, should every class implement an interface, or should you limit it to classes that you expect to be potentially swapped out in the future?

2
  • 1
    Remember, when you use an actual class as a parameter, you're also coding to an interface, to the interface of this class. Nobody forces you to use that specific class, you could just as well inherit it and provide completely new functionality, but that does not seem right. Interfaces exist to make people wrap their heads around the idea easier. With that being sad, no, you don't really need interfaces for everything.
    – Andy
    May 2, 2016 at 18:17
  • 1
    Possible duplicate of The need for adding an interface to every class
    – gnat
    May 2, 2016 at 19:14

5 Answers 5

8

Creating an interface for every class is a bit overkill. From a purely object-oriented perspective, every class already has an interface. An interface is nothing more than the public-facing methods and data members of a class.

We typically use "interface" to mean "a Java class defined using the interface keyword" or "a C++ class with only public, pure virtual functions." These are useful abstractions, because they decouple the interface of a class from its implementation.

With that in mind, use interfaces when appropriate.

  • Will there be multiple implementations for an interface? If so, this situation may be a candidate for extracting common, public-facing methods into an interface.

  • Will I hand off implementations of a potential interface to other modules that should not know the inner workings of my module? An interface can be useful here, because it reduces the size of the touch point between modules.

Notice the weasel words above: "may" be a candidate, "can be" useful. There is no hard and fast rule that says "yes" or "no" for a given situation.

That being said, having an interface for everything is most likely overkill. If you see this pattern, you are going to far:

interface I {
  int getA()
  int getB()
  ...
  int getY()
  int getZ()
}

class C : I {
  int getA() { ... }
  int getB() { ... }
  ...
  int getY() { ... }
  int getZ() { ... }
}
6
  • One more reason for interfaces is if your testing system makes it necessary, which may depend on your language and test-framework. Hopefully you don't need to do this, of course.
    – Darien
    May 3, 2016 at 1:55
  • @Darien: The reason that a testing system may require interfaces is because the test are actually using a different (mocked) implementation, bringing you back to the first bullet of when an interface is appropriate. May 3, 2016 at 10:29
  • Some great stuff here. Just pondering this: An interface is nothing more than the public-facing methods and data members of a class. Whilst this is true for an interface implementation, it certainly does not hold true for an interface which is never implemented, although granted - this would be something of a code smell.
    – Robbie Dee
    May 3, 2016 at 11:16
  • @RobbieDee it is true for e.g. a Java interface, it just so happens that everything in the Java interface is also its public-facing interface (OO concept).
    – user22815
    May 3, 2016 at 16:28
  • Everyone! Write down the answer's 2nd & 3rd sentences. Laminate it. Put it in your wallet. Reference often.
    – radarbob
    May 4, 2016 at 21:30
10

If you are not sure if you actually need the interfaces, then you probably don't. This is the core of the YAGNI principle. When you need to be able to swap the implementation, then you introduce an interface.

7

The reason for having interfaces is because it simplifies polymorphism. Meaning you can send instances by contract rather than knowing their actual implementation. For instance, you may send a "Reader" to a method, so that such a called method can use it's "read()" method. By declaring an interface "Reader" you can make any object conform to this contract, by implementing the methods it specifies. This way, any caller may assume certain methods will exist, even if the objects underlying the contract may be completely different.

This decouples polymorphism from a base class, and makes it possible also between class chain borders, by implying a contract.

Now... This is only useful if you have the need for multiple inheritance chains to act in the same way, or if you will have many base classes with common behaviour that you will want to pass to other users.

If you only have ONE inheritance chain (baseclass->subclass) or just the base, or you have no need to actually PASS the related objects to someone else or use them generically, then you would not add interface implementations, as that notion is then useless.

1
  • I'd also add that interfaces should model abstractions, so don't create them by simply hoisting all the public members of a class. Think about what that class represents, and only put those things in the interface that any object of that type should have. You might also wind up creating multiple interfaces (e.g. Moves and Shoots for your tank example) for a single class.
    – TMN
    May 3, 2016 at 12:50
6

It can be very tempting for newer developers to think of interfaces as an inconvenience that you simply add just because you're told it is "best practice". If you are blindly doing this, it smacks of cargo cult programming.

There are a number of very good reasons that you should consider interfaces for larger developments rather than throwing together a set of classes.

Mocking frameworks

If you want to test a multi-layer application without having to craft in objects for the various layers, you'll undoubtedly want to use mocking frameworks to mock out the layers. Interfaces are used extensively here.

Dependency injection

Whilst they have fallen out of favour somewhat due to the bloat they add, the idea is sound - the ability to simply swap in concretions based on an interface. The principle can also be found in many design patterns such as the factory pattern.


These approaches are summarised in the D from SOLID principles. The rub of this is - use abstractions, not concretions.

Like design patterns themselves, when to use them is a judgement call. The takeaway point is to understand how the interfaces are useful not just stick them on your classes because you feel you have to. There is a good discussion of the various merits of DIP and YAGNI here.

3
  • 1
    Note that dependency injection and IoC containers are two completely different things (one is a design principle and the other is one way of concretely putting that principle into practice by using various frameworks). You can use DI without using an IoC container.
    – sara
    May 3, 2016 at 12:41
  • @kai "You can use DI without using an IoC container". I think more mature development shops can (and do). There is simply no need to pollute the code for what is ostensibly a simple concept. Joel is of a similar view.
    – Robbie Dee
    May 3, 2016 at 13:17
  • YAGNI is very tricky. Whatever the philosophy is, in most cases, in reality, YAGNI is used as an excuse for cutting corners. Avoid coupling should be taken more seriously. It is frustrating to see in many scrum meetings, a developer calls himself blocked because someone else did not finish their job. How come blocking another developer is saving anybody time? My suggestion is to use an interface to avoid coupling. Of course, one doesn't have to use an interface for Model classes. Jun 1, 2019 at 20:00
0

I personally don't think so, even though I have read before that you are supposed to depend on an interface, not a concrete implementation. But again, there is a lot of nuance in that. There is just no way you would have a one rule fits all. My advice would be to see what your team understands as the better, not best(because this doesnt exist) approach to take. And that's the better today, for your (you , your team) use-case, for the language you use and so on. I would not use it, unless there is a need, justification for it. Is just a waste of time, if comes to a point where in order to make your design better, an interface is necessary, then use it. Don't take things you read as a rule. People tend to read something, which most of the time doesn't fit her/his context, then they want to apply that new knowledge, which is fine, but you will eventually question. If you are against using it, but your team requires it, because is a "convention", then, move on. If you use the argument of YAGNI, and they come with the whole, but is easy to just create one just in case we need in the future, and other, judge how much is that worth your time to actually discuss that. At the end of the day, there will be a point in your career, that you set the standard (the one that get's to say the last word).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.