Inversion of Control (IoC) is often achieved by Dependency Injection and programming to interfaces and can be facilitated using IoC containers such as
Castle Windsor or
Spring.
Pro
- Improves modularity and extensibility through interface based programming - it's easier to add/swap out implementations in the future and mock frameworks are well suited to mocking interfaces
- Reduces coupling and dependency through isolation and decoupling into layers - layers can be replaced in the future or if that is not needed, they still gain the benefit of individual development and testing brought about by the reduction in dependencies
- Promotes Single Responsibility Principle - easier to prevent unexpected breakage from unrelated functionality in the same class
- All of the above facilitate creating fine grained unit tests that test only one thing and run quickly, especially using Mocks.
- Explictly defining your external dependencies in constructors makes them clear to users of the class serving to improve implicit documentation
Note: #1-#3 above result from a solid implementation of IoC principles. Nevertheless, aside from the facets of isolation that result strictly from dependency injection, the rest of the principles mentioned in #1 - #3 above are not specific to inversion of control. This is an important distinction as often arguments FOR IoC are just arguments for some of those good, base programming principles and IoC is not required for their implementation
Con
- Leads to a lot of classes generated for interfaces and factories on objects that are not required for production code and many objects are perhaps known to be simple and very unlikely to change. Violates YAGNI.
- Tends to deviate from some facets of encapsulation given that dependencies which can arguably be considered to be implementation details are made external and must be known to be passed in/set.
- Testability via IoC doesn't deal well with static methods or singletons. While there may be certain good reasons for avoiding these at times, at others they are useful and do serve a purpose, but you have no choice
- Similarly, while programming to interfaces is often useful and recommended, there are times when inheritance lends itself more easily to the design and IoC becomes kludgy to implement when dealing with a dependency that can consist of any of a inheritance chain of classes. [Need example for this - not as clear in my mind as when I had thought of this a while back]
- Difficult to retrofit legacy code to use IoC
---
Resources
More Debate: http://kohari.org/2007/08/15/defending-dependency-injection/
Pro