Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I know how to use dependency injection but I recognize no practical advantage for it

It is about this (Inject the dependency)

private readonly ICustomerService _customerService;
public Billing(ICustomerService customerService)
{
   _customerService = customerService;
}

versus this (Create the dependency)

private readonly ICustomerService _customerService;
public Billing()
{
   _customerService = new CustomerService();
}

The latter sample so they say is bad because... it violates DI...of course nothing is injected... but what if DI would not exist, what is so bad that the CustomerService is created manually from the Billing class? I see no practical advantage concerning exchangeability of the Service interface.

I ask for a practical example with source code may it be a unit test or showing a practical solution why it is so much more loose coupling.

Anyone keen enough to show his DI muscles and why it has a practical right to exist and be applied?

UPDATE

So people have not to read all up I will write here my short experience:

DI as a pattern has a practical usage. To follow DI by not injecting all services manually (a poor mans DI tool so they say...) use a DI framework like LightCore/Unity but be sure you use the right tool for the appropriate job. This is what I did not;-) Developing a mvvm/wpf application I have other requirements the LightCore/Unity tool could not support they even were a barrier. My solutions was to use MEFEDMVVM with which I am happy. Now my services are automatically injected at runtime not at startup time.:-)

like image 310
msfanboy Avatar asked Sep 08 '11 19:09

msfanboy


3 Answers

Understanding the how and understanding the why are very different things..

One of the biggest benefits of DI is for unit testing. In your second example it's impossible to unit test Billing without also testing CustomerService (and also testing any further dependencies in the chain). In that case you're not unit testing, you're integration testing! If you want a good rationale for using DI, you need not look any further than a rationale for unit testing..

like image 55
MattDavey Avatar answered Sep 29 '22 01:09

MattDavey


Imagine that CustomerService connects to your CRM system and your database. It creates a whole bunch of network connections to retrieve data about the customer and maybe reads additional things from the database to augment that before returning the data to the Billing class to use in its calculation.

Now you want to unit test Billing to make sure the calculations it's making are correct (you don't want to send out wrong bills right?)

How will you unit test Billing if its constructor is tied to a class that requires connections to a real CRM system and database? Wouldn't it be better to inject that dependency as an interface, easily allowing you to provide a mock version for your tests?

That is why DI is useful.

like image 23
Paolo Avatar answered Sep 29 '22 01:09

Paolo


DI Comes in useful, when you want to pass different implementations of the Interface to your class, for example: Unit Testing.

Say your Billing constructor is an MVC controller's constructor, and your CustomerService took some form of IDataContext as a parameter.

Global.asax

// Does the binding
ICustomerService binds to CustomerService
IDataContext binds to EntityFrameworkContext

CustomerService

private IDataContext _datacontext;   
public CustomerService(IDataContext dataContext)   
{   
   _dataContext = dataContext;  
}

public AddCustomer(Customer entity)   
{   
  this._dataContext.Customers.Add(entity);
  this._dataContext.SaveChanges;   
}   

MVC Controller

private ICustomerService _customerService;
public Billing(ICustomerService customerService)
{
   _customerService = customerService;
}

public ActionResult NewCustomer()
{
  Customer customer = new Customer(){ Name = "test" };
  this._customerService.AddCustomer(customer);

  return View();
}

Say you wanted to unit test your Services, or Controllers. You would pass in the CustomerServices, but you would pass in a fake implementation of the EntityFrameWorkContext. So a FakeDbContext, that implements IDataContext, is passed to customer services.

The FakeDbContext may just store the entities in Lists or a more elaborate storage mechanism, the point being, you can inject different implementations of dependencies, which allows you to alter the behaviour of one component without having to modify your code elsewhere.

like image 37
Zack Avatar answered Sep 29 '22 01:09

Zack