Tuesday, May 24, 2011

Dependency injection - a practical approach

What do we want to achieve when we are coding? I mean, which are the quality attributes of a code that define it as a GOOD piece code? Well … we all know that the response to these questions is: “it depends, it depends on the problem”. Despite of the fact that this is actually true (it is a correct answer, we should define out software quality attributes before coding), we usually want our code to be at least extensible, testable and readable:

  • Extensible because we think that our code will be reuse in the future (yes, right :-s).
  • Testable because we are force to create unit tests for our classes (nowadays committing code without test is unacceptable) , and
  • Readable because we might think that our code will be read in the future and we want it to be understood (actually, you don’t want to be bother in the future with questions about things we wrote and don’t remember)

Ok, but … why is it related to dependency injection? Well … dependency injection is a design principle that would help us to achieve these goals. To make it clear, dependency injection defines that “your class should be configured with its collaborators by using constructors or setters”. This is the most practical and simple definition I could think of.


Let me show you a common example of code,




And the usage of the class would be:



Let’s first analyze readability. When we see the code of the class Service we can say that “Service builds a Report for a particular country BY READING INFORMATION FROM THE DATABASE”. But, when we read the usage of the class what we know is that “Service builds a Report for a particular country”. Do you see the difference? When we use the class Service we don’t know if we are going to connect to the database or if the information comes from a web service or whatever. This becomes a problem when we read the code because we are forced to go into the Service class and look into its implementation just to realize that it actually reads information from the database. Hmmm … but isn’t it what encapsulation is all about? …… NO, encapsulation is not hiding information, it just hiding implementation and prohibiting the direct manipulation of the internal state of the class from the outside.


This readability issue may be seen as stupid for this particular example, because Service class is quite simple, short and easy to read. But is different when we are working with some real code in real applications where you don’t have one class, you have thousands! When we read code we want it to be as much as expressive as we can, we want to have all the information of what that class does, maybe not how it does it, but we want to be aware of things like database connectivity, for example.

Now let’s check extensibility. The responsibility of the class Service is to “Build a Report for a particular country by reading the database information”. Hmmm … there is something that seems to be wrong, right?, if we look at the code of service there is nothing that connects the Service functionality with the database. I mean, from my perspective the Service class creates a report. To achieve this, it needs the clients and the accounts. In the particular case of out example, we see that the Clients and Accounts come from the database, but this should be a detail of implementation only. Do you see where I’m going? With the implementation of Service as it is, we have a strong relation between the building of a report and the database connectivity. We shouldn’t have this, because we don’t have a good separation of concerns in our code. If we want to change the information resource (let’s say a web service) we will have a problem with our service implementation. Or we will have to create another service class that uses a web service to create the Report. This is an example of poor extensibility; the service class can only be used to create a Report from the database.

Finally, let’s take a look at testability. How do we create a unit test for Service? Focus on the word UNIT, we only want to test Service and not the database connectivity, it seems very hard to do because of the new instruction inside the constructor of Service. If we want to mock the Database connectivity we have a problem and we need to do a lot of ad hoc things just to avoid going to the database. Testability is very important because with a test we can establish the expected functionality of the class (doing Test is not testing).

A few lines and a lot of problems, hug? Let’s see the same implementation with dependency injection:



And it’s usage,




Now our class is more readable, extensible and testable.

It is more readable because we have more information when we use the class than when we see its code. When we see the code we know that “Service creates a Report using an external resource to gather information”, but when we see the usage, we know that “Service creates a Report using a Database connection to gather information”.

It is more testable because it is easier to mock the database connection, we can test what service does without worrying about the database connectivity, we just mock it.
It is more extensible because it is quite simple to change the behavior of the class service, if we want it to connect to the database we inject a DBConnector, however, if we want it to connect to a web service, we just create an ExternalResource implementation that connects to a web service and retrieves the clients and accounts.

Of course we can talk about other benefits of dependency injection like coupling reduction or interface programming, but these are much related to the extensibility of a class. I wanted to show a real example of the gain of using dependency injection in our code. I didn’t want to write a lot about all the theory behind it in this post, but I could write something more specific in the future without sounding like a book.




I hope this helps to understand!



1 comment: