
Më shpesh has zhvillues që nuk kanë dëgjuar për parimet SOLID (ne . — P.S.) ose programimin orientuar në objekte (OOP), ose kanë dëgjuar, por nuk i përdorin ato në praktikë. Ky artikull shkruan për përfitimet e parimeve OOP që ndihmojnë zhvilluesin në punën e tij të përditshme. Disa nga ato janë mjaft të njohura, të tjera - jo aq shumë, kështu që artikulli do të jetë i dobishëm si për fillestarët ashtu edhe për programuesit me përvojë.
Kujtojmë: për të gjithë lexuesit e “Habr” - një zbritje prej 10,000 rubla për regjistrimin në çdo kurs Skillbox me kodin promocional “Habr”.
Skillbox rekomandon: Kurs online edukativ .
DRY (Mos e përsëris veten)
Një parim mjaft i thjeshtë, thelbi i të cilit është i qartë nga emri: «Mos u përsërit». Për një programues, kjo do të thotë nevoja për të shmangur kodin e përsëritur, si dhe mundësinë për të përdorur abstraksionin në punën e tij.
Nëse ka dy segmente të përsëritura në kod, ato duhet të bashkohen në një metodë. Nëse një vlerë e caktuar është përdorur më shumë se një herë, ajo duhet të konvertohet në një konstante publike.
Kjo është e nevojshme për të thjeshtuar kodin dhe për të lehtësuar mbështetje, që është qëllimi kryesor i OOP. Nuk duhet të abuzohet me bashkimin gjithashtu, pasi e njëjta kod nuk do të kalojë verifikimin si me OrderId ashtu edhe me SSN.
Inkapcizimi i ndryshimeve
Produktet software të shumicës së kompanive vazhdojnë të zhvillohen. Kështu, në kodin duhet bërë ndryshime, ai duhet mbështetur. Mund të thjeshtoni jetën tuaj duke e përdorur inkapsulimin. Kjo do të lejojë që baza ekzistuese e kodit të testohet dhe mbështetet më efikas. .
Nëse shkruani në Java, atëherë .
Parimi i hapjes/mbylljes
Ky parim mund të mbahet lehtë mend nëse lexoni deklaratën e mëposhtme: «Entitetet software (klasat, modulat, funksionet, etj.) duhet të jenë të hapura për zgjerim, por të mbyllura për ndryshim». Në praktikë kjo do të thotë se ato mund të lejojnë të ndryshojnë sjelljen e tyre pa ndryshuar kodin burimor.
Ky parim është i rëndësishëm kur ndryshimet në kodin burimor kërkojnë shqyrtimin e tij, testimin modular dhe procedura të tjera. Kodi që i nënshtrohet parimit të hapjes/mbylljes nuk ndryshohet gjatë zgjerimit, prandaj ka shumë më pak probleme me të.
Ky është një shembull kodi që shkel këtë parim.

Nëse në të duhet të bëni ndonjë ndryshim, do të nevojitet shumë kohë, pasi do të duhet të ndryshoni të gjitha pjesët e kodit që kanë lidhje me fragmentin e nevojshëm.
A propos, hapja-mbyllja është një nga parimet SOLID.
Parimi i përgjegjësisë së vetme (SRP)
Një tjetër parim nga grupi SOLID. Ai thotë se «ka vetëm një arsye që çon në ndryshimin e një klase». Klasa zgjidh vetëm një problem. Ajo mund të ketë disa metoda, por çdo njëra përdoret vetëm për të zgjidhur problemin e përgjithshëm. Të gjitha metodat dhe pronësitë duhet të shërbejnë vetëm për këtë.

Vlera e këtij parimi qëndron në atë se ai dobëson lidhjen midis komponentit të veçantë të softuerit dhe kodit. Nëse shtoni më shumë se një funksionalitet në një klasë, kjo vendos një lidhje midis dy funksioneve. Kështu, nëse ndryshoni një prej tyre, ka një mundësi të madhe që të dëmtoni tjetrën, lidhur me të parën. Dhe kjo do të thotë rritjen e cikleve të testimit për të identifikuar problemet paraprakisht.
Parimi i opsionit të varësisë (DIP)

Më lart kemi dhënë një shembull kode ku AppManager varet nga EventLogWriter, i cili nga ana e tij është i lidhur ngushtë me AppManager. Nëse kërkohet një mënyrë tjetër për të treguar njoftimin, qoftë kjo njoftim push, SMS ose email, duhet të ndryshoni klasën AppManager.
Problemi mund të zgjidhet duke përdorur DIP. Në vend të AppManager, ne kërkojmë EventLogWriter, i cili do të introdukohet nëpërmjet framework-ut.
DIP ofron mundësinë për të zëvendësuar module të veçanta me të tjera, duke ndryshuar modulimin e varësisë. Kjo lejon ndryshimin e një moduli pa ndikuar në të tjerët.
Kompozimi në vend të trashëgimisë
Ka dy mënyra kryesore për të ripërdorur kodin - trashëgimi dhe kompozim, dhe secila ka avantazhet dhe disavantazhet e saj. Zakonisht preferohet e dyta, pasi është më fleksibile.
Kompozimi ofron mundësinë për të ndryshuar sjelljen e klasës gjatë ekzekutimit duke vendosur pronësitë e saj. Kur implementohen ndërfaqet, përdoret polimorfizmi, i cili ofron një implementim më fleksibël.
Madje “Effective Java” i Joshua Bloch këshillon që t'i jepet përparësi kompozimit në vend të trashëgimisë.
Parimi i zëvendësimit të Barbara Liskov (LSP)
Një tjetër parim nga mjeti SOLID. Ai thotë se nënklasat duhet të jenë të zëvendësueshme për superklasën. Kështu, metodat dhe funksionet që punojnë me superklasën duhet të kenë mundësinë të punojnë pa probleme edhe me nënklasat e saj.
LSP është i lidhur si me parimin e përgjegjësisë së vetme, ashtu edhe me parimin e ndarjes së përgjegjësisë. Nëse një klasë ofron më shumë funksionalitete se sa nënklasa, atëherë kjo e fundit nuk do të mbështesë disa funksione, duke shkelur këtë parim.
Ja një fragment kodi që është në kundërshtim me LSP.

Metoda area(Rectangle r) llogarit sipërfaqen e Rectangle. Programi do të bjerë pas ekzekutimit të Square, sepse Square këtu nuk është një Rectangle. Sipas parimit LSP, funksionet që përdorin referenca në klasat bazë duhet të jenë në gjendje të përdorin edhe objektet e klasave të derivuara pa udhëzime shtesë.
Ky parim, i cili është një definicion specifik i nënklasës, u propozua nga Barbara Liskov në vitin 1987 në një konferencë në një fjalim kryesor me titull "Abstraksioni e të dhënave dhe hierarkia" — nga këtu dhe emri i tij.
Parimi i ndarjes së interfesës (ISP)
Një parim tjetër SOLID. Sipas tij, një interfesë që nuk përdoret nuk duhet të zbatohet. Ndjekja e këtij parimi ndihmon sistemin të mbetet fleksibël dhe i përshtatshëm për rifaktorizim kur ndryshohet logjika e punës.
Kjo situatë ndodh shpesh kur interfesa përmban disa funksionalitete, dhe klienti ka nevojë vetëm për një prej tyre.
Duke qenë se shkruhen interfesa është një detyrë e vështirë, pas përfundimit të punës, ta ndryshosh atë pa prishur diçka, do të jetë problem.
Avantazhi i parimit ISP në Java është se fillimisht duhet të zbatohen të gjitha metodat, dhe vetëm pastaj ato mund të përdoren nga klasat. Prandaj, ky parim ofron mundësinë për të reduktuar numrin e metodave.

Programimi për interfesën, dhe jo për zbatimin
Këtu gjithçka është e qartë nga emri. Rrjedhimi i këtij parimi çon në krijimin e kodit fleksibël, i cili është në gjendje të punojë me çdo zbatim të ri të interfesës.
Duhet të përdoren tipa interfese për variablat, llojet e kthimit ose llojin e argjumentit të metodës. Një shembull — përdorimi i SuperClass, e jo SubClass.
Pra:
List numbers = getNumbers();
Dhe jo:
ArrayList numbers = getNumbers();
Ja një zbatim praktik të asaj që është thënë më sipër.

Parimi i delegimit
Një shembull i zakonshëm — metodat equals() dhe hashCode() në Java. Kur është e nevojshme të krahasohen dy objekte, kjo veprim delegohet klasës përkatëse në vend të klientit.
Avantazhi i këtij parimi është se përjashtohet dublimi i kodit dhe ndryshimi i sjelljes është relativisht i thjeshtë. Ai gjithashtu aplikohet për delegimin e ngjarjeve.

Të gjithë këta parime lejojnë shkruarjen e kodit më fleksibël, të bukur dhe të besueshëm me lidhshmëri të lartë dhe varësisë të ulët. Sigurisht, teoria është e mirë, por që zhvilluesi të vërtetë të fillojë ta përdorë njohurinë e fituar, nevojitet praktikë. Hapi tjetër pas zotërimit të parimeve të OOP mund të jetë studimi i modeleve të dizajnit për të zgjidhur probleme të zakonshme në zhvillimin e softuerit.
Skillbox rekomandon:
- Kurs praktik .
- Kursi online i aplikimit .
- Kurs praktik dyvjeçar .
Burimi: habr.com
