Friday, May 20, 2011

Dependency Inversion Principle ( DIP )

The dependency inversion principle OR DIP states 
  • High level modules should not depend upon low level modules. Both should depend upon abstractions  
  • Abstractions should not depend upon details. Details should depend upon abstractions
This principle seeks to "invert" the conventional notion that high level modules in software should depend upon the lower level modules. The principle states that high level or low level modules should not depend upon each other, instead they should depend upon abstractions. This is best illustrated by an example.

DIP is "D" of SOLID in design principles.

Example of this can be seen here.

Dependency inversion and dependency injection
Another practice often associated with the Dependency Inversion Principle is Dependency Injection. Dependency Injection encompasses a set of techniques for assigning the responsibility of provisioning dependencies for a component to an external source. The goal of Dependency Injection is to separate the concerns of how a dependency is obtained from the core concerns of a component.

The practice of dependency injection is often discussed alongside the Dependency Inversion Principle as a facilitating pattern for supplying implementations of the client interface to the client component at run time. While other patterns such as Service Locator and Plug-in can be used to facilitate the Dependency Inversion Principle, Inversion of Control in the more common solution due to its ability to decouple components from how their dependencies are obtained.

One potential stumbling block newcomers to these design approaches face is in the similarity of terms used in describing these approaches. For instance, taken at face value, the phrase “Dependency Inversion” might conjure up the idea that dependency requirements are being inverted (as in turned inside out) rather than the inversion of dependency (as in reversal) between higher-level components and lower-level components. While the former is an adequate understanding of what dependency injection is, it doesn’t describe the goal of the Dependency Inversion Principle. While certainly complimentary, how dependency implementations are obtained is orthogonal to the module dependency concerns set forth by the Dependency Inversion Principle.

Benefits and Consequences
The approach advocated by the Dependency Inversion Principle provides a useful option for decoupling components from their external dependencies. By following the guideline that higher-level components shouldn’t depend upon lower-level components, core functionality within an application can be more easily used in different contexts.
While applying the Dependency Inversion Principle enables higher-level components to be used in a different context, it unfortunately negatively impacts the ability to reuse lower-level components. While this may at times be an optimal compromise, it is not always the case that higher-level components possess the greatest need for decoupling.
The core business components within an application often encapsulate a rich set of behavior tailored to a specific context. While such components may be of tremendous benefit to applications requiring the same behavior, it is their specificity that tends to limit the context where reuse is possible. In contrast, lower-level components often encapsulate more generic functionality which is applicable across a wider range of contexts.
Consider for example the development of a custom logging component. Logging is generally a concern shared by many components across all applications within an enterprise. In following the Dependency Inversion Principle, the logging component would be developed to depend upon a client-owned interface package to allow higher-level components to remain decoupled from the specific logging implementation. While this enables a higher-level component to be reused without requiring the specific logging implementation, it doesn’t allow the logging component to be easily used by other applications.
While the Dependency Inversion Principle does account for the reuse of lower-level components by maintaining the client interface in a separate package, assigning ownership of this package to one or more consumers of a lower-level component can itself be problematic. In doing so, this creates a form of associative coupling between clients which may have diverging interests that affect the agreement upon, or stability of the interface contract. Additionally, the resulting contract, naming conventions, and deployment strategy may lack the objectively and elegance that might follow more naturally from assigning the ownership of the interface package to the lower-level component.

No comments:

Post a Comment