When designing an application there are sets of tasks which relate to each other and there are sets of tasks which are independent of each other. Tasks that relate to each other will be organized in one system. Tasks that are independent of each other will be organized in different systems preferrably. At several points in the application independent tasks will have to make use of one another. But because they are independent of each other, they can not make valid assumptions about behavior nor do they know which implementation to use. The calling task does not have more information then the need to make the call. The callee knows best what has to be done and how it should be done. It is at that time that Inversion of Control is best used as a design principle, because implementing this call with Inversion of Control will make it possible to decide at run time which implementation should do the job.
This might sound abstract, but in the example talking about the wave of the server facade was this principle already demonstrated. When the server facade was calling the business interface and letting the business interface do the rest, the server facade was handing over the control. It is the business facade who knows best what has to be done.
Another example was presented while talking about the double loose coupling, when it was shown that a call to another system should only be made, when according to the caller the call is valid. That had the effect that the callee could judge the call at its own merits and is relieved from making assumptions about the internal processing of the caller, and therefore return the call based on its own processing solely. In both examples Inversion of Control is applied.
Inversion of Control (=IoC) is the design principle to hand over the control how to perform the call from the caller to the callee. The reason why is shown above in the two examples, namely to maximize the independence of any system and minimize the number of assumptions necessary for communication between systems. When the callee is capable of reacting to any call without assistance of the caller, then is IoC applied successfully. As a result is it neccessary to be able to postpone the choice of implementation to run time, because that is the first moment the callee will know that there is a call on which it has to respond. Often IoC is restricted to this moment of the call, but its power goes beyond that moment in time. Let's take a look at the constraints applying to the communication between respectively independent systems or a set of dependent subsystems within a system.
Table 1: Comparison of communication constraints for systems
|Between systems||Within a system|
|The existence of the other system is not known or need not to be known at design time.||All elements are designed in relation to one another.|
|Systems can only focus on what they do themselves.||Focus on cooperation with other elements, together the overall job is performed.|
|Replacing implementations of systems has no side effect on the other system.||Replacing whatever has likely effect on other elements of the system.|
|Construction of the callee will be done at run time.||Construction of cooperating elements is known at compile time.|
|Implementation is hidden by definition as the callee is not known before run time.||It is best practice to hide the implementation. More for testing and replacement in the future.|
|Data exchange is restricted to personal yes, private no.||All talk and therefore all data is by definition private.|
The first five constraints for the situation 'between systems' are automatically applied when using IoC. Usage of IoC and this type of communication fits very well. The first five constraints for communication within any system on the other hand are not points of focus when applying IoC and sometimes even in contradiction with handing over control from the caller to the callee. When the caller and the callee are designed in relation to one another, then is it not very beneficial to hand over the control from the caller to the callee as they are both designed to work together. The usage of constructing objects using Dependency Injection or any other technique favoring IoC is not very usefull within systems. It has far more added value to restrict the usage of IoC to those situations in which communication between independent systems has to take place.