Basic theory question alert!
Its about IoC.
I was reading about IoC, and realized how i am not fully comfortable about the exact meaning of the term.
Then, I came across a specific Answer about IoC, which made me realize, that IoC is not just about control/dependency between classes, it is a much more general term: https://stackoverflow.com/a/3108/976537
"instead of the computer accepting user input in a fixed order, the user controls the order in which the data is entered"
Interesting. Now i am a lot more comfortable with the term.
Then i was reading this article about IoC and achieving it via basic DI, which i am very comfortable with, implement all the time, know the benefits of etc.
But, in the scenario below, going from figure 1 to figure 2, we take control away from OrderService. OrderServices only knows about an abstraction now, great. Plenty benefits.
EDIT: The code (from the article) in Figure 1, above, is:
public class OrderService
{
public void AcceptOrder(Order order)
{
new OrderDatabase().SaveOrder(order);
}
}
Then, after IoC & DI is implemented in Figure 2 above, the code is:
public class OrderService
{
private IOrderSaver orderSaver;
public OrderService(IOrderSaver orderSaver)
{
this.orderSaver = orderSaver;
}
public void AcceptOrder(Order order)
{
orderSaver.SaveOrder(order);
}
}
My question is, where is control considered to have gone?
Has control considered to be been shifted to:
1 - The interface? (my feeling is that this is unlikely)
2 - The IOC container used to wire up for DI at runtime? (my feeling is this one is a maybe)
3 - Or OrderDatabase (i feel this is the most likely answer)
SO - where has control been inverted to?
Referring to the following code
public class OrderService {
public void AcceptOrder(Order order) {
//...Domain logic such as validation
//then save order
new OrderDatabase().SaveOrder(order);
}
}
OrderService
should not be responsible for creating OrderDatabase
, which violates Single Responsibility Principle (SRP). It is tightly coupling itself to implementation concerns which violates Separation of Concerns (SoC).
By inverting the control that OrderService
has in creating the dependency,
it explicitly depends on an abstraction of the desired functionality in the refactored version
public class OrderService {
private readonly IOrderSaver orderSaver;
public OrderService(IOrderSaver orderSaver) {
this.orderSaver = orderSaver;
}
public void AcceptOrder(Order order) {
//...Domain logic such as validation
//then save order
orderSaver.SaveOrder(order);
}
}
delegating/inverting that control of creating the dependency to the consumer of the OrderService
(what ever is responsible for creating and using the OrderService
)
which could be a DI/IoC container or via pure DI (Dependency Injection without a DI Container)
Whether DI via container or pure DI does not matter as they will be considered implementation details which is of no concern to the target class, in this case OrderService
.