15

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?

Carcigenicate
  • 2,673
  • 3
  • 25
  • 39

5 Answers5

12

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.

JacquesB
  • 61,955
  • 21
  • 135
  • 189
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() { ... }
}
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.

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.

Robbie Dee
  • 9,823
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).