Načela SOLID obsegajo pet smernic za čisto, vzdr­žlji­vo in pri­la­go­dlji­vo kodo v objektno usmer­je­nem pro­gra­mi­ra­nju. Uporaba in upo­šte­va­nje teh načel omogoča ra­zu­mlji­vo zasnovo pro­gram­ske opreme tudi v dol­go­roč­nih razvojnih projektih. S pomočjo teh načel je mogoče ne le napisati boljšo kodo, temveč tudi lažje vzdr­že­va­ti obstoječo kodo.

Kaj so načela SOLID in kdo jih je oblikoval?

Dobra izvorna koda temelji na pravilih, pro­gram­skih pa­ra­di­gmah in primernem pro­gram­skem slogu, ki omogočajo učin­ko­vi­to in pregledno kodo. Prav to za­go­ta­vlja­jo pet načel SOLID, ki so jih obli­ko­va­li Robert C. Martin, Bertrand Meyer in Barbara Liskov. Če upo­šte­va­te ta načela pri objektno usmer­je­nem pro­gra­mi­ra­nju (OOP) z jeziki, kot sta Python ali Java, ne boste le napisali boljše kode, ampak boste tudi za­go­to­vi­li učin­ko­vi­tej­še vzdr­že­va­nje kode, traj­no­stno in pri­la­go­dlji­vo zasnovo pro­gram­ske opreme ter večjo varnost na dolgi rok.

Ime SOLID sim­bo­li­zi­ra trdne temelje pro­gra­mi­ra­nja, ki jih mora imeti vsak, ki se želi naučiti pro­gra­mi­ra­ti. Akronim je ustvaril Michael Feathers, ki je za njegovo sestavo uporabil začetnice vseh petih načel:

  • Načelo ene od­go­vor­no­sti: Razred naj ima en in samo en razlog za spremembo.
  • Načelo odprtosti-zaprtosti: Pro­gram­ske entitete (razredi, moduli, funkcije itd.) morajo biti odprte za raz­ši­ri­tev, vendar zaprte za spremembe.
  • Liskovovo načelo na­do­me­stlji­vo­sti: Po­d­ra­zre­di morajo biti sposobni po­de­do­va­ti in im­ple­men­ti­ra­ti vse metode in lastnosti nad­ra­zre­da.
  • Načelo ločevanja vmesnikov: Vmesniki ne smejo vsebovati več metod, kot jih je potrebno za im­ple­men­ta­ci­jo razredov.
  • Načelo obrnjene od­vi­sno­sti: Razredi ne smejo biti odvisni od drugih razredov, ampak od vmesnikov ali ab­strak­tnih razredov.

Kakšne prednosti prinašajo načela SOLID?

Kjer ni pravil, nastane kaos, kar je še posebej opazno pri pro­gra­mi­ra­nju. Že majhne napake, ne­toč­no­sti in vrzeli lahko dol­go­roč­no pov­zro­či­jo, da dobra izvorna koda postane popolnoma ne­u­po­rab­na, če se jih ne odpravi. Včasih za­do­stu­je­jo že zapletene razrede, ki otežujejo im­ple­men­ta­ci­jo, ali po­d­ra­zre­di, ki nimajo po­sa­me­znih lastnosti svojih nad­ra­zre­dov. Načela SOLID za­go­ta­vlja­jo, da je treba z re­fak­to­ri­ra­njem popraviti čim manj kode.

Načela SOLID pri pisanju kode:

  • Jasno, pregledno in privlačno: pro­gram­ska oprema in koda sta lažje ra­zu­mlji­vi, učin­ko­vi­tej­ši in preprosto izgledata bolje.
  • Enostavno vzdr­že­va­nje: Preprosta in jasna struktura olajša več so­de­lav­cem vzdr­že­va­nje in upra­vlja­nje tako nove kot stare kode.
  • Pri­la­go­dlji­va, raz­šir­lji­va, ponovno uporabna: Zaradi iz­bolj­ša­ne ber­lji­vo­sti, zmanjšane kom­ple­ksno­sti in od­go­vor­no­sti ter zmanjšane od­vi­sno­sti od razredov je kodo mogoče bolje urejati, pri­la­ga­ja­ti in raz­šir­ja­ti prek vmesnikov ter jo fle­ksi­bil­no ponovno uporabiti.
  • Manj nagnjena k napakam: Čista koda s preprosto strukturo pomeni, da spremembe v enem delu kode ne vplivajo naključno na druga področja ali funkcije.
  • Varno in za­ne­slji­vej­še: Zmanj­ša­nje ali odprava ran­lji­vo­sti, ne­zdru­žlji­vo­sti in napak izboljša funk­ci­o­nal­nost in za­ne­slji­vost sistemov, kar po­sle­dič­no izboljša varnost.

Kaj pomeni vsako od načel SOLID?

Načela SOLID sodijo med zlata pravila dobrega pro­gra­mi­ra­nja in bi jih moral poznati vsak, ki se ukvarja z objektno usmer­je­nim pro­gra­mi­ra­njem. V na­da­lje­va­nju bomo vsako načelo podrobno razložili.

SRP: Načelo ene od­go­vor­no­sti

Robert C. Martin je prvotno opre­de­li­tev tega načela oblikoval v knjigi »Agile Software De­ve­lop­ment: Prin­ci­ples, Patterns and Practices«; v njej je zapisal:

Quote

»Vsak pro­gram­ski modul naj ima en sam razlog za spremembo.«

Načelo ene od­go­vor­no­sti (SRP) določa, da naj bi imel vsak razred v objektno usmer­je­nem pro­gra­mi­ra­nju (OOP) le eno od­go­vor­nost. To pomeni, da naj bi obstajal le en razlog za spre­mi­nja­nje razreda. V nasprotju s splošnimi razlagami to ne pomeni, da lahko razred ali modul opravlja le eno nalogo. Pomeni pa, da naj bi bil odgovoren le za določene naloge, ki se v idealnem primeru ne pre­kri­va­jo z drugimi področji.

Pre­kri­va­nje od­go­vor­no­sti, na primer ponujanje funkcij za različne poslovne segmente, lahko vpliva na delovanje razreda, kadar pride do sprememb v enem od segmentov. Zaradi več­pla­stnih od­go­vor­no­sti in številnih od­vi­sno­sti lahko že ena sama sprememba na enem področju povzroči napake v kodi ali potrebo po dodatnih spre­mem­bah.

Načelo enotne od­go­vor­no­sti (SRP) je zasnovano za ustvar­ja­nje povezanih modulov, ki so namenjeni izvajanju kon­kre­tnih, natančno opre­de­lje­nih funkcij ali objektov. Zaradi jasne, struk­tu­ri­ra­ne zasnove z mi­ni­mal­ni­mi od­vi­snost­mi in ne­od­vi­sni­mi izvedbami je mogoče spremembe in pri­la­go­di­tve izvajati učin­ko­vi­te­je, hitreje in brez težav.

Note

Razredi, znani tudi kot tipi objektov, so osrednji elementi objektno usmer­je­ne­ga pro­gra­mi­ra­nja (OOP). Lahko jih razumemo kot načrte za objekte, ki opre­de­lju­je­jo njihove lastnosti, tako da je mogoče v pro­gram­ski opremi po­u­stva­ri­ti objekte in pojme iz re­snič­ne­ga sveta. Razrede, znane tudi kot module, pogosto pri­mer­ja­jo s tipi datotek.

OCP: načelo odprtosti in zaprtosti

Po mnenju Roberta C. Martina in Bertranda Meyera v knjigi »Object Oriented Software Con­struc­ti­on« OCP navaja:

Quote

»Pro­gram­ske enote (razredi, moduli, funkcije itd.) morajo biti odprte za raz­ši­ri­tev, vendar zaprte za spre­mi­nja­nje«.

OCP za­go­ta­vlja, da vam za izvedbo sprememb ni treba na novo pisati jedra pro­gram­ske opreme. Če so potrebne globoke spremembe kode, obstaja tveganje za neopazne napake in »code smells«. Dobro struk­tu­ri­ra­na koda mora vsebovati vmesnike, prek katerih jo je mogoče razširiti z dodatnimi funk­ci­ja­mi. Ključna beseda pri tem je dedovanje razredov.

Nove funkcije in raz­ši­ri­tve z jasno opre­de­lje­ni­mi novimi funk­ci­ja­mi in metodami, ki jih je treba im­ple­men­ti­ra­ti, je mogoče prek vmesnika v obliki po­d­ra­zre­dov enostavno dodati nad­ra­zre­du. Na ta način ni treba posegati v že napisano, stabilno kodo. To po­e­no­sta­vi vzdr­že­va­nje in po­so­da­blja­nje pro­gram­ske opreme ter prek vmesnikov znatno izboljša učin­ko­vi­tost ponovne uporabe stabilnih elementov kode.

LSP: Liskovovo načelo na­do­me­stlji­vo­sti

Po mnenju Barbare H. Liskov in Jeannette M. Wing v članku »Be­ha­vi­o­ral Subtyping Using In­va­ri­ants and Con­stra­ints« LSP navaja, da:

Quote

»Naj bo q(x) lastnost, ki jo je mogoče dokazati za objekte x tipa T. Potem naj bi bilo q(y) mogoče dokazati za objekte y tipa S, kjer je S podtip tipa T«.

Morda se sliši skriv­no­stno, a je v resnici precej enostavno razumeti: povezane ali raz­šir­je­ne po­d­ra­zre­de morajo delovati tako kot njihovi nad­ra­zre­di ali osnovni razredi. To pomeni, da mora vsak podrazred prek dedovanja ohraniti lastnosti svojega nad­ra­zre­da, te lastnosti pa se v po­d­ra­zre­du ne smejo spre­mi­nja­ti. Načeloma morajo biti za­men­lji­ve, od todi izhaja načelo za­men­lji­vo­sti. Nad­ra­zre­di pa se lahko spre­mi­nja­jo.

Da bi to pojasnili, si oglejmo klasičen primer Roberta C. Martina o pra­vo­ko­tni­kih in kvadratih. V pouku ge­o­me­tri­je se naučimo naslednje načelo: vsak kvadrat je pra­vo­ko­tnik, vendar ni vsak pra­vo­ko­tnik kvadrat. Kvadrat ima namreč ne le pra­vo­ko­tne stranice, kot jih imajo pra­vo­ko­tni­ki, ampak so vse njegove stranice tudi enako dolge.

V pro­gra­mi­ra­nju domneva, da so podobni ali na videz identični razredi med seboj povezani ali odvisni, vodi do napak, ne­spo­ra­zu­mov in nejasne kode. Zato v pro­gra­mi­ra­nju razred »Rectangle« ni kvadrat, razred »Square« pa ni pra­vo­ko­tnik. Oba sta ločena in im­ple­men­ti­ra­na ločeno. Brez in­te­gri­ra­ne povezave med razredi ne­spo­ra­zu­mi ne morejo voditi do napak med razredi. To poveča varnost in sta­bil­nost pri zamenjavi im­ple­men­ta­cij v po­d­ra­zre­dih ali nad­ra­zre­dih brez posledic.

ISP: Načelo ločevanja vmesnikov

Po mnenju Roberta C. Martina v delu »Načelo ločevanja vmesnikov« je ISP opre­de­lje­no kot sledi:

Quote

»Stranke ne bi smele biti pri­si­lje­ne, da so odvisne od vmesnikov, ki jih ne upo­ra­blja­jo.«

V ISP je navedeno, da upo­rab­ni­ki ne bi smeli biti pri­si­lje­ni upo­ra­blja­ti vmesnikov, ki jih ne po­tre­bu­je­jo. Z drugimi besedami: da bi strankam omogočili dostop do funkcij določenih razredov, se obli­ku­je­jo novi, manjši vmesniki, pri­la­go­je­ni kon­kre­tnim zahtevam. S tem se prepreči, da bi vmesniki postali preveliki, in zagotovi, da med razredi ne nastanejo premočne od­vi­sno­sti. Prednost tega pristopa je, da je pro­gram­ska oprema z ločenimi razredi in več manjšimi vmesniki, pri­la­go­je­ni­mi kon­kre­tnim zahtevam, lažje vzdr­že­va­ti.

DIP: Načelo obrnjenih od­vi­sno­sti

Po mnenju Roberta C. Martina je »načelo obrnjenih od­vi­sno­sti«, peto in zadnje izmed načel SOLID, naslednje:

Quote

„A. Moduli višje ravni ne smejo biti odvisni od modulov nižje ravni. Oba morata biti odvisna od ab­strak­cij. B. Ab­strak­ci­je ne smejo biti odvisne od po­drob­no­sti.“

Načelo DIP za­go­ta­vlja, da se posamezne funk­ci­o­nal­no­sti in od­vi­sno­sti znotraj plasti izvorne kode opirajo na ab­strak­tne vmesnike, ne pa ne­po­sre­dno druga na drugo. Pro­gram­ske ar­hi­tek­tu­re so običajno raz­de­lje­ne na višje upo­rab­ni­ške ravni in nižje, bolj ab­strak­tne ravni. Logično bi bilo misliti, da ab­strak­tna podlaga vpliva na delovanje zgornjih plasti. Vendar pa načelo DIP tukaj opozarja na po­ten­ci­al­no težavo, saj ustvarja od­vi­sno­sti višjih ravni od nižjih, kar lahko povzroči težave.

Namesto da bi višje ravni po­ve­zo­va­li z nižjimi, morajo razredi na višjih in nižjih ravneh temeljiti na ab­stra­knih, vmesnih vmesnikih. Ti vmesniki pri­do­bi­va­jo funk­ci­o­nal­no­sti, potrebne na višjih ravneh, iz nižjih ravni in jih dajo na voljo. Na ta način se lahko izognemo hi­e­rar­hi­ji od­vi­sno­sti od spodaj navzgor, ki lahko sčasoma privede do napak v kodi. To olajša ponovno uporabo modulov in omogoča spremembe v nižjih razredih, ne da bi to vplivalo na višje ravni.

Kaj se zgodi, če se načela SOLID ne upo­šte­va­jo?

Pisanje čistega in ber­lji­ve­ga kode, ki po­e­no­sta­vlja vzdr­že­va­nje, bi moralo biti glavni cilj pri razvoju pro­gram­ske opreme. Če raz­vi­jal­ci spre­gle­da­jo ključna navodila, kot so načela SOLID, se lahko kakovost kode močno poslabša zaradi ran­lji­vo­sti, pod­va­ja­nja, na­ko­pi­če­nih napak in pre­ko­mer­nih od­vi­sno­sti. V skrajnih primerih lahko koda sčasoma postane ne­u­po­rab­na. To je pomemben problem pri agilnem razvoju pro­gram­ske opreme, kjer na zahtevnih pro­gram­skih nalogah pogosto dela več ljudi hkrati.

Med posledice neurejene kode ali slabe vzdr­že­va­nja kode spadajo:

  • Zaznamek slabe kode: Kadar koda ni napisana v skladu z ustre­zni­mi standardi, lahko to povzroči »zaznamek slabe kode« ali »smrdljivo kodo«, kar vodi do funk­ci­o­nal­nih napak in ne­zdru­žlji­vih programov.
  • Code rot: Če koda ni vzdr­že­va­na ali po­pra­vlje­na z re­fak­to­ri­ra­njem ali dragim pregledom kode, lahko koda v pre­ne­se­nem pomenu »gnije« in popolnoma izgubi svojo funk­ci­o­nal­nost. Drugi izraz za ne­ber­lji­vo, zapleteno kodo je spaghetti code.
  • Varnostna tveganja: Težave, ki se pojavijo, niso omejene na izpade, zapleteno vzdr­že­va­nje in težave z zdru­žlji­vo­stjo. Obstajajo tudi varnostne vrzeli, ki zlo­na­mer­ni pro­gram­ski opremi omogočajo iz­ko­ri­šča­nje kode, vključno z iz­ko­ri­šča­njem ran­lji­vo­sti zero-day.

Kdo je oblikoval načela SOLID?

Izvor načel SOLID sega v več načel, ki jih je leta 2000 v svojem eseju z naslovom »Design Prin­ci­ples and Design Patterns« prvi pred­sta­vil Robert C. Martin (»Uncle Bob«), eden od po­bu­dni­kov agilnega pro­gra­mi­ra­nja. Načela SOLID so obli­ko­va­li Robert C. Martin, Bertrand Meyer in Barbara Liskov. Ujemljivo kratico je po­pu­la­ri­zi­ral Michael Feathers, ki je začetne črke petih bistvenih načel preuredil v zapomljiv vrstni red.

Katera podobna načela pro­gra­mi­ra­nja obstajajo?

V razvoju pro­gram­ske opreme so načela splošna ali zelo konkretna navodila in pri­po­ro­či­la za delovanje. Poleg načel SOLID, ki so bila razvita za objektno usmerjeno pro­gra­mi­ra­nje, med druga načela za pisanje čiste kode spadajo:

  • Načelo DRY (Don’t repeat yourself – Ne ponavljaj se) za funkcije z eno samo, edin­stve­no pred­sta­vi­tvi­jo
  • Načelo KISS (Keep it simple, stupid) za kodo, se­sta­vlje­no čim bolj preprosto
Go to Main Menu