[Design Patterns] Dependency Injection

The “Dependency Injection” is a kind of misnomer or rather a confusing term. In short, it is a way to set an object variable in a loosely coupled way. That’s all. But do not misjudge the effect of this just because of its simplicity. It is a very good tool when it is used properly.

 

1. Sample Business Requirement

Now you’re developing a desktop application for product management. The product information needs to be persisted in DB or a file. It comes with three flavors.

  • Enterprise Edition: uses a dedicated SQL Server
  • StandAlone DB Edition: uses a Sybase DB in a user’s workstation
  • StandAlone File Edition: uses a text file in a user’s workstation

As a first step, you created a “Product” class as a domain model. Now you want to create DAL(Data Access Layer) of the “Product” class.

What can you do?

The simplest approach is to create a single “ProductSerializer” class and provide methods for all possible use cases.

public class ProductSerializer
{
  public void SerializeToSQLServer { }
  public void DeserializeFromSQLServer { }
  public void SerializeToSybase { }
  public void DeserializeFromSybase { }
  public void SerializeToFile { }
  public void DeserializeFromFile { }
}

Instantly, you will agree this is not a good practice. One class does everything. It is the prime vice in OOP.

As a second step, let’s divide this monolithic class into a couple of small classes that do the only one task.

public class ProductSQLSerializer
{
  public void Serialize() { }
  public void Deserialize() { }
}
public class ProductSybaseSerializer
{
  public void Serialize() { }
  public void Deserialize() { }
}
public class ProductFileSerializer
{
  public void Serialize() { }
  public void Deserialize() { }
}

 

2. Programming Against Interface

It is a common sense to professional developer to use a common “Interface” rather than accessing concrete classes directly. By creating and accessing concrete objects directly, you are creating tightly coupled code, which is the another prime vice in OOP.

Choosing between “abstract classes” and “interfaces” is up to the business models. In our example, SQL and Sybase can be abstracted as a common base “DB” but “File” stands in its own. Therefore “interface” model will be more appropriate.

interface IProductSerializable
{
  void Serialize();
  void Deserialize();
}
public abstract class ProductDBSerializer : IProductSerializable
{
  public abstract void Serialize();
  public abstract void Deserialize();
}
public class ProductSQLSerializer : ProductDBSerializer
{
  public override void Serialize() { }
  public override void Deserialize() { }
}
public class ProductSybaseSerializer : ProductDBSerializer
{
  public override void Serialize() { }
  public override void Deserialize() { }
}
public class ProductFileSerializer : IProductSerializable
{
  public void Serialize() { }
  public void Deserialize() { }
}

Now it’s much better. Let’s create an invoker code.

IProductSerializable serializer = new ProductSQLSerializer();
serializer.Serialize();

Well Done! But can you see the problem here?

 

3. Dependency Injection

What is the problem of the last code snippet? You want to create a loose coupled code, right? Whenever you need to create a “IProductSerializable” object, you need to refer to one of the concrete classes, which means you are still depending on the concrete class.

Let’s see why this is a problem. It is true that you need to create a concrete object in one point. Our goal is to centralize this task only in one place and nowhere else.

Suppose the model is used in a couple of Controller classes such as  “ProductController”, “OrderController”, “StockController”… Is it a good idea to let all controllers refer to all concrete classes? Absolutely not. So what can you do?

Now the “Dependency Injection” pattern shines.

  • Define a property variable of the type of an interface
  • Provide a Constructor with a parmater (Constructor Injection)
  • or Use the Setter (Property Injection)
IProductSerializable Serializer { get; set; }
public ProductController(IProductSerializable s)
{
  Serializer = s;
}

Now controller classes only knows about the interface. The name DI comes from this. Dependencies are not created inside the class and rather injected into it.

 

4. DI and Testing

The greatest benefit of DI is that it makes unit tests much easier. In our example, to test the code, you need to connect to DB or create a file, which developers usually do not like. Now dependencies are not tightly linked to controller classes. What you need to do is to create a mock object and inject it to a controller class.

Cool, isn’t it?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s