Dependency inversion principle

from Wikipedia, the free encyclopedia
Structuring of modules according to DIP

The Dependency Inversion Principle ( DIP , English for dependency inversion principle ) is a principle in object-oriented design of software . It deals with the dependency of modules .

In general, the DIP is described by:

Higher level modules should not depend on lower level modules.
Both should depend on abstractions.
Abstractions shouldn't depend on details.
Details should depend on abstractions.

Problem and solution

Object-oriented designs are structured in modules that implement different responsibilities. A common practice is to arrange the modules in levels. The lower the level of a module, the more specific the operations it defines. In modules of lower levels, processes are defined which are used by more general processes in higher levels.

If this arrangement is implemented incorrectly, i.e. modules of higher levels depend on modules of lower levels, a problem arises. Changes in modules at lower levels inevitably lead to changes in modules at higher levels. On the one hand, this contradicts the actual approach of the hierarchy; on the other hand, it leads to cyclical dependencies. This leads to an increased coupling of the modules, which unnecessarily complicates changes in architecture and design.

The solution is to invert the dependency. The higher level module defines the interface with which it operates. Lower level modules implement the interface.

example

We consider a simple switch-lamp model. Pressing the switch is intended to turn the lamp on or off.

A simple implementation in Java :

public class Lampe {
   private boolean leuchtet;

   public void anschalten() {
      leuchtet = true;
   }

   public void ausschalten() {
      leuchtet = false;
   }
}

public class Schalter {
   private Lampe lampe;
   private boolean gedrueckt;

   public Schalter(Lampe lampe) {
      this.lampe = lampe;
   }

   public void drueckeSchalter() {
      gedrueckt = !gedrueckt;
      if(gedrueckt) {
         lampe.anschalten();
      } else {
         lampe.ausschalten();
      }
   }
}

Switch controls the behavior and uses a lamp. It should therefore belong to a higher-level module. However, the model described violates the DIP, since the switch is dependent on the lamp. If it is decided that the lamp methods are to be renamed, switches must also be changed.

The basic problem is that the switch works directly with the lamp, which belongs to a lower module. Switch itself should define what the object it is working with should look like.

The solution in Java:

public interface SchalterClient {
   public void anschalten();
   public void ausschalten();
}

public class Lampe implements SchalterClient {
   private boolean leuchtet;

   public void anschalten() {
      leuchtet = true;
   }

   public void ausschalten() {
      leuchtet = false;
   }
}

public class Schalter {
   private SchalterClient client;
   private boolean gedrueckt;

   public Schalter(SchalterClient client) {
      this.client = client;
   }

   public void drueckeSchalter() {
      gedrueckt = !gedrueckt;
      if(gedrueckt) {
         client.anschalten();
      } else {
         client.ausschalten();
      }
   }
}

The interface switch client belongs to the same module such as switches. More specific modules must implement this interface so that Switch can work with them. Thus the dependency was inverted.

In addition to breaking the dependency, another advantage was developed: Schalt can now work with any client.

The example can be continued. The switch itself is probably used by another module that decides when the switch was pressed. Accordingly, this module should in turn define an interface that switches must implement.

literature