Objektorientierung ist oft eine überraschend komplexe Sache. Damit man sich nicht in dem Knäuel aus Design Patterns, Best Practices und Vererbung verheddert, sollte man sich am besten an ein paar elementare Regeln halten, die man vor allem Anderen einhält. In diesem Blogpost will ich mit euch drei Regeln teilen, die für mich bisher immer gut funktioniert haben.

Wollknäuel

1. Erfüllt jede Klasse genau eine Aufgabe?

Wenn eine Aufgabe über mehrere Klassen aufgeteilt wird, erkennt man das häufig daran dass Klassen häufig an die Daten anderer Klassen heran wollen. Da das bei privaten Membern natürlich nicht funktioniert, tendiert man dann dazu, diese Klasse weiter zu öffnen als eigentlich gut wäre, oder die man fängt an die ganze Architektur der Klasse anzupassen. Wenn hingegen mehrere Aufgaben in eine einzelne Klasse geschrieben werden, tendiert man dazu den Code in dieser in mehrere Kategorien zu gruppieren. Hier sollte man dann mehrere Unterklassen erstellen die die einzelnen Teilaufgaben des Problems erledigen.

2. Sind die Aufgaben Teil des Problems?

Diese Regel lässt sich am besten Anhand eines Beispiels erklären.

Nehmen wir an, wir haben in einer Anwendung Personen die verschiedene Rollen wie Mitarbeiter, Kunde, Administrator oder Freelancer einnehmen können. Man erstellt jetzt die Klassen Mitarbeiter und Kunde, die von Person erben. Administrator kann dann noch von Mitarbeiter erben und die Architektur ist fertig, richtig? In der Praxis erzeugt so eine Architektur leider sehr viele Probleme. Es ist nicht möglich neue Rollen anzulegen ohne den eigentlichen Code zu verändern, einer Person kann nur eine einzige Rolle zugewiesen werden und Rollen können sich nicht verändern, unser Klassenmodell wird uns im Weg stehen. OOP verleitet einen häufig dazu aus jedem “Ding” das existiert eine Klasse zu machen, jede Klasse sollte aber eigentlich ein Teilproblem aus der Lösung abbilden. Für unser Problem “Personen Rollen zuweisen”, wäre zum Beispiel folgende Struktur besser geeignet:

class Person {
   Role[] role;
   // ...
}
class Role {
   String name;
   // ...
}

Rollen können von Role erben und so eigene Methoden implementieren.

3. Niemals Übertreiben

Benutzer objektorientierter Programmiersprachen machen sich häufig dem Over-Engineering schuldig. Wenn man eine Funktionalität oder Eigenschaft nicht sofort braucht, sollte man sie am besten ganz weg lassen. Auch wenn es trivial klingt, aber gar keine Objektorientierung besser ist als schlechte Objektorientierung. Wenn sich ein Problem nur sehr umständlich in ein Objektorientiertes Schema pressen lässt, dann sollte man es einfach Prozedural lösen.