Dependency Inversion

What is a Dependency

For the purposes of this discussion a class A has a dependency on another class B, iff you cannot compile class A without class B.

Example

class A {B b;}
class B { }

Box A with an arrow pointing to box B

We have to compile class B before (or at the same time as) class A.

Other kinds of Dependency

Anywhere the name “B” appears in class A creates a dependency. Some other examples of dependencies are:

class A extends B { }
class A implements B { }
class A { void method(B b) { } }

Transitive Dependencies

If a class A depends on another class B which itself has dependencies then the dependencies of class B are effectively dependencies of class A

Example:

class A { B b; }
class B { C c; } 
class C { }

Box A with an arrow to Box B with an Arrow to Box C, dotted arrow from Box A to Box C

We have to compile class C before (or at the same time as) class B and class A.

The Problem

When class C changes, we have to recompile and retest both class A and class B. In a large system this can take a very long time. It also means that you have to know about class C in advance; you cannot decide on class C after deciding on class A.

If class C is a more concrete class then it might change more frequently than class A. This will cause class A to be recompiled/tested much more frequently than it otherwise would need to be.

The Solution

Inverting Dependencies

Have class A and class B both depend on an abstraction I. This inverts the direction of the dependency arrow on class B.

interface I { }
class A { I i; }
class B implements I { }

Box A with arrow to Box I, Box B with arrow to Box I

Breaks Transitive Dependency

The really helpful effect of this inversion is that it also breaks the transitive dependency from class A onto class B

interface I{ }
class A { I i; }
class B implements I{ C c; }
class C { }

Box A arrow to Box I, Box B arrow to Box I, Box B arrow to box C. Box A dotted arrow to Box C deleted

Dependency Inversion Principle

This is an application of the Dependency Inversion Principle:

  • High level modules should not depend on low level modules. Both should depend on abstractions.
  • Abstractions should not depend upon details. Details should depend upon abstractions.

One thought on “Dependency Inversion

  1. Pingback: » Compilation Time and Layering Lexical Scope

Leave a Reply