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.:-)
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..
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With