I've been reading about DI and best practices, and still haven't found the answer to this question. When should I use interfaces?
- Some developers suggest to add interface for every object that is being injected. This would make a modular application.
- Some other are against this.
So my question is which one is correct?
EDIT:
Below are the two sides, I still don't see the advantage of using interfaces. In both cases I can easily mock classes, and change the implementations
Using interfaces
bind(IUserStorage.class).to(UserStorage.class);
// Unit test
bind(IUserStorage.class).to(Mock(UserStorage.class));
Not using interfaces
bind(UserStorage.class).to(UserStorage.class);
// Unit test
bind(UserStorage.class).to(Mock(UserStorage.class));
I can't believe using interfaces is againt OOP principles!
I would definitely use interfaces in this scenario. It means you're loosely coupling your components and can easy mock and/or substitute alternatives. Lots of DI frameworks will use the interfaces in order to provide additional functionality (e.g. create proxy objects mapped to the real objects, but with additional features).
As such I would try and use interfaces for all but the most trivial of injected objects. At some stage you're going to want to make use of substitutability, framework code generation etc. and retrofitting interface usage is an additional pain that it's easy to avoid at the beginning of a project.
Interface based design is the cornerstone of IoC, here is a short description of Interface-based design (Sorry that I'm referencing my own blog, but I just finished an article about this, it was an extract from my MS Thesis):
Nandigam et al. defines Interface-based design as "a way of developing
object-oriented systems where one consciously and proactively defines
and uses interfaces wherever possible in a design to reap the benefits
of designing with interfaces" [Nan09]. Applications with an
interface-based design follow the principle "program to an interface,
not an implementation". This principle brings the following benefits
to the resulting system [Dav03]: flexibility (describes the system
robustness to change), extensibility (the ease with which a system may
accommodate additions) and pluggability (the ability that allows
substitutions of objects with identical interfaces at run-time).
Once you mix interface design with IoC you obtain the following benefits:
- Tasks are decoupled from the implementation.
- Increases modularity where modules rely on other modules solely on their contracts (interfaces).
- Increases pluggability and replacing a module does not have a cascading effect on other modules.
To answer your question, I would use interfaces for different types of modules. For example, one per service or repository.
I do not create interfaces for controllers or Model classes (MVC apps).
All this, as a side effect, facilitates testing.
If you use interfaces or at least abstract/inheritable classes you can change the behaviour of the program by an easy exchange of the implementation (inject another class) in the DI/IoC config.
Using interfaces is a good practice (imho). This is especially very important if you are writing UnitTests which needs mocks. It is much harder to write UnitTests with a good coverage (not to say impossible in most "real world" cases) if you're not using interfaces.
I think you should use an interface if there might be a chance that the injected part could change. It should be easy to extend your implementation, see Open-Closed-Principle. => This will require the exchange of modules/parts/implementations... ask yourself what would happen if your class has no virtual functions to override and you are forced to change the implementation.
I would use interfaces at least for the public classes / parts of your code (the parts other programmers would use).
Having a look at your sample. The problem is at the wiring part and not only the binding of a class as (default) implementation of an interface (binding works, but wiring could break).
For example if you have 2 implementations (C# sample here, should be the same in Java etc., too):
public interface IUserStorage
{
void Write(object something);
}
public class UserStorageTextFile : IUserStorage
{
public void Write(object something) { ... }; // stores to text file
}
public class UserStorageDB : IUserStorage
{
public void Write(object something) { ... }; // stores to DB
}
public class MyStorageClient
{
public MyStorageClient(IUserStorage storage) { ... } // copy to private field and use it etc.
}
Depending on your IoC it should be easy to wire
an instance of MyStorageClient to your binding of IUserStorage.
bind(IUserStorage.class).to(UserStorageDB.class); // Java sample, eh?
But if your MyStorageClient is strongly forced to use DB already...
public class MyStorageClient
{
public MyStorageClient(UserStorageDB storage) { ... } // copy to private field and use it etc.
}
... it is imposible to wire it up with the UserStorageTextFile class except the UserStorageTextFile is inherited from UserStorageDB... but why should you have a dependency to e.g. Oracle drivers (required by UserStorageDB) if you only want to write a simple text file?
I think the sample is clear enough and shows up the benefits of using interfaces...
but if not... try to do this:
bind(UserStorageDB.class).to(UserStorageTextFile.class);
// and in another config/module/unitTest
bind(UserStorageTextFile.class).to(Mock(UserStorageDB.class));
// and try to wire it against your client class, too (both ways, meaning one config for TextFile and load a config for the DB after changing only the configuration)
Your question states "some developers [are for this]" and "some developers [are against this]", so there is no right answer. But this is why I agree that interfaces are overused
If you are creating a library, choosing when to use interfaces is important. It is harder to create a maintainable contract when you don't control how your code is consumed.
If, however, you are creating an application, it less likely to require an interface, because the public interface of a class can serve as the maintainable contract to consuming code. Let's say version 1 looks like this:
public class UserStorage
{
public void Store(User user) { /* ... */ }
}
You don't even need refactoring tools to change it to this:
public interface UserStorage
{
public void Store(User user);
}
class TheImplementation implements IUserStorage
{
public void Store(User user) { /* ... */ }
}
Then you can easily use refactoring tools to rename the interface to IUserStorage
.
So when you are writing non-library code, you can usually get away with a class until you need swappable implementations, decorators, etc. You should use an interface when the public interface of the class does not suit your needs. (For example, see the interface segregation principle)
In short - having an interface that is 1:1 with a class is unnecessary indirection in application code.