Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it the best practice to extract an interface for every class?

I have seen code where every class has an interface that it implements.

Sometimes there is no common interface for them all.

They are just there and they are used instead of concrete objects.

They do not offer a generic interface for two classes and are specific to the domain of the problem that the class solves.

Is there any reason to do that?

like image 578
the_drow Avatar asked Jun 14 '10 11:06

the_drow


People also ask

Should you make an interface for every class?

In most cases, a final class is the best thing you can create. If a user doesn't like your class, they can simply choose not to use it. However, if you're building up a hierarchy of objects you should introduce an interface for every class.

When should you extract an interface?

Use Extract Interface to explicitly indicate which role. Another convenient case arises when you need to describe the operations that a class performs on its server. If it's planned to eventually allow use of servers of multiple types, all servers must implement the interface.

Should every object have an interface?

It all depends... Oh yes, and if you do go heavily into interfaces - beware web services. If you need to expose your object methods via a web service they can't really return or take interface types, only concrete types (unless you are going to hand-write all your own serialization/deserialization).

Should you always use interfaces?

No, every class should not have an interface. It's overkill squared. You use an interface when you need to abstract what's done from how it's done, and you're certain that the implementation can change.


2 Answers

No.

Interfaces are good for classes with complex behaviour, and are especially handy if you want to be able to create a mock or fake implementation class of that interface for use in unit tests.

But, some classes don't have a lot of behaviour and can be treated more like values and usually consist of a set of data fields. There's little point in creating interfaces for classes like this because doing so would introduce unnecessary overhead when there's little point in mocking or providing alternative implementations of the interface. For example, consider a class:

class Coordinate {   public Coordinate( int x, int y);   public int X { get; }   public int y { get; } } 

You're unlikely to want an interface ICoordinate to go with this class, because there's little point in implementing it in any other way than simply getting and setting X and Y values.

However, the class

class RoutePlanner {    // Return a new list of coordinates ordered to be the shortest route that    // can be taken through all of the passed in coordinates.    public List<Coordinate> GetShortestRoute( List<Coordinate> waypoints ); } 

you probably would want an IRoutePlanner interface for RoutePlanner because there are many different algorithms that could be used for planning a route.

Also, if you had a third class:

class RobotTank {    public RobotTank( IRoutePlanner );    public void DriveRoute( List<Coordinate> points ); } 

By giving RoutePlanner an interface, you could write a test method for RobotTank that creates one with a mock RoutePlanner that just returns a list of coordinates in no particular order. This would allow the test method to check that the tank navigates correctly between the coordinates without also testing the route planner. This means you can write a test that just tests one unit (the tank), without also testing the route planner.

You'll see though, it's quite easy to feed real Coordinates in to a test like this without needing to hide them behind an ICoordinate interface.

like image 53
Scott Langham Avatar answered Sep 22 '22 19:09

Scott Langham


After revisiting this answer, I've decided to amend it slightly.

No, it's not best practice to extract interfaces for every class. This can actually be counterproductive. However, interfaces are useful for a few reasons:

  • Test support (mocks, stubs).
  • Implementation abstraction (furthering onto IoC/DI).
  • Ancillary things like co- and contra-variance support in C#.

For achieving these goals, interfaces are considered good practice (and are actually required for the last point). Depending on the project size, you will find that you may never need talk to an interface or that you are constantly extracting interfaces for one of the above reasons.

We maintain a large application, some parts of it are great and some are suffering from lack of attention. We frequently find ourselves refactoring to pull an interface out of a type to make it testable or so we can change implementations whilst lessening the impact of that change. We also do this to reduce the "coupling" effect that concrete types can accidentally impose if you are not strict on your public API (interfaces can only represent a public API so for us inherently become quite strict).

That said, it is possible to abstract behaviour without interfaces and possible to test types without needing interfaces, so they are not a requirement to the above. It is just that most frameworks / libraries that you may use to support you in those tasks will operate effectively against interfaces.


I'll leave my old answer for context.

Interfaces define a public contract. People implementing interfaces have to implement this contract. Consumers only see the public contract. This means the implementation details have been abstracted away from the consumer.

An immediate use for this these days is Unit Testing. Interfaces are easy to mock, stub, fake, you name it.

Another immediate use is Dependency Injection. A registered concrete type for a given interface is provided to a type consuming an interface. The type doesn't care specifically about the implementation, so it can abstractly ask for the interface. This allows you to change implementations without impacting lots of code (the impact area is very small so long as the contract stays the same).

For very small projects I tend not to bother, for medium projects I tend to bother on important core items, and for large projects there tends to be an interface for almost every class. This is almost always to support testing, but in some cases of injected behaviour, or abstraction of behaviour to reduce code duplication.

like image 20
Adam Houldsworth Avatar answered Sep 23 '22 19:09

Adam Houldsworth