Das Open-Closed Principle

Definition

Das Open-Closed Principle (Offen-Geschlossen-Prinzip, OCP) ist eines der SOLID-Prinzipien. Es wurde 1988 von Bertrand Meyer beschrieben und es lautet:

„Software Entities (Classes, Modules, Functions, etc.) should be open for extension, but closed for modification.“
„Software Entitäten (Klassen, Module, Funktionen, usw.) sollten offen für Erweiterungen sein, aber geschlossen für Modifikationen.“

Ein intelligenter Entwurf einer Anwendung sollte stets die häufigen Änderungen während der Entwicklung und der Wartungsphase berücksichtigen. Fügt man einer Anwendung neue Funktionalität hinzu, sind Änderungen am Code unumgänglich. Diese Änderungen im existierenden Code sollten jedoch auf das Minimum reduziert werden. Bedenkt man, dass der Code bereits getestet wurde, können Änderungen im geschriebenen Code unerwünschte Nebenwirkungen haben oder zu unbeabsichtigten Fehler führen.

Das Offen-Geschlossen-Prinzip sagt aus, man sollte Module so entwerfen, dass sich diese niemals ändern. Wenn sich die Anforderungen ändern, sollte man das Verhalten durch das hinzufügen neuen Codes erweitern, statt den existierenden Code zu ändern, der bereits funktioniert. Der existierenden Code sollte soweit wie möglich unverändert bleiben.

Beschreibung

Module die mit dem Offen-Geschlossen-Prinzip übereinstimmen, weisen zwei Eigenschaften auf:

  1. Sie sind „Offen für Erweiterungen“.
    Das Bedeutet, dass das Verhalten der Module erweitert werden kann. Dadurch können sich die Module entsprechend den neuen Anforderungen der Anwendung in einer neuen oder anderen Weise verhalten oder neuen Bedürfnissen der Anwendung begegnen.
  2. Sie sind „Geschlossen für Modifikationen“.
    Der Quellcode eines solchen Moduls ist geschützt. Niemand darf Änderungen an dem Quellcode vornehmen.

Der Schlüssel dazu ist die Abstraktion. Die Abstraktionsebene besteht aus abstrakten Klassen, die konkreten Verhaltensweisen werden in den abgeleiteten Klassen implementiert. Für ein Modul ist es somit möglich die Abstraktion zu beeinflussen. Ein solches Modul ist für Modifikationen geschlossen, da es an eine Abstraktion gekoppelt ist. Dennoch kann das Verhalten des Moduls durch die Schaffung neuer Ableitungen erweitert werden.

Beispiel

Das untere Beispiel verletzt das Offen-Geschlossen-Prinzip. Es implementiert eine Funktion die verschiedene Formen zeichnet. Es ist offensichtlich, dass sie dem Prinzip nicht folgt, da sie jedes mal modifiziert werden muss, wenn eine neue Form hinzu kommt. Zudem kann das Hinzufügen einer neuen Form die bestehende Funktionalität in unerwünschter Weise beeinflussen, auch wenn die neue Form perfekt funktioniert. In diesem Fall wäre es eine grosse Verbesserung, wenn man eine neue Form hinzufügen könnte, ohne die Funktion ändern zu müssen.

enum ShapeType { Circle, Square };

public abstract class Shape
{
     public ShapeType Type;
}

public class Circle : Shape
{
     public double Radius;
     public Point itsCenter;
}

public class Square : Shape
{
     public double Side;
     public Point TopLeft;
}

public void DrawCircle(Circle circle) { ... }
public void DrawSquare(Square square) { ... }

public void DrawShapes(Shape[] shapes)
{
     foreach (Shape shape in shapes)
     {
          switch (shape.Type)
          {
               case ShapeType.Circle:
                    DrawCircle(shape);
                    break;

               case ShapeType.Square:
                    DrawSquare(shape);
                    break;

          }
     }
}

Das folgende Beispiel folgt dem Offen-Geschlossen-Prinzip. Im neuen Entwurf verwenden wir die abstrakte Funktion Draw() zum Zeichnen der Formen. Durch das Verschieben des Zeichnen-Codes in die konkreten Form Klassen, wird auch das Risiko reduziert, dass bestehende Funktionalität durch neue beeinflusst wird.

public abstract class Shape
{
     public abstract void Draw();
}

public class Circle : Shape
{
     public override void Draw() { ... }
}

public class Square : Shape
{
     public override void Draw() { ... }
}

public void DrawShapes(Shape[] shapes)
{
     foreach (Shape shape in shapes)
     {
          shape.Draw();
     }
}

Fazit

In vielerlei Hinsicht ist das Offen-Geschlossen-Prinzip das Herzstück eines objektorientierten Entwurfs. Die Einhaltung dieses Prinzips bringt den größten Vorteil in der objektorientierten Entwicklung: Wiederverwendbarkeit und Wartbarkeit. Die Konformität mit diesem Prinzip wird aber nicht automatisch durch das Verwenden einer objektorientierten Programmiersprache erreicht. Vielmehr bedarf es einer gewissen Hingabe des Entwicklers, die Abstraktionsebene auf die Teile des Entwurfs anzuwenden, die sich am wahrscheinlichsten ändern werden.

Quellen

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.