GetNoticed IT#3: S-O-L-I-Dependency Inversion Principle

Hi there!
One day I want to be professional dev. In order to do that I need not only to write something that works but also is written in proper manner. What that means? Every time that matter is discussed conclusion is always the same: properly written code is simple, testable, easily maintainable and expandable. Some time ago ca. 2000 a set of rules was established to achieved that. These rules were defined by Robert Martin and Michael Feathers and are called SOLID.

S – Single Responsiblity Principle
O – Open/Closed Principle
L – Liskov Substitution Principle
I – Interface Segregation Principle
D – Dependency Inversion Principle

Some say that the last one is the most important (for instance, founder of Get Noticed contest here: as it allows developers to write loosely coupled (internal dependencies-wise) applications. For that very same reason I will start this short series of posts about SOLID principles.

High-level modules should not depend on low-level modules. Both should depend on abstractions.
Abstractions should not depend on details. Details should depend on abstractions.

It would be best to explain that using an example. Assume that we’re building an application to handle purchase orders. Let’s consider this small piece of code:

In our application we have two classes: Item which describes items we have to sell; and OrderHandler which handles an actual order by adding tax and shipping cost. In this case class OrderHandler depends on class Item. That is DIP violation. To fix it we need to abstract Item class.

In the code above there is ICanBeSold interface defined which has only one get-only property. That’s enough for our OrderHandler as it has only one method that returns total cost of ordering an item. That creates loose coupling between items and item orders. Changes in Item class would not inflict errors in OrderHandler (of course as long as it implements ICanBeSold interface). Another benefit of that is the fact that you can create multiple classes which can be used in OrderHandler.

Dependency Injection
Neat and nimble way to follow the DIP rule is dependency injection. This pattern is about designing your classes in a way that they use abstractions instead of concrete classes and whenever you need a concrete object to be used you hand the object to the class through class constructor, a method’s parameter or through property.

Injection through constructor
Let’s rebuild our application so different rules of discounting can be applied. For instance, we need to allow free shipping sale and abroad shipping. In order to achieve that we’ll create new class called PriceCalculator.

Take a look at the code above. Now OrderHandler class can be used to sell anything that implements ICanBeSold interface by rules set by anything that implements IPricingRules interface. What is that going to be is now passed to OrderHandler in its constructor.

So, actually there are two dependencies injected through the constructor.

Dependency injection through a method
If our OrderHandler is going to be used to do something more than perform one-time action it might be better to consider injecting a dependency through its method. It is very similar to what I have described above. The difference is that the dependency is given as a parameter to one of methods available in high level class. Let’s rebuild our OrderHandler again:

In the example above IPricingRules is injected to ProceedeSale method. That allows us to use different rules every time we want to do the sale. The example above has been simplified slightly by replacing item injection by simply giving its value in OrderHandler constructor. Now, take a look a the code below:

We’re proceeding with the sale twice but each proceeding has its own rules defined by IPricingRules implementation.

Injecting through property
Another way to inject a dependency is through property. In this case we simply create a IPricingRules property with both getter and setter. Now, every time we want to change pricing rules we simply set value of this property. Our rebuilt OrderHandler would look like that:

And here’s its usage:

Other means
However simple Dependency Injection is and, I presume, most common way to follow the DIP it isn’t the only way. For example, a delegate can also be considered as a way to achieve dependency inversion since a delegate is also form of abstraction. Let’s again rebuilt our OrderHandler class and equip it with a delegate to use for custom sales:

And its usage:

In the above we’re using Lambda expression as a delegate but here we could set whatever method we want including one from different class.
So, these are basics of Dependency Inversion Principle and Dependency Injection. Here are some recommendations where to look for further information about the topic:

In my next posts I will continue about SOLID principles and plausibly at some point I will write a post also about dependency injection containers.
So, thanks for reading today. In my case SOLID principles redefines how I should write code. This means that I need to restart my project again. But, as I see it, it is better  to write good code and maybe finish the project with delay or in impoverished version than to write something that works but is crap.
Good luck!