Načelo pojedinačne odgovornosti u Javi

1. Pregled

U ovom uputstvu razgovarat ćemo o Jedinstvenom principu odgovornosti, kao jednom od SOLID principa objektno orijentiranog programiranja.

Sve u svemu, detaljno ćemo proučiti što je ovo načelo i kako ga primijeniti prilikom dizajniranja našeg softvera. Nadalje, objasnit ćemo kada ovo načelo može zavarati.

* SRP = Načelo pojedinačne odgovornosti

2. Načelo jedinstvene odgovornosti

Kao što i samo ime govori, ovo načelo kaže da svaki razred bi trebao imatijedna odgovornost, jedna jedina svrha. To znači da će razred raditi samo jedan posao, što nas navodi na zaključak da bi ga trebalo imati samo jedan razlog za promjenu.

Ne želimo predmete koji znaju previše i imaju nepovezano ponašanje. Te je klase teže održavati. Na primjer, ako imamo klasu koju mnogo mijenjamo i iz različitih razloga, onda bi ovu klasu trebalo podijeliti na više klasa, od kojih svaka rješava jednu brigu. Sigurno, ako se dogodi pogreška, bit će je lakše pronaći.

Razmotrimo klasu koja sadrži kôd koji na neki način mijenja tekst. Jedini posao ove klase trebao bi biti manipuliranje tekstom.

javna klasa TextManipulator {private String text; javni TextManipulator (tekst u nizu) {this.text = text; } javni String getText () {return tekst; } javna praznina appendText (String newText) {text = text.concat (newText); } javni String findWordAndReplace (Riječ niza, Riječ koja zamjenjuje Riječ) {if (text.contens (word)) {text = text.replace (word, replaceWord); } vratiti tekst; } javni String findWordAndDelete (niz riječi) {if (text.contens (word)) {text = text.replace (word, ""); } vratiti tekst; } public void printText () {System.out.println (textManipulator.getText ()); }}

Iako se ovo može činiti u redu, to nije dobar primjer SRP-a. Evo nas dvaodgovornosti: manipuliranje i ispis teksta.

Postojanje metode koja ispisuje tekst u ovoj klasi krši načelo jedinstvene odgovornosti. U tu svrhu trebali bismo stvoriti drugu klasu koja će se baviti samo ispisom teksta:

javna klasa TextPrinter {TextManipulator textManipulator; javni TextPrinter (TextManipulator textManipulator) {this.textManipulator = textManipulator; } public void printText () {System.out.println (textManipulator.getText ()); } public void printOutEachWordOfText () {System.out.println (Arrays.toString (textManipulator.getText (). split (""))); } javna praznina printRangeOfCharacters (int startIndex, int endIndex) {System.out.println (textManipulator.getText (). podniz (startIndex, endIndex)); }}

Sada, u ovoj klasi, možemo stvoriti metode za onoliko varijacija ispisa teksta koliko želimo, jer je to njegov posao.

3. Kako ovaj princip može dovesti u zabludu?

Trik implementacije SRP-a u naš softver je poznavanje odgovornosti svakog razreda.

Međutim, svaki programer ima svoju viziju svrhe nastave, što stvari čini zeznutima. Budući da nemamo stroge upute kako provesti ovo načelo, preostaju nam naša tumačenja koja će biti odgovornost.

To znači da ponekad samo mi, kao dizajneri naše aplikacije, možemo odlučiti je li nešto u okviru klase ili ne.

Kada pišemo nastavu prema SRP principu, moramo razmišljati o domeni problema, poslovnim potrebama i arhitekturi aplikacije. Vrlo je subjektivan, što otežava provedbu ovog načela nego što se čini. Neće biti tako jednostavno kao primjer koji imamo u ovom vodiču.

To nas vodi do sljedeće točke.

4. Kohezija

Slijedeći SRP princip, naše će se nastave pridržavati jedne funkcije. Njihove metode i podaci odnosit će se na jednu jasnu svrhu. To znači visoka kohezija, kao i robusnost, koja zajedno smanjuje pogreške.

Pri dizajniranju softvera temeljenog na principu SRP, kohezija je ključna jer nam pomaže pronaći jedinstvene odgovornosti za svoje satove. Ovaj koncept također nam pomaže pronaći razrede koji imaju više od jedne odgovornosti.

Vratimo se našem TextManipulator metode klase:

... javna praznina appendText (String newText) {text = text.concat (newText); } javni String findWordAndReplace (Riječ niza, String replaceWord) {if (text.contens (word)) {text = text.replace (word, replaceWord); } vratiti tekst; } javni String findWordAndDelete (niz riječi) {if (text.contens (word)) {text = text.replace (word, ""); } vratiti tekst; } ...

Ovdje imamo jasan prikaz onoga što ova klasa radi: Manipulacija tekstom.

Ali, ako ne razmišljamo o koheziji i nemamo jasnu definiciju odgovornosti ove klase, mogli bismo reći da su pisanje i ažuriranje teksta dva različita i odvojena posla. Vođeni ovom mišlju, možemo zaključiti da bi ovo trebale biti dvije odvojene klase: WriteText i UpdateText.

U stvarnosti bismo i dobili dvije klase koje su usko povezane i labavo povezane, koje bi gotovo uvijek trebalo koristiti zajedno. Ove tri metode mogu izvode različite operacije, ali one u osnovi služe jednoj jedinoj svrsi: Manipulacija tekstom. Ključno je ne pretjerano razmišljati.

LCOM je jedan od alata koji može pomoći u postizanju visoke kohezije u metodama. U srži, LCOM mjeri vezu između komponenata klase i njihov međusobni odnos.

Martin Hitz i Behzad Montazeri predstavili su LCOM4, ​​koji je Sonarqube neko vrijeme mjerio, ali je od tada zastario.

5. Zaključak

Iako je naziv principa sam po sebi razumljiv, možemo vidjeti kako ga je lako nepravilno primijeniti. Svakako razdvojite odgovornost svakog razreda pri razvoju projekta i obratite dodatnu pozornost na koheziju.

Kao i uvijek, kôd je dostupan na GitHubu.