SRP (Single Responsibility Principle) — das erste Prinzip von SOLID, das besagt: Jede Klasse oder jedes Modul sollte genau einen Grund zur Änderung haben. Dieses Prinzip wurde von Robert Martin im Buch Clean Architecture (2017) formuliert und wurde zur Grundlage des modularen Designs. Laut diesem Buch reduziert die Anwendung von SRP direkt die Kopplung von Komponenten und eliminiert kaskadierende Änderungen bei der Funktionsänderung.
Wichtigste Erkenntnisse
SRP (Single Responsibility Principle) ist das Prinzip der einzigen Verantwortung, das besagt: Jede Klasse oder jedes Modul sollte genau einen Grund zur Änderung haben. Dies bedeutet nicht, dass eine Klasse genau eine Operation ausführen soll. Es bezieht sich auf eine Gruppe verwandter Aktionen, die durch eine einzige Verantwortung gegenüber einem Akteur verbunden sind.
Robert Martin hat SRP im Sinne von Akteuren neu formuliert: Eine Klasse sollte sich nur auf Anfrage eines Beteiligten oder einer Gruppe von Personen ändern. Wenn zwei verschiedene Akteure Änderungen an derselben Klasse verlangen, ist die Verantwortung falsch aufgeteilt.
Zum Beispiel verletzt eine Employee-Klasse, die gleichzeitig Gehalt berechnet (Anfrage der Buchhaltung) und Berichte erstellt (Anfrage des Managements), SRP. Eine Änderung der Berechnungsregeln könnte die Berichterstellung beeinträchtigen und umgekehrt.
Ein Modul sollte einen und nur einen Grund zur Änderung haben. Der Änderungsgrund wird durch einen Akteur bestimmt — eine Person oder ein System, das die Anforderung initiiert. Wenn Anforderungen von verschiedenen Akteuren zu Änderungen an einem Modul führen, verletzt das Modul SRP.
Das Konzept des Akteurs macht SRP zu einem praktischen Werkzeug für die Architekturanalyse, nicht zu einer abstrakten Empfehlung. Beim Entwurf eines Systems reicht die Frage: „Wer wird darum bitten, diesen Code zu ändern?“ — wenn die Antwort mehr als einen Beteiligten umfasst, sollte die Verantwortung aufgeteilt werden.
Einzige Verantwortung wird durch Gruppierung von Methoden implementiert, die sich aus einem Grund ändern. Eine Klasse wird zu einem „Sammelpunkt“ für verwandte Logik, nicht zu einem „Schweizer Taschenmesser“ für alle Fälle. Dies vereinfacht das Codeverständnis: Der Entwickler sieht die Klasse und versteht sofort ihren Zweck.
Der Mechanismus von SRP basiert auf der Regel der einzigen Änderungsachse. Wenn eine Funktionalität aus unabhängigen Gründen geändert werden kann, sollte sie in separate Klassen extrahiert werden. Verbindungen zwischen diesen Klassen werden durch Komposition oder Delegation hergestellt.
SRP-Verletzung zeigt sich in „God Objects“ — Klassen mit Dutzenden von Methoden, die mit verschiedenen Daten arbeiten. Eine solche Klasse ist schwer zu testen — das Testen einer Methode erfordert die Einrichtung der Umgebung für alle anderen. Die Änderung einer Verantwortung kann eine andere brechen, was den Code zerbrechlich macht.
In der Praxis hilft SRP Entwicklern, die Frage „Wo ist dieser Code?“ zu beantworten. Wenn jede Verantwortung in ihrer eigenen Klasse getrennt ist, dauert das Finden der richtigen Datei Sekunden. In einem Android-Projekt mit MVVM-Architektur bedeutet dies, dass UserViewModel nur für den Zustand des Benutzerbildschirms verantwortlich ist und UserRepository für den Datenabruf. Ein Entwickler, der nach Caching-Logik sucht, geht zu UserCacheRepository, nicht zu ViewModel. Eine solche Code-Organisation beschleunigt die Einarbeitung neuer Teammitglieder und reduziert die Anzahl der Fehler beim Refactoring.
Mobile Entwicklung stellt besondere Anforderungen an die Modularität des Codes. Ein Android-Fragment oder iOS-ViewController wird oft zu einem „Magnet“ für Logik: Tippbehandlung, API-Aufrufe, Antwortanalyse, UI-Updates — alles in einer Klasse. SRP verlangt, diese Verantwortungen zu trennen.
In der Android-Architektur ist SRP in Googles Jetpack-Empfehlungen verankert: ViewModel ist für den Bildschirmzustand zuständig, Repository für Daten, UseCase für Geschäftslogik. Jede Komponente hat einen Grund zur Änderung. In der iOS-Entwicklung folgen die MVVM- und Coordinator-Muster derselben Logik.
Die Befolgung von SRP in mobilen Projekten bringt messbare Vorteile: 40-60% Reduzierung der Klassengröße, weniger Zeit für Code-Reviews und weniger Regressionsfehler beim Hinzufügen neuer Funktionen. Isolierte Module lassen sich leichter mit Unit-Tests abdecken und auf anderen Bildschirmen wiederverwenden.
Unit-Tests von Klassen, die SRP befolgen, benötigen weniger Mock-Objekte und weniger Konfiguration. Wenn eine Klasse eine einzige Verantwortung hat, sind ihre Abhängigkeiten begrenzt. Der Test überprüft ein Verhalten, nicht eine Kombination mehrerer unabhängiger Szenarien.
Laut dem Bericht des Google Testing Blog (2023) zeigen Klassen mit einziger Verantwortung 35% höhere Testabdeckung im Vergleich zu Aggregatorklassen. Entwickler schreiben eher Tests für kleine, verständliche Module.
Betrachten wir eine typische Android-Klasse, die SRP verletzt — sie lädt Daten, analysiert die Antwort und aktualisiert die UI. Nach dem Refactoring ist jede Verantwortung in ihre eigene Komponente getrennt.
// SRP-Verletzung: Eine Klasse macht alles
class BadUserProfileActivity {
fun loadUser(userId: Int) {
// HTTP-Anfrage
// JSON-Parsing
// UI-Update
// Datenbank speichern
}
}
// Nach Anwendung von SRP
class UserRepository {
fun getUser(userId: Int): User
}
class UserViewModel {
private val repo: UserRepository
fun loadUser(userId: Int) { }
}
class UserProfileFragment {
fun render(user: User) { }
}
Ein ähnliches Beispiel in iOS Swift mit Trennung von Netzwerkschicht und Anzeige:
// SRP-Verletzung: ViewController verwaltet Daten und UI
class BadProfileViewController: UIViewController {
func viewDidLoad() {
// URLSession-Anfrage
// JSON dekodieren
// Label aktualisieren
}
}
// Nach Anwendung von SRP
protocol UserServiceProtocol {
func fetchUser(id: Int) async throws -> User
}
class ProfileViewModel {
private let service: UserServiceProtocol
func loadProfile(id: Int) { }
}
class ProfileViewController: UIViewController {
func display(user: User) { }
}
SRP-Refactoring verkompliziert die Architektur nicht — es verteilt die Verantwortung neu. Die Code-Menge kann durch die Beseitigung von Duplikaten sogar abnehmen. Jede neue Klasse hat einen klaren Zweck und kann unabhängig entwickelt werden.
Komposition hilft, SRP dort einzuhalten, wo Vererbung unnötige Kopplungen erzeugt. Anstelle einer Superklasse mit Dutzenden von Methoden erhält die Unterklasse über den Konstruktor einen Satz spezialisierter Objekte. Jedes Objekt ist für seine eigene Funktionalität verantwortlich.
In der Android-Entwicklung ermöglicht das Decorator-Muster das Hinzufügen von Verantwortungen ohne Änderung der ursprünglichen Klasse. In iOS trennt eine Middleware-Kette in der Netzwerkschicht Logging, Caching und Authentifizierung in separate Module.
Die häufigste Verletzung ist eine „God Class“: eine Klasse, die die Datenbank verwaltet, Benachrichtigungen sendet, Berichte erstellt und Benutzereingaben verarbeitet. Eine solche Klasse wird zum Flaschenhals des Projekts: Jede Änderung erfordert vollständige Regressionstests.
In der mobilen Entwicklung entsteht eine SRP-Verletzung durch die Vermischung von Geschäftslogik und UI-Logik in Activity, Fragment oder ViewController. Wenn ein onClickListener gleichzeitig Daten validiert, eine API aufruft und die Sichtbarkeit von Schaltflächen aktualisiert — das ist eine direkte Verletzung des Prinzips der einzigen Verantwortung.
Die Folgen von SRP-Verletzungen umfassen: Schwierigkeiten bei der parallelen Entwicklung (Konflikte in einer Datei), erschwertes Unit-Testing, hohe Kosten für Änderungen und geringere Lesbarkeit des Codes. Projekte mit systematischen SRP-Verletzungen benötigen 2-3 mal mehr Zeit für das Hinzufügen neuer Funktionen.
SRP-Verletzungen sind an indirekten Anzeichen erkennbar: Die Klasse überschreitet 200 Zeilen, importiert Module aus verschiedenen Anwendungsschichten (UI + Network + Database), hat mehr als 5 öffentliche Methoden zu verschiedenen Themen. Die Kohäsionsmetrik ist ein statistischer Indikator: Eine niedrige Kohäsion der Methoden innerhalb einer Klasse weist auf eine SRP-Verletzung hin.
Verwenden Sie statische Analysetools, um SRP-Verletzungen zu erkennen: für Android — Detekt mit der TooManyFunctions-Regel, für iOS — SwiftLint mit der file_length-Regel. Diese Dienstprogramme heben Klassen hervor, die Größen- und Komplexitätsschwellen überschreiten.
Das Refactoring von Klassen, die SRP verletzen, erfolgt durch Extract Class oder Extract Delegate: Eine Gruppe verwandter Methoden wird in eine separate Klasse extrahiert, und die ursprüngliche Klasse delegiert Aufrufe an sie. Die schrittweise Anwendung solcher Refactorings verwandelt eine „God Class“ in eine Reihe lose gekoppelter Module, jedes mit einer einzigen Verantwortung. Dieser Ansatz ermöglicht die Verbesserung der Architektur ohne Unterbrechung der Entwicklung — das Refactoring erfolgt iterativ, ein Modul nach dem anderen.
Häufig gestellte Fragen
Nein. SRP geht es nicht um die Anzahl der Methoden, sondern um die Anzahl der Änderungsgründe. Eine Klasse kann Dutzende von Methoden haben, wenn sie alle eine Verantwortung gegenüber einem Akteur erfüllen. Eine einzige Methode ist das andere Extrem, das zu einer übermäßigen Fragmentierung des Codes führt.
Es ist dasselbe Prinzip. Single Responsibility Principle wird sowohl als „einzige Verantwortung“ als auch als „einzige Pflicht“ übersetzt. Der Begriff „Verantwortung“ spiegelt das Wesen besser wider: Es geht um die Verantwortung gegenüber einem Akteur, nicht um eine technische Funktion.
Repository ist ein direktes Ergebnis der Anwendung von SRP auf die Datenschicht. Anstatt die Datenzugriffslogik auf ViewModel oder UseCase zu verteilen, übernimmt Repository eine einzige Verantwortung: Bereitstellung von Daten mit Quellenabstraktion. Dies ist eine klassische SRP-Implementierung in der mobilen Architektur.
Ja, SRP verbietet Abhängigkeiten nicht. Eine Klasse mit einer einzigen Verantwortung kann einen Teil der Arbeit durch Komposition an andere Klassen delegieren. Wichtig ist, dass diese delegierten Aufgaben Teil derselben Verantwortung sind und keinen unabhängigen Änderungsgrund darstellen.
Stellen Sie die Frage: „Welche Akteure könnten Änderungen an dieser Klasse verlangen?“ Wenn die Antwort mehr als einen Akteur enthält, ist SRP verletzt. Zusätzlich: Versuchen Sie, den Zweck der Klasse in einem Satz ohne die Konjunktion „und“ zu beschreiben. Wenn das nicht gelingt, macht die Klasse zu viel.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch