Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Mastering Ninject for Dependency Injection

You're reading from   Mastering Ninject for Dependency Injection For .NET developers and architects, this is the ultimate guide to the principles of Dependency Injection and how to use the automating features of Ninject in the most effective way. Packed with examples, diagrams, and illustrations.

Arrow left icon
Product type Paperback
Published in Sep 2013
Publisher Packt
ISBN-13 9781782166207
Length 142 pages
Edition 1st Edition
Tools
Arrow right icon
Author (1):
Arrow left icon
Daniel Baharestani Daniel Baharestani
Author Profile Icon Daniel Baharestani
Daniel Baharestani
Arrow right icon
View More author details
Toc

How can DI help?


Every software application is inevitable of change. As your code grows and new requirements arrive, the importance of maintaining your codes becomes more tangible, and it is not possible for a software application to go on if it is not maintainable. One of the design principles that lead to producing a maintainable code is known as Separation of Concerns (SoC). The SoC is a broad concept and is not limited to software design; but in the case of composing software components, we can think of SoC as implementing distinct classes, each of which deals with a single responsibility. In the first example, finding a tool is a different concern from doing the operation itself and separating these two concerns is one of the prerequisites for creating a maintainable code.

Separation of concerns, however, doesn't lead to a maintainable code if the sections that deal with concerns are tightly coupled to each other.

Although there are different types of forceps that Sarah may need during the operation, she doesn't need to mention the exact type of forceps which she requires. She just states that she needs forceps, and it is on her assistant to determine which forceps satisfies her need the best. If the exact type that Sarah needs is temporarily not available, the assistant has the freedom to provide her with another suitable type. If the hospital has bought a new type of forceps that the assistant thinks is more suitable, he or she can easily switch to the new one because he or she knows that Sarah doesn't care about the type of forceps as long as it is suitable. In other words, Sarah is not tightly coupled to a specific type of forceps.

The key principle leading to loose coupling is the following, from the Gang of Four (Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, Design Patterns: Elements of Reusable Object-Oriented Software):

"Program to an "interface", not an "implementation"."

When we address our dependencies as abstract elements (an interface or abstract class), rather than concrete classes, we will be able to easily replace the concrete classes without affecting the consumer component:

class Surgeon
{
  private IForceps forceps;

  public Surgeon(IForceps forceps)
  {
    this.forceps = forceps;
  }

  public void Operate()
  {
    forceps.Grab();
    //...
  }
}

The Surgeon class is addressing the interface IForceps and does not care about the exact type of the object injected into its constructer. The C# compiler ensures that the argument passed to the forceps parameter always implements the IForceps interface and therefore, existence of the Grab() method is guaranteed. The following code shows how an instance of Surgeon can be created providing with a suitable forceps:

var forceps = assistant.Get<IForceps>();
var surgeon = new Surgeon (forceps);

Because the Surgeon class is programmed to the IForceps interface rather than a certain type of forceps implementation, we can freely instantiate it with any type of forceps that the assistant object decides to provide.

As the previous example shows, loose coupling (surgeon is not dependent on a certain type of forceps) is a result of programming to interface (surgeon depends on IForceps) and separation of concerns, (choosing forceps is the assistant's concern, while the surgeon has other concerns) which increases the code maintainability.

Now that we know loose coupling increases the flexibility and gives freedom of replacing the dependencies easily; let's see what else we get out of this freedom other than maintainability. One of the advantages of being able to replace the concrete classes is testability. As long as the components are loosely coupled to their dependencies, we can replace the actual dependencies with Test Doubles such as mock objects. Test Doubles are simplified version of the real objects that look and behave like them and facilitate testing. The following example shows how to unit test the Surgeon class using a mock forceps as a Test Double:

[Test]
public void CallingOperateCallsGrabOnForceps()
{
  var forcepsMock = new Mock<IForceps>();

  var surgeon = new Surgeon(forcepsMock.Object);
  surgeon.Operate();

  forcepsMock.Verify(f => f.Grab());
}

In this unit test, an instance of the Surgeon class is being created as a System Under Test (SUT), and the mock object is injected into its constructor. After calling the Operate method on the surgeon object, we ask our mock framework to verify whether the Grab operation is called on the mock forceps object as expected.

Maintainability and testability are two advantages of loose coupling, which is in turn a product of Dependency Injection. On the other hand, the way an Injector creates the instances of concrete types, can introduce the third benefit of DI, which is the late binding. An Injector is given a type and is expected to return an object instance of that type. It often uses reflection in order to activate objects. So, the decision of which type to activate can be delayed to the runtime. Late binding gives us the flexibility of replacing the dependencies without recompiling the application. Another benefit of DI is extensibility. Because classes depend on abstractions, we can easily extend their functionality by substituting the concrete dependencies.

lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image