SRP (Single Responsibility Principle) — het eerste SOLID-principe dat bepaalt: elke klasse of module moet precies één reden hebben om te veranderen. Dit principe werd geformuleerd door Robert Martin in het boek Clean Architecture (2017) en werd de basis van modulair ontwerpen. Volgens dit boek vermindert toepassing van SRP direct de koppeling tussen componenten en elimineert het cascade-veranderingen bij het verbeteren van functionaliteit.
Belangrijkste
SRP (Single Responsibility Principle) — het principe van enkele verantwoordelijkheid dat stelt: elke klasse of module moet precies één reden hebben om te veranderen. Dit betekent niet dat een klasse precies één bewerking moet uitvoeren. Het gaat om een groep gerelateerde acties, verenigd door één verantwoordelijkheid tegenover één actor.
Robert Martin herformuleerde SRP in termen van actoren: een klasse mag alleen veranderen op verzoek van één belanghebbende persoon of één groep mensen. Als twee verschillende actoren een wijziging van dezelfde klasse eisen — is de verantwoordelijkheid onjuist verdeeld.
Bijvoorbeeld de klasse Employee, die tegelijkertijd het salaris berekent (verzoek van boekhouding) en een rapport genereert (verzoek van management), schendt SRP. Een wijziging van de rekenregels kan het genereren van rapporten beïnvloeden en vice versa.
Een module moet één en slechts één reden hebben om te veranderen. De reden voor verandering wordt bepaald door de actor — de persoon of het systeem dat de eis initieert. Als eisen van verschillende actoren leiden tot verandering van één module — schendt de module SRP.
Het concept van actor maakt SRP een praktisch instrument voor architectuuranalyse, geen abstracte aanbeveling. Bij het ontwerpen van een systeem is het voldoende om te vragen: „Wie zal vragen om deze code te wijzigen?” — als het antwoord meer dan één belanghebbende bevat, moet de verantwoordelijkheid worden gesplitst.
Enkele verantwoordelijkheid wordt gerealiseerd door het groeperen van methoden die om één reden veranderen. Een klasse wordt een „verzamelpunt” van gerelateerde logica, geen „Zwitsers zakmes” voor alle gelegenheden. Dit vereenvoudigt het begrijpen van code: de ontwikkelaar ziet de klasse en begrijpt direct het doel ervan.
Het werkingsmechanisme van SRP is gebaseerd op de regel van één veranderingsas. Als functionaliteit om onafhankelijke redenen kan veranderen — moet deze worden ondergebracht in afzonderlijke klassen. De verbindingen tussen deze klassen worden gebouwd via compositie of delegatie.
SRP-schending manifesteert zich in „god-klassen” (God Objects), die tientallen methoden bevatten die met verschillende gegevens werken. Zo'n klasse is moeilijk te testen — het testen van één methode vereist het configureren van de omgeving voor alle andere. Verandering van de ene verantwoordelijkheid kan een andere breken, wat de code broos maakt.
In de praktijk helpt SRP ontwikkelaars om de vraag „waar is deze code?” te beantwoorden. Als elke verantwoordelijkheid in een eigen klasse is ondergebracht, duurt het vinden van het juiste bestand seconden. In een Android-project met MVVM-architectuur betekent dit dat UserViewModel alleen verantwoordelijk is voor de status van het gebruikersscherm en UserRepository voor het ophalen van gegevens. Een ontwikkelaar die op zoek is naar cache-logica gaat naar UserCacheRepository, niet naar ViewModel. Een dergelijke organisatie van code versnelt de onboarding van nieuwe teamleden en vermindert het aantal fouten bij refactoring.
Mobiele ontwikkeling stelt bijzondere eisen aan de modulariteit van code. Android Fragment of iOS ViewController worden vaak „aantrekkingspunten” van logica: het afhandelen van klikken, API-aanroepen, parsren van antwoorden, updaten van UI — alles in één klasse. SRP vereist het scheiden van deze verantwoordelijkheden.
In Android-architectuur is SRP ingebouwd in Google's aanbevelingen voor Jetpack: ViewModel is verantwoordelijk voor de schermstatus, Repository voor gegevens, UseCase voor bedrijfslogica. Elk onderdeel heeft één reden om te veranderen. In iOS-ontwikkeling volgen het MVVM-patroon en Coordinator dezelfde logica.
Het naleven van SRP in mobiele projecten levert meetbare voordelen op: vermindering van de klassengrootte met 40-60%, kortere code-reviewtijd en minder regressiefouten bij het toevoegen van nieuwe functionaliteit. Geïsoleerde modules zijn eenvoudiger te voorzien van unittesten en herbruikbaar in andere schermen.
Unittesten van klassen die SRP naleven vereisen minder mock-objecten en configuraties. Als een klasse één verantwoordelijkheid heeft, zijn de afhankelijkheden beperkt. De test controleert één gedrag, niet een combinatie van meerdere niet-gerelateerde scenario's.
Volgens het rapport van Google Testing Blog (2023) vertonen klassen met één verantwoordelijkheid 35% meer testdekking in vergelijking met aggregerende klassen. Ontwikkelaars schrijven gemakkelijker tests voor kleine, begrijpelijke modules.
Beschouw een typische Android-klasse die SRP schendt — hij laadt gegevens, parst het antwoord en werkt de UI bij. Na refactoring is elke verantwoordelijkheid ondergebracht in een aparte component.
// SRP-schending: één klasse doet alles
class BadUserProfileActivity {
fun loadUser(userId: Int) {
// HTTP-verzoek
// JSON-parsing
// UI-update
// Opslaan in database
}
}
// Na toepassing van SRP
class UserRepository {
fun getUser(userId: Int): User
}
class UserViewModel {
private val repo: UserRepository
fun loadUser(userId: Int) { }
}
class UserProfileFragment {
fun render(user: User) { }
}
Een vergelijkbaar voorbeeld op iOS Swift met scheiding van de netwerklaag en de presentatielaag:
// SRP-schending: ViewController beheert gegevens en UI
class BadProfileViewController: UIViewController {
func viewDidLoad() {
// URLSession-verzoek
// JSON-decodering
// Label-update
}
}
// Na toepassing van 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 maakt de architectuur niet complexer — het herverdeelt de verantwoordelijkheid. De hoeveelheid code kan zelfs afnemen door het elimineren van duplicatie. Elke nieuwe klasse heeft een duidelijk doel en kan onafhankelijk worden ontwikkeld.
Compositie helpt bij het naleven van SRP waar overerving onnodige koppelingen creëert. In plaats van een superklasse met tientallen methoden ontvangt de subklasse een set gespecialiseerde objecten via de constructor. Elk object is verantwoordelijk voor zijn eigen functionaliteit.
In Android-ontwikkeling maakt het Decorator-patroon het mogelijk om verantwoordelijkheden toe te voegen zonder de oorspronkelijke klasse te wijzigen. In iOS verdeelt de Middleware-keten in de netwerklaag loggen, cachen en authenticatie over afzonderlijke modules.
De meest voorkomende schending — „God Class”: een klasse die de database beheert, meldingen verzendt, rapporten genereert en gebruikersinvoer verwerkt. Zo'n klasse wordt een knelpunt in het project: elke wijziging vereist volledige regressietesten.
In mobiele ontwikkeling leidt het mengen van bedrijfslogica en UI-logica in Activity, Fragment of ViewController tot SRP-schending. Wanneer een onClickListener-methode tegelijkertijd gegevens valideert, API aanroept en de zichtbaarheid van knoppen bijwerkt — is dat een directe schending van het principe van enkele verantwoordelijkheid.
Gevolgen van SRP-schending zijn onder meer: moeilijkheden bij parallelle ontwikkeling (conflicten in één bestand), bemoeilijkt unittesten, hoge kosten van wijzigingen en verminderde leesbaarheid van code. Projecten met systematische SRP-schending hebben 2-3 keer meer tijd nodig voor het toevoegen van nieuwe functionaliteit.
SRP-schending kan worden vastgesteld aan de hand van indirecte kenmerken: een klasse bevat meer dan 200 regels, importeert modules uit verschillende lagen van de applicatie (UI + network + database), heeft meer dan 5 openbare methoden met verschillende onderwerpen. Cohesiemetriek — een statistische indicator: lage cohesie van methoden binnen een klasse wijst op SRP-schending.
Voor het opsporen van SRP-schendingen is het nuttig om statische analysetools te gebruiken: voor Android — Detekt met de regel TooManyFunctions, voor iOS — SwiftLint met de regel file_length. Deze tools markeren klassen die de drempelwaarden voor grootte en complexiteit overschrijden.
Refactoring van klassen die SRP schenden wordt uitgevoerd via Extract Class of Extract Delegate: een groep gerelateerde methoden wordt ondergebracht in een aparte klasse en de oorspronkelijke klasse delegeert de aanroepen ernaartoe. Stapsgewijze toepassing van dergelijke refactorings transformeert „God Class” in een set losjes gekoppelde modules, elk met één verantwoordelijkheid. Een dergelijke aanpak maakt het mogelijk de architectuur te verbeteren zonder de ontwikkeling te stoppen — refactoring wordt iteratief uitgevoerd, één module per keer.
Veelgestelde vragen
Nee. SRP gaat niet over het aantal methoden, maar over het aantal redenen voor verandering. Een klasse kan tien methoden hebben als ze allemaal één verantwoordelijkheid tegenover één actor dienen. Eén methode — is het andere uiterste, dat leidt tot overmatige fragmentatie van code.
Het is hetzelfde principe. Single Responsibility Principle wordt zowel vertaald als „enkele verantwoordelijkheid” als „enkele plicht”. De term „verantwoordelijkheid” weerspiegelt de essentie nauwkeuriger: het gaat om verantwoordelijkheid tegenover een actor, niet om een technische functie.
Repository — het directe resultaat van het toepassen van SRP op de gegevenslaag. In plaats van de logica voor gegevenstoegang te verspreiden over ViewModel of UseCase, neemt Repository de enkele verantwoordelijkheid op zich: het leveren van gegevens met abstractie van de bron. Dit is een klassieke implementatie van SRP in mobiele architectuur.
Ja, SRP verbiedt afhankelijkheden niet. Een klasse met één verantwoordelijkheid kan een deel van het werk delegeren aan andere klassen via compositie. Belangrijk is dat deze gedelegeerde taken deel uitmaken van dezelfde verantwoordelijkheid en geen onafhankelijke reden voor verandering vormen.
Stel de vraag: „Welke actoren kunnen vragen om wijziging van deze klasse?” Als het antwoord meer dan één actor bevat — is SRP geschonden. Extra: probeer het doel van de klasse in één zin te beschrijven zonder het voegwoord „en”. Als dat niet lukt — doet de klasse te veel.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook