Single Responsibility Principle in Java

1. Overzicht

In deze tutorial bespreken we het Single Responsibility-principe, als een van de SOLID-principes van objectgeoriënteerd programmeren.

Over het algemeen gaan we dieper in op wat dit principe is en hoe we het kunnen implementeren bij het ontwerpen van onze software. Verder zullen we uitleggen wanneer dit principe misleidend kan zijn.

* SRP = Single Responsibility Principle

2. Principe van één verantwoordelijkheid

Zoals de naam suggereert, stelt dit principe dat elke klas zou moeten hebbenéén verantwoordelijkheid, één doel. Dit betekent dat een klas maar één taak zal doen, wat ons leidt tot de conclusie dat het zou moeten zijn slechts één reden om te veranderen.

We willen geen objecten die te veel weten en niet-gerelateerd gedrag vertonen. Deze lessen zijn moeilijker te onderhouden. Als we bijvoorbeeld een klasse hebben die we veel veranderen, en om verschillende redenen, dan moet deze klasse worden opgesplitst in meer klassen, die elk één probleem behandelen. Zeker, als er een fout optreedt, is deze gemakkelijker te vinden.

Laten we eens kijken naar een klasse die code bevat die de tekst op de een of andere manier verandert. De enige taak van deze klas zou moeten zijn het manipuleren van tekst.

openbare klasse TextManipulator {privé String-tekst; openbare TextManipulator (String-tekst) {this.text = text; } public String getText () {retourtekst; } public void appendText (String newText) {text = text.concat (newText); } public String findWordAndReplace (String word, String replacementWord) {if (text.contains (word)) {text = text.replace (word, replacementWord); } terug tekst; } public String findWordAndDelete (String woord) {if (text.contains (word)) {text = text.replace (word, ""); } terug tekst; } openbare ongeldige printText () {System.out.println (textManipulator.getText ()); }}

Hoewel dit misschien goed lijkt, is het geen goed voorbeeld van de SRP. Hier hebben we tweeverantwoordelijkheden: het manipuleren en afdrukken van de tekst.

Het hebben van een methode die tekst in deze klas afdrukt, is in strijd met het Single Responsibility Principle. Voor dit doel moeten we een andere klasse maken, die alleen het afdrukken van tekst kan verwerken:

openbare klasse TextPrinter {TextManipulator textManipulator; openbare TextPrinter (TextManipulator textManipulator) {this.textManipulator = textManipulator; } openbare ongeldige printText () {System.out.println (textManipulator.getText ()); } openbare ongeldige printOutEachWordOfText () {System.out.println (Arrays.toString (textManipulator.getText (). split (""))); } openbare ongeldige printRangeOfCharacters (int startIndex, int endIndex) {System.out.println (textManipulator.getText (). substring (startIndex, endIndex)); }}

Nu kunnen we in deze klasse methoden maken voor zoveel variaties in het afdrukken van tekst als we willen, want dat is zijn taak.

3. Hoe kan dit principe misleidend zijn?

De truc om SRP in onze software te implementeren, is de verantwoordelijkheid te kennen van elke klas.

Echter, elke ontwikkelaar heeft zijn visie op het klassendoel, wat het lastig maakt. Aangezien we geen strikte instructies hebben voor de implementatie van dit principe, blijven we achter met onze interpretaties van wat de verantwoordelijkheid zal zijn.

Dit betekent dat soms alleen wij, als ontwerpers van onze applicatie, kunnen beslissen of iets binnen het bereik van een klas valt of niet.

Bij het schrijven van een les volgens het SRP-principe moeten we nadenken over het probleemdomein, de bedrijfsbehoeften en de applicatiearchitectuur. Het is erg subjectief, wat de implementatie van dit principe moeilijker maakt dan het lijkt. Het zal niet zo eenvoudig zijn als het voorbeeld dat we in deze tutorial hebben.

Dit brengt ons bij het volgende punt.

4. Samenhang

Volgens het SRP-principe houden onze lessen zich aan één functionaliteit. Hun methoden en gegevens zullen betrekking hebben op één duidelijk doel. Dit betekent hoge cohesie, net zoals robuustheid, die samen fouten verminderen.

Bij het ontwerpen van software op basis van het SRP-principe is samenhang essentieel, omdat het ons helpt om enkele verantwoordelijkheden voor onze lessen te vinden. Dit concept helpt ons ook klassen te vinden die meer dan één verantwoordelijkheid hebben.

Laten we teruggaan naar onze TextManipulator klassemethoden:

... public void appendText (String newText) {text = text.concat (newText); } public String findWordAndReplace (String word, String replacementWord) {if (text.contains (word)) {text = text.replace (word, replacementWord); } terug tekst; } public String findWordAndDelete (String woord) {if (text.contains (word)) {text = text.replace (word, ""); } terug tekst; } ...

Hier hebben we een duidelijke weergave van wat deze klasse doet: Tekstmanipulatie.

Maar als we niet nadenken over cohesie en we hebben geen duidelijke definitie van wat de verantwoordelijkheid van deze klas is, zouden we kunnen zeggen dat het schrijven en bijwerken van de tekst twee verschillende en afzonderlijke taken zijn. Onder leiding van deze gedachte kunnen we concluderen dat dit twee afzonderlijke klassen zouden moeten zijn: WriteText en UpdateText.

In werkelijkheid zouden we krijgen twee klassen die nauw met elkaar zijn gekoppeld en losjes samenhangend, die bijna altijd samen moeten worden gebruikt. Deze drie methoden kunnen verschillende bewerkingen uitvoeren, maar ze dienen in wezen één enkel doel: Tekstmanipulatie. De sleutel is om niet te lang na te denken.

Een van de tools die kunnen helpen bij het bereiken van een hoge cohesie in methoden is LCOM. Eigenlijk, LCOM meet de verbinding tussen klassencomponenten en hun relatie tot elkaar.

Martin Hitz en Behzad Montazeri introduceerden LCOM4, ​​dat Sonarqube een tijdje heeft gedoseerd, maar sindsdien is verouderd.

5. Conclusie

Hoewel de naam van het principe voor zichzelf spreekt, kunnen we zien hoe gemakkelijk het is om het op een verkeerde manier te implementeren. Zorg ervoor dat je de verantwoordelijkheid van elke klas onderscheidt bij het ontwikkelen van een project en besteed extra aandacht aan samenhang.

Zoals altijd is de code beschikbaar op GitHub.