I feel like using Dependency Injection is changing the way I write my object oriented code. For instance, below is what I would do without DI
Interface: DataAdapter
SqliteDataAdapter implements DataAdapter
XMLDataAdapter implements DataAdapter
OracleDataAdapter implements DataAdapter
// Initialization
DataAdapter adapter = new SqliteDataAdapter();
DataAdapter adapter = new XMLDataAdapter();
DataAdapter adapter = new OracleDataAdapter();
but using DI my code structure would be:
Interface: DataAdapter
SqliteDataAdapter implements ISqliteDataAdapter, DataAdapter
XMLDataAdapter implements IXMLDataAdapter, DataAdapter
OracleDataAdapter implements IOracleDataAdapter, DataAdapter
// Initialization
ISqliteDataAdapter adapter = new SqliteDataAdapter();
IXMLDataAdapter adapter = new XMLDataAdapter();
IOracleDataAdapter adapter = new OracleDataAdapter();
The reason for this change is that in my module I can bind 1 interface to 1 class.
Is this a bad practice? If yes what is the correct solution?
Doesn’t DI change the whole purpose of using interfaces?
EDIT:
The following is my binding for DI container
bind(ISqliteDataAdapter.class).to(SqliteDataAdapter.class);
bind(IXMLDataAdapter.class).to(XMLDataAdapter.class);
bind(IOracleDataAdapter.class).to(OracleDataAdapter.class);
If i do as suggested, how would I be able to use multiple adapters? What if I need to use both XMLDataAdapter and SQLDataAdapter in my application?
bind(DataAdapter.class).to(SqliteDataAdapter.class);
Edit:
Here is the current call to get an instance:
@inject protected ISqliteDataAdapter dataAdapter;
Here is how I should do it with having 1 interface only:
@inject protected DataAdapter dataAdapter;
// In this case I don't have a choice on which type of data adapter It's going to create
// It's already defined in my module file and it's pointing to one of the 3 DataAdapters
So what I’m trying to understand is, how can I structure my code in a way that I have control over the type of object it’s injecting, without having interface for every type of DataAdapter.
I would say that DI is a natural consequence of having interfaces. The reason we have interfaces is so that we can write code that doesn’t depend on particular class, but instead an work with a multitude of classes without any changes. Even if we expect there to only be one class which does we need, this may change in the future. By programming to interface, we can even account for changes we can’t imagine.
DI just uses the above notions in a peculiar way, to maximize the testability and adaptability of code. So I would say the DI is a really good practice.
That said, I think there is one warning to be issued for anyone involved with these kinds of systems. There’s the danger that we write full-fledged classes like your
SqliteDataAdaptor, and then push a “extract the interface” button to give theISqliteDataAdaptorinterface. This practice is very bad, particularly if it happens a lot. Instead,ISqliteDataAdaptorshould usually be designed first, and then a sensible implementation can be written.