Single-Responsibility-Prinzip
# Single-Responsibility-Prinzip

Das Single-Responsibility-Prinzip (SRP, deutsch Prinzip der eindeutigen Verantwortlichkeit) ist eine Entwurfsrichtlinie in der Softwarearchitektur.

## Definition

Eine weit verbreitete, aber fehlerhafte Annahme ist, dass SRP aussagt, dass jede Klasse nur eine fest definierte Aufgabe zu erfüllen habe.

Der Ausdruck wurde von Robert C. Martin in einem Teilartikel gleichen Namens in seiner Publikation Principles of Object Oriented Design eingeführt:

   “There should never be more than one reason for a class to change.”
   „Es sollte nie mehr als einen Grund geben, eine Klasse zu ändern.“

Bekannt wurde der Ausdruck durch sein Buch Agile Software Development: Principles, Patterns, and Practices.

In seinem Buch Clean Architecture: A Craftsman’s Guide to Software Structure and Design geht Robert C. Martin auf die Fehlinterpretation des SRP ein und schlägt die „finale Version“ der Definition vor.

   “A module should be responsible to one, and only one, actor.”
   „Ein Modul sollte einem, und nur einem, Akteur gegenüber verantwortlich sein.“

Somit geht es beim SRP nicht nur um die einzelnen Klassen oder Funktionen. Vielmehr geht es um durch die Anforderungen eines Akteurs definierten Sammlungen an Funktionalitäten und Datenstrukturen.

## Verallgemeinerung des Single-Responsibility-Prinzips

### Funktionen und Variablen

Eine Verallgemeinerung des SRP stellt Curly’s Law dar, welches SRP, methods should do one thing, once and only once (OAOO), don’t repeat yourself (DRY) und single source of truth (SSOT) zusammenfasst. Das SRP kann und soll demnach für alle Aspekte eines Softwareentwurfs angewendet werden. Dazu gehören nicht nur Klassen, sondern unter anderem auch Funktionen und Variablen. Es ist daher auch bei der Verwendung von nicht-objektorientierten Programmiersprachen und dem Entwurf von Serviceschnittstellen gültig.

   “A functional unit on a given level of abstraction should only be responsible for a single aspect of a system’s requirements. An aspect of requirements is a trait or property of requirements, which can change independently of other aspects.”
   “A variable should mean one thing, and one thing only. It should not mean one thing in one circumstance, and carry a different value from a different domain some other time. It should not mean two things at once. It must not be both a floor polish and a dessert topping. It should mean One Thing, and should mean it all of the time.”

Beispiel In dem folgenden Beispiel wird eine Reihe von Zahlen sortiert:

Da die Variable numbers zuerst die unsortierten Zahlen repräsentiert und nachher die sortierten Zahlen, wird Curly’s Law verletzt. Dies lässt sich auflösen, indem eine zusätzliche Variable eingeführt wird:

### Anwendungen

Auch in der Unix-Philosophie kommt ein ähnliches Prinzip vor, denn hier sollen Anwendungen einen einzelnen Zweck erfüllen.

   Make each program do one thing well. By focusing on a single task, a program can eliminate much extraneous code that often results in excess overhead, unnecessary complexity, and a lack of flexibility.
   „Gestalte jedes Programm so, dass es eine Aufgabe gut erledigt. Durch die Fokussierung auf eine einzelne Aufgabe, kann ein Programm viel unnötigen Code eliminieren, welcher oft zu übertriebenem Overhead, unnötiger Komplexität und mangelnder Flexibilität führt.“

Anwendungen und Benutzerschnittstellen nach einem einzelnen Zweck aufzuteilen, besitzt nicht nur in der Entwicklung Vorteile. Auch für Benutzer sind Programme und Benutzerschnittstellen mit einem klar bestimmten Aufgabenzweck besser verständlich und schneller erlernbar. Nicht zuletzt ergeben sich Vorteile bei beschränkten Bildschirmgrößen, wie dies z. B. bei Smartphones der Fall ist.

## Verwandte Muster

Das Interface-Segregation-Prinzip kann als ein Spezialfall des SRP gesehen werden. Es entsteht durch die Anwendung des SRP auf Interfaces.

Command-Query-Separation dient dazu, Funktionen und Entitäten nach ihrer Aufgabe zu trennen, indem zwischen Kommandos (Commands) und Abfragen (Queries) unterschieden wird. Ähnliches gilt für CQRS, welches unterschiedliche Codepfade für Datenbankzugriffe definiert, welche unabhängig voneinander optimiert werden können.

## Querschnittsaspekte

Querschnittsaspekte, welche die gesamte Anwendung betreffen, stellen bezüglich des SRP eine besondere Herausforderung dar. Hierzu zählt insbesondere das Logging.

### Bewusster Verstoß gegen das SRP

Viele Entwickler vertreten die Ansicht, dass bei Querschnittsaspekten gegen das SRP verstoßen werden sollte, da Querschnittsaspekte, wie das Logging, so nah wie möglich an der zuständigen Geschäftslogik sein sollten.

Das Logging direkt in der Methode führt allerdings dazu, dass das SRP nicht eingehalten und die Methode spaghettifiziert wird. Das Lesen und Testen der Geschäftslogik wird durch den Code des Aspekts erschwert.

### Decorator-Methode

Eine Decorator-Methode ist eine einfache Möglichkeit, den Aspekt und die Geschäftslogik in getrennte Methoden auszulagern.

Nachteilig ist, dass der Aspekt zwar auf Methodenebene ausgelagert wurde, allerdings weiterhin in der Klasse vorhanden ist. Dies stellt daher eine Verletzung des SRP auf Klassenebene dar. Zwar wird die Lesbarkeit verbessert, jedoch stellt sich beim Testen weiterhin die Herausforderung, dass der Aspekt mitgetestet werden muss.

### Aspektorientierte Programmierung

Die Aspektorientierte Programmierung (AOP) stellt einen alternativen Ansatz dar, um den Aspekt auszulagern. Hierbei wird die Logik lediglich über eine Auszeichnung definiert und von einem Aspekt-Weaver implementiert.

Nachteilig ist hierbei, dass das SRP nicht eingehalten wird, da der Aspekt weiterhin in der Klasse verbleibt. Zudem können eventuell nicht alle Aspekte ausgegliedert werden. Beispielsweise kann im obigen Beispiel mit einem Attribut keine parametrisierte Fehlermeldung angegeben werden. Dies führt dazu, dass die Lösung an vielen Stellen annähernd dieselbe Komplexität aufweist wie die ursprüngliche Lösung:

Zudem befindet sich die Logik des Aspekt nach dem Kompiliervorgang weiterhin in der Klasse und erschwert daher weiterhin die Testbarkeit.

### Unterklasse

Eine weitere Möglichkeit den Aspekt von der Geschäftslogik zu trennen besteht darin, abgeleitete Klassen einzuführen.

Diese Lösung verstößt allerdings gegen das Prinzip Komposition an Stelle von Vererbung einzusetzen. Ein weiterer Nachteil ist, dass sämtliche Klassen und Methoden für Vererbung geöffnet werden müssen, wodurch zudem gegen das Open-Closed-Prinzip verstoßen wird.

Unterklassen zur Auslagerung von Aspekten stellen daher ein Antipattern dar.

### Decorator

Aspekte lassen sich mittels eines Decorators realisieren und somit von der Geschäftslogik trennen.

Der Vorteil hierbei ist, dass das Prinzip der Komposition an Stelle von Vererbung eingehalten wird. Die Klasse PersonRepository kann in Folge gegenüber Vererbung geschlossen werden, da eine Erweiterung durch Komposition jederzeit möglich ist. Ein weiterer Vorteil ist, dass der Aspekt durch eine Konfiguration der Dependency Injection ausgetauscht werden kann. Zudem kann die Logging-Logik unabhängig von der Business-Logik getestet werden.

Nachteilig ist allerdings ein höherer Wartungsaufwand, da in der Dependency Injection sowohl die Klasse mit der Geschäftslogik, als auch die Klasse mit dem Aspekt verwaltet werden muss. Durch die Trennung wird zudem die Nachvollziehbarkeit (z. B. in welcher Klasse ein Fehler aufgetreten ist) erschwert.

## Raviolicode

Die konsequente Anwendung des Single-Responsibility-Prinzips führt dazu, dass anstatt des Spaghetticodes ein sogenannter Raviolicode entsteht. Dabei handelt es sich um Code mit sehr vielen kleinen Klassen und kleinen Methoden.

Raviolicode besitzt den Nachteil, dass die Menge an Klassen in großen Projekten dazu führt, dass eine geringere Übersichtlichkeit gegeben ist. Dies betrifft insbesondere die in objektorientierten Programmiersprachen auftretenden Functor-Klassen, also Klassen mit nur einer einzigen Methode.

Das SRP macht somit eine saubere Strukturierung mittels Modulen, Namespaces und Fassaden zwingend notwendig, damit die Übersichtlichkeit nicht verloren geht.

