Techblog

Warum ich SOLID für überbewertet halte

Von Silas Graffy @SilasG auf Twitter
22. Februar 2016

Erinnert sich jemand an die Szene der Simpsons, in der sich Prof. Frink Gehör verschaffen muss, indem er die versammelte Wissenschaftsmeute mit dem Ausruf "Pi ist genau 3!" in Schreckensstarre versetzt? Falls die Überschrift auf die eine oder den anderen Software-Crafter diese Wirkung gehabt haben sollte: Sorry, das war nicht meine Absicht. Worum es mir stattdessen geht, ist darauf aufmerksam zu machen, dass ich SOLID vielleicht nicht wirklich für überbewertet, wohl aber für einen ungeeigneten Einstieg in die Welt der Prinzipien guten Softwarebaus halte. Nicht nur Juniorentwickler_innen verstoßen oft genug gegen so viel grundlegendere Programmierleitlinien, um so einen Artikel zu rechtfertigen, ja in meinen Augen nötig zu machen.

Aber fangen wir vorne an: Worum geht es bei SOLID überhaupt? SOLID steht als Akronym für die ersten fünf Prinzipien des Entwurfs von Klassen in objektorientierten Softwaresystemen, wie sie Robert C. Martin zusammengetragen hat. Diese sind (Kenner überspringen die Auflistung einfach):

  1. Single Responsibility Principle (SRP): Das SRP fordert von (in diesem Fall) einer Klasse, dass sie nur eine Aufgabe erfüllen darf. In der Regel wird das mit "nur ein Grund für Änderungen" gleichgesetzt.
  2. Open/Closed Principle (OCP): Das von Bertrand Mayer 1988 formulierte OCP besagt, dass Module von Software offen für Erweiterungen, aber geschlossen für Änderungen (ihres Verhaltens) sein sollten.
  3. Liskov Substitution Principle (LSP): Barbara Liskov forderte 1993, dass Objekte einer Basisklasse immer durch Objekte einer von dieser abgeleiteten Klasse ersetzbar sein müssen, ohne Laufzeitprobleme zu verursachen.
  4. Interface Segregation Principle (ISP): Beim ISP plädiert Robert C. Martin - vereinfacht gesagt - für mehrere kleine Interfaces anstelle eines großen Interfaces. So werden Abhängigkeiten minimiert und explizit gemacht.
  5. Dependency Inversion Principle (DIP): Das DIP wird manchmal (sträflich) vereinfacht dargestellt als "Abhängigkeiten immer von Abstraktionen, nie von Konkretem". Der zentrale Aspekt der Umkehr von Abhängigkeiten bleibt dabei jedoch auf der Strecke. Vollständig fordert Robert C. Martin im DIP daher auch zweierlei: Zum einen, dass Module höherer Ebenen, z. B. Business-Layer in einer klassischen Dreischichtenarchitektur, nicht von Modulen niedrigerer Ebenen, z. B. Persistenz-Layer, abhängen sollen, sondern beide von Abstraktionen. Zum anderen sollen Abstraktionen nicht von Details abhängig sein, sondern umgekehrt. Im genannten Beispiel bedeutet dies, sowohl Business- als auch Persistenz-Layer sollten von Repository-Interfaces abhängen, ersterer als Nutzer, letzter als Implementierer.

SOLID reicht nicht 

Was stört mich nun also an alldem? Klingt doch vernünftig, oder?

Nun, es ist vor allem der Fakt, dass für viele Software Crafter "SOLID" die allererste Antwort auf die Frage nach wichtigen Prinzipien der Softwareentwicklung ist. Für einige ist es dann aber leider auch die einzige Antwort. Woran das liegt, kann ich nicht mit Sicherheit sagen. Vielleicht am griffigen Akronym? Das geht im Übrigen nicht auf Martin, sondern auf Micheal Feathers zurück. Vielleicht daran, dass Martin die Prinzipien kategorisiert vorstellt, anstatt nach Relevanz sortiert, und mit diesen für Klassendesign in OO-Systemen beginnt? Ich weiß es nicht. Sicher bin ich mir jedoch darin, dass damit der Fokus weg von Prinzipien gelenkt wird, die ich für eine viel, viel wichtigere Basis guten Softwarebaus halte. Unsere zahlreichen Software-Architekturaudits und Sanierungsprojekte bestärken mich darin.  

Separation of Concerns: fachlichen und technischen Code sowie fachliche Belange in der Domäne trennen

Das SRP finde ich wichtig, das steht hier völlig zu recht. Und man könnte das Prinzip Separation of Concerns (SoC) ergänzen, das sich zwar mit dem SRP überschneidet, aber größeres Augenmerk auf eine Trennung unterschiedlicher Belange legt. Das kann sowohl eine Trennung von fachlichem und technischem Code sein, als auch eine saubere Trennung von unterschiedlichen fachlichen Belangen innerhalb der Domäne. Gerade diese fachliche Komponentenbildung kommt in klassischen Schichtenarchitekturen oft viel zu kurz, denn scheinbar gehört ja alles zum Belang des Business-Layers. Bounded Contexts aus dem Domain Driven Design, aber auch eine in Featureteams aufgeteilte Organisationsstruktur (Conway's Law) können hier helfen.

Composition over Inheritance: wichtiger als Aufmerksamkeit auf Vererbung  

Das LSP und – in Teilen das OCP – lenken in meinen Augen viel zu viel Aufmerksamkeit auf Vererbung. Während der Bezug beim LSP klar ist, meint Erweiterung beim OCP nicht primär die Ableitung von einer Klasse, wird aber häufig so interpretiert – das Schlüsselwort extends in Java ist sicher nicht ganz unschuldig daran. Im Allgemeinen führt die Betonung von OCP und LSP in SOLID häufig auch dazu, dass Vererbung nach wie vor häufig Anwendung findet, wenn Code wiederverwendet werden soll. Tatsächlich ist Wiederverwendung durch Vererbung eine Unsitte, die mir insbesondere im Java-Umfeld stark verbreitet zu sein scheint. Hier würde ich mir stattdessen eine weitere Verbreitung des Prinzips Composition over Inheritance wünschen: Vererbung sollte nur in Betracht gezogen werden, wenn tatsächlich eine fachliche "Ist ein(e)"-Beziehung modelliert werden soll, keinesfalls aber, wenn es "nur" um Code-Re-Use geht. Komposition erleichtert in diesem Fall die Lesbarkeit des Codes, die Nutzung von Dependency Injection, die Testbarkeit sowie die Modularisierung, Entkopplung und somit Wiederverwendung der Klassen.

DRY statt DIP: Code-Wiederverwendung viel grundlegender als Umkehr von Abhängigkeiten

Dass das ISP als Teil von SOLID eine solche Prominenz bekommt, geht für mich noch in Ordnung. Beim DIP bin ich da jedoch schon nicht mehr so sicher. Nicht, dass ich das Prinzip nicht wichtig fände, das schon. Immerhin ist es zentraler Bestandteil hexagonaler Architekturen. Allerdings ist es in meinen Augen eher schon etwas für Fortgeschrittene. Dem junioren Entwickler oder der junioren Entwicklerin, die erstmals mit Prinzipien guten Softwarebaus in Berührung kommen, lege ich da – um bei einem Prinzip mit D zu bleiben – eher Don't Repeat Yourself (DRY)nahe. Immerhin zielen grundlegende Sprachkonstrukte wie Funktionen, Prozeduren und Methoden, Softwarebibliotheken, Komponenten und Frameworks sowie Templates, Code-Generatoren und-und-und vor allem auf die Wiederverwendung statt der Wiederholung von Code ab.

KISS und YAGNI auf allen Ebenen und in allen Phasen

Für wichtiger als die meisten SOLID-Prinzipien halte ich außerdem Keep It Simple, Stupid (KISS) und You Ain't Gonna Need It (YAGNI), da diese beiden Prinzipien auf allen Ebenen des Softwarebaus zum Tragen kommen: angefangen vom Programmieren, über Software- und Systemarchitektur bis zum Abbilden fachlicher Anforderungen. Leider verstoßen auch erfahrenere Software Crafter, Software- und Enterprise-Architekt_innen sowie Anforderungsanalyst_innen regelmäßig dagegen. Zu groß scheint die Versuchung zu sein, unnötig komplizierte Strukturen zu entwerfen und zu bauen, denn "es ist doch klar, dass wir das bald brauchen". Naja. Jede Menge Zeit, Geld und Nerven kosten diese unnötigen und oft nur teilweise implementierten Features und komplizierten Strukturen von da an aber jedes Mal, wenn etwas gewartet, gefixt, weiterentwickelt, getestet, dokumentiert oder auch einfach nur verstanden werden soll. Und noch mal bei deren Rückbau – wenn er denn stattfindet.

Von Abstraktionen, Überraschungen, Farben und Pfadfindern

Auch auf der Ebene des Programmierens fallen mir mit Single Level of Abstraction (SLA) und Principle Of Least Astonishment (POLA) zwei Kandidaten ein, die von SOLID zu Unrecht in den Schatten gestellt werden. Dabei drücken sie weit über die Objektorientierung heraus wichtige, allgemeingültige Programmiergrundsätze aus.

Alles in allem scheint mir die Clean Code Developer-Initiative von Ralf Westphal und Stefan Lieser eine sinnvolle Reihenfolge vorzuschlagen: In den ersten beiden von sechs aufeinander aufbauenden Graden, rot und orange, wird hier fokussiert auf:

Die Pfadfinder-Regel ist zwar kein Prinzip im engeren Sinne, aber so wichtig, dass ich ihr Vorkommen im roten Grad hier dennoch nicht unerwähnt lassen möchte.

Natürlich kann der oder die Theoretiker_in im Elfenbeinturm nun einwenden, dass Prinzipien wie YAGNI eher der XP-Schule um Kent Beck entstammen, während SOLID orthogonal dazu eben Martins Prinzipien zum Klassenentwurf in OO-Systemen zusammenfasst. Als Praktiker glaube ich aber nicht an solche gefühlt künstlichen Abgrenzungen, sondern wünsche mir eine pragmatische Basis als solide ;-) Grundlage für den Arbeitsalltag in der Softwareentwicklung.


Siehe auch