SOLID principai – tai penkios gairės, pa­de­dan­čios kurti aiškų, lengvai pri­žiū­ri­mą ir lanksčią prog­ra­mi­nę įrangą ob­jek­ti­nio prog­ra­ma­vi­mo srityje. Taikant ir laikantis šių principų, net ir ilgai trun­kan­čių kūrimo projektų metu gaunamas lengvai su­pran­ta­mas prog­ra­mi­nės įrangos projektas. Laikantis šių principų, ne tik galima rašyti geresnį kodą, bet ir lengviau pri­žiū­rė­ti esamą kodą.

Kas yra SOLID principai ir kas juos sukūrė?

Geras šaltinio kodas prasideda nuo taisyklių, prog­ra­ma­vi­mo paradigmų ir tinkamo prog­ra­ma­vi­mo stiliaus, už­tik­ri­nan­čių efektyvų ir tvarkingą kodą. Būtent tai ga­ran­tuo­ja penki SOLID principai, kuriuos su­for­mu­la­vo Robertas C. Martinas, Ber­tran­das Meyeris ir Barbara Liskov. Lai­ky­da­mie­si šių principų ob­jek­ti­nio prog­ra­ma­vi­mo (OOP) kalba, pa­vyz­džiui, Python ar Java, ne tik rašysite geresnį kodą, bet ir už­tik­rin­si­te efek­ty­ves­nę kodo priežiūrą, tvarų ir lankstų prog­ra­mi­nės įrangos dizainą bei didesnį saugumą il­ga­lai­kė­je per­spek­ty­vo­je.

Pa­va­di­ni­mas „SOLID“ sim­bo­li­zuo­ja tvirtą prog­ra­ma­vi­mo pagrindą, kurį turėtų turėti kiek­vie­nas, norintis išmokti prog­ra­muo­ti. Šią santrumpą sukūrė Michaelas Fe­at­her­sas, paimdamas po pirmąją kiekvieno iš penkių principų raidę:

  • Vienos at­sa­ko­my­bės principas: klasė turėtų turėti vieną ir tik vieną priežastį keistis.
  • Atvirumo-uždarumo principas: Prog­ra­mi­nės įrangos elementai (klasės, moduliai, funkcijos ir pan.) turėtų būti atviri iš­plė­ti­mui, bet uždari mo­di­fi­ka­vi­mui.
  • Liskov pakeitimo principas: pa­kai­ti­nės klasės turėtų galėti paveldėti ir įgy­ven­din­ti visas vir­šu­ti­nės klasės metodus ir savybes.
  • Sąsajų atskyrimo principas: sąsajos neturėtų turėti daugiau metodų, nei reikia klasėms įgy­ven­din­ti.
  • Pri­klau­so­my­bės apgręžimo principas: klasės neturėtų pri­klau­sy­ti nuo kitų klasių, o nuo sąsajų arba abst­rak­čių klasių.

Kokios naudos teikia SOLID principai?

Kai nėra taisyklių, įsi­vy­rau­ja chaosas, ir tai ypač pastebima prog­ra­ma­vi­mo metu. Net nedidelės klaidos, ne­tiks­lu­mai ir spragos ilgainiui gali paversti gerą šaltinio kodą visiškai netinkamu naudoti, jei jų ne­pa­ša­li­na­ma. Kartais pakanka sudėtingų klasių, kurios apsunkina įgy­ven­di­ni­mą, arba paklasių, kurioms trūksta virš­kla­sių savybių. SOLID principai užtikrina, kad re­fak­to­rin­go metu tektų taisyti kuo mažiau kodo.

SOLID principai lemia kodo kokybę:

  • Aišku, tvarkinga ir patrauklu: prog­ra­mi­nė įranga ir kodai tampa lengviau su­pran­ta­mi, veiks­min­ges­ni ir tiesiog atrodo geriau.
  • Lengva pri­žiū­rė­ti: paprasta ir aiški struktūra leidžia keliems bend­ra­dar­biams lengviau pri­žiū­rė­ti ir valdyti tiek naują, tiek seną kodą.
  • Pri­tai­ko­ma, iš­plės­ti­na, pa­kar­to­ti­nai naudojama: Dėl geresnio su­pran­ta­mu­mo, sumažinto su­dė­tin­gu­mo ir at­sa­ko­my­bės bei su­ma­žin­tos pri­klau­so­my­bės nuo klasių, kodą galima geriau redaguoti, pri­tai­ky­ti ir išplėsti per sąsajas bei lanksčiai pa­kar­to­ti­nai naudoti.
  • Mažiau klaidų: švarus kodas su paprasta struktūra reiškia, kad vienos kodo dalies pa­kei­ti­mai netyčia nepaveiks kitų sričių ar funkcijų.
  • Saugus ir pa­ti­ki­mes­nis: pa­žei­džia­mu­mų, ne­su­de­ri­na­mu­mų ir klaidų su­ma­ži­ni­mas arba pa­ša­li­ni­mas pagerina sistemos funk­cio­na­lu­mą ir pa­ti­ki­mu­mą, o tai savo ruožtu pagerina saugumą.

Ką reiškia kiek­vie­nas iš SOLID principų?

SOLID principai yra vieni iš pag­rin­di­nių geros prog­ra­ma­vi­mo praktikos taisyklių ir turėtų būti žinomi kiek­vie­nam, kuris dirba ob­jek­ti­nio prog­ra­ma­vi­mo srityje. Toliau išsamiai pa­aiš­kin­si­me kiekvieną principą.

SRP: Vienos at­sa­ko­my­bės principas

Robertas C. Martinas pateikė pirminį šio principo api­brė­ži­mą knygoje „Agile Software De­velop­ment: Prin­ci­p­les, Patterns and Practices“; jis rašė:

Quote

„Kiek­vie­nas prog­ra­mi­nės įrangos modulis turėtų turėti vie­nin­te­lę priežastį, dėl kurios jį reikėtų keisti“.

Vienos at­sa­ko­my­bės principas (SRP) teigia, kad kiekviena klasė ob­jek­ti­nia­me prog­ra­ma­vi­me (OOP) turėtų turėti tik vieną at­sa­ko­my­bę. Tai reiškia, kad turėtų būti tik viena prie­žas­tis, dėl kurios klasę reikėtų keisti. Prie­šin­gai nei dažnai manoma, tai nereiškia, kad klasė ar modulis gali turėti tik vieną užduotį. Tai reiškia, kad ji turėtų būti atsakinga tik už konk­re­čias užduotis, kurios, idealiu atveju, ne­si­dub­liuo­tų su kitomis sritimis.

At­sa­ko­my­bių sutapimas, pa­vyz­džiui, kai funkcijos teikiamos įvairiems verslo seg­men­tams, gali turėti įtakos klasės funk­cio­na­lu­mui, jei viename segmente atliekami pa­kei­ti­mai. Dėl daugybės at­sa­ko­my­bių ir pri­klau­so­my­bių vie­nin­te­lis pa­kei­ti­mas vienoje srityje gali sukelti kodavimo klaidas arba pa­rei­ka­lau­ti papildomų pakeitimų.

Vienos at­sa­ko­my­bės principas (SRP) skirtas kurti nuo­sek­lius modulius, kurių užduotis – atlikti konk­re­čias, aiškiai api­brėž­tas funkcijas arba valdyti objektus. Dėl aiškios, struk­tū­ri­zuo­tos struk­tū­ros, kurioje yra kuo mažiau pri­klau­so­my­bių ir ne­pri­klau­so­mų įgy­ven­di­ni­mų, pa­kei­ti­mus ir ko­re­ga­vi­mus galima atlikti efek­ty­viau, greičiau ir sklan­džiau.

Note

Klasės, dar vadinamos objektų tipais, yra pag­rin­di­niai ob­jek­ti­nio prog­ra­ma­vi­mo (OOP) elementai. Jas galima laikyti objektų brė­ži­niais, api­brė­žian­čiais jų savybes, kad prog­ra­mi­nė­je įrangoje būtų galima atkurti realaus pasaulio objektus ir sąvokas. Klasės, dar vadinamos moduliais, dažnai lyginamos su failų tipais.

OCP: Atvirumo ir uždarumo principas

Remiantis Roberto C. Martino ir Bertrando Meyero knyga „Ob­jek­ti­nis prog­ra­mi­nės įrangos kūrimas“, OCP teigia:

Quote

„Prog­ra­mi­nės įrangos elementai (klasės, moduliai, funkcijos ir pan.) turėtų būti atviri plėtrai, bet uždari mo­di­fi­ka­vi­mui“.

OCP užtikrina, kad norint įgy­ven­din­ti pa­kei­ti­mus nereikės iš esmės perrašyti prog­ra­mi­nės įrangos. Jei rei­ka­lin­gi gi­lu­mi­niai kodo pa­kei­ti­mai, kyla pavojus, kad atsiras ne­pa­ste­bi­mų klaidų ir kodo trūkumų. Gerai struk­tū­ri­zuo­tas kodas turėtų turėti sąsajas, kurias galima naudoti siekiant jį išplėsti pa­pil­do­mo­mis funk­ci­jo­mis. Čia raktinis žodis yra klasių pa­vel­dė­ji­mas.

Naujas funkcijas ir iš­plė­ti­mus, kuriuose yra aiškios naujos funkcijos ir metodai, kuriuos reikia įgy­ven­din­ti, galima lengvai pridėti prie vir­šu­ti­nės klasės per sąsają, sukuriant pa­kai­ti­nes klases. Tokiu būdu nereikia keisti jau parašyto, stabilaus kodo. Tai su­pa­pras­ti­na prog­ra­mi­nės įrangos priežiūrą ir palaikymą bei žymiai padidina stabilių kodo elementų pa­kar­to­ti­nio naudojimo efek­ty­vu­mą per sąsajas.

LSP: Liskov pakeitimo principas

Remiantis Barbara H. Liskov ir Jeannette M. Wing straips­niu „Elgesio ti­pi­za­vi­mas naudojant in­va­rian­tus ir ap­ri­bo­ji­mus“, LSP teigia, kad:

Quote

„Tegul q(x) yra savybė, kurią galima įrodyti apie T tipo objektus x. Tuomet q(y) turėtų būti įmanoma įrodyti apie S tipo objektus y, kur S yra T potipis“.

Tai gali skambėti mįslingai, bet iš tikrųjų tai gana lengva suprasti: susietos arba išplėstos pa­kai­ti­nės klasės turi veikti taip pat, kaip ir jų vir­šu­ti­nės arba bazinės klasės. Tai reiškia, kad kiekviena pakaitinė klasė turi per pa­vel­dė­ji­mą išlaikyti ati­tin­ka­mos vir­šu­ti­nės klasės savybes, o šios savybės pa­kai­ti­nė­je klasėje negali būti keičiamos. Jos iš esmės turi būti pa­kei­čia­mos – iš čia ir kyla pakeitimo principas. Kita vertus, vir­šu­ti­nės klasės gali būti mo­di­fi­kuo­ja­mos.

Norėdami tai pa­aiš­kin­ti, pa­nag­ri­nė­ki­me klasikinį Roberto C. Martino pavyzdį apie sta­čia­kam­pius ir kvadratus. Geo­met­ri­jos pamokose iš­moks­ta­me tokį principą: kiek­vie­nas kvadratas yra sta­čia­kam­pis, bet ne kiek­vie­nas sta­čia­kam­pis yra kvadratas. Kvadratas ne tik turi sta­čia­kam­pius kampus, kaip ir sta­čia­kam­piai, bet ir visų jo kraštinių ilgis yra vienodas.

Prog­ra­ma­vi­mo srityje prielaida, kad panašios ar iš pažiūros iden­tiš­kos klasės yra su­si­ju­sios arba viena nuo kitos priklauso, veda prie klaidų, ne­su­si­pra­t­imų ir neaiškaus kodo. Dėl šios prie­žas­ties prog­ra­ma­vi­mo srityje klasė „Rectangle“ nėra kvadratas, o klasė „Square“ nėra sta­čia­kam­pis. Abi klasės yra atskirtos ir įgy­ven­di­na­mos atskirai. Nesant in­te­gruo­to ryšio tarp klasių, ne­su­si­pra­t­imai negali sukelti klaidų tarp klasių. Tai padidina saugumą ir stabilumą keičiant įgy­ven­di­ni­mus pa­klas­sė­se ar virš­kla­siuo­se be neigiamų pasekmių.

ISP: Sąsajų atskyrimo principas

Remiantis Roberto C. Martino knyga „Sąsajos atskyrimo principas“, ISP api­brė­žia­mas taip:

Quote

„Klientai neturėtų būti priversti naudotis sąsajomis, kurių jie nenaudoja“.

ISP teigia, kad var­to­to­jai neturėtų būti priversti naudoti jiems ne­rei­ka­lin­gų sąsajų. Kitaip tariant: siekiant suteikti klientams tam tikrų klasių funkcijas, pagal konk­re­čius rei­ka­la­vi­mus kuriamos naujos, mažesnės sąsajos. Tai neleidžia sąsajoms tapti pernelyg didelėmis ir užtikrina, kad tarp klasių ne­su­si­da­ry­tų stiprių pri­klau­so­my­bių. Pri­va­lu­mas yra tas, kad prog­ra­mi­nę įrangą, kurioje klasės yra atsietos viena nuo kitos ir kurioje yra keletas mažų, pagal konk­re­čius rei­ka­la­vi­mus pri­tai­ky­tų sąsajų, lengviau pri­žiū­rė­ti.

DIP: Pri­klau­so­my­bės apgręžimo principas

Pasak Roberto C. Martino, knygoje „Pri­klau­so­my­bės apgręžimo principas“ penktasis ir pas­ku­ti­nis iš SOLID principų yra toks:

Quote

„A. Aukšto lygio moduliai neturėtų pri­klau­sy­ti nuo žemo lygio modulių. Abu turėtų pri­klau­sy­ti nuo abst­rak­ci­jų. B. Abst­rak­ci­jos neturėtų pri­klau­sy­ti nuo detalių“.

DIP užtikrina, kad konk­re­čios funkcijos ir pri­klau­so­my­bės šaltinio kodo sluoks­niuo­se būtų grin­džia­mos abst­rak­čio­mis sąsajomis, o ne tie­sio­giai viena nuo kitos. Prog­ra­mi­nės įrangos ar­chi­tek­tū­ros paprastai su­skirs­to­mos į aukš­tes­nius vartotojo lygmenis ir žemesnius, abst­rak­čius lygmenis. Logiškai mąstant, galima manyti, kad abst­rak­tus pagrindas daro įtaką aukš­tes­nių sluoksnių veikimui. Tačiau DIP čia įžvelgia po­ten­cia­lią problemą, nes ji sukuria aukš­tes­nių lygmenų pri­klau­so­my­bę nuo žemesnių lygmenų, o tai gali sukelti sunkumų.

Vietoj to, kad aukš­tes­nie­ji lygiai būtų susieti su že­mes­niai­siais, aukš­tes­nio­jo ir že­mes­nio­jo lygių klasės turėtų pri­klau­sy­ti nuo abst­rak­čių, tarpinės grandies sąsajų. Šios sąsajos iš že­mes­nių­jų lygių gauna aukš­tes­nie­siems lygiams rei­ka­lin­gas funkcijas ir jas pateikia. Tokiu būdu galima išvengti „iš apačios į viršų“ pri­klau­so­my­bės hie­rar­chi­jos, kuri laikui bėgant gali sukelti klaidų kode. Tai pa­leng­vi­na modulių pa­kar­to­ti­nį naudojimą ir leidžia keisti že­mes­nio­jo lygio klases ne­pa­vei­kiant aukš­tes­nių­jų lygių.

Kas nutiks, jei nebus laikomasi SOLID principų?

Sukurti švarų, lengvai su­pran­ta­mą kodą, kuris pa­leng­vin­tų jo priežiūrą, turėtų būti pag­rin­di­nis prog­ra­mi­nės įrangos kūrimo tikslas. Jei prog­ra­muo­to­jai nepaiso esminių gairių, pa­vyz­džiui, SOLID principų, kodas gali smarkiai pablogėti dėl pa­žei­džia­mu­mų, dub­lia­vi­mo­si, su­si­kau­pu­sių klaidų ir pernelyg didelių pri­klau­so­my­bių. Kraš­tu­ti­niais atvejais kodas laikui bėgant gali tapti visiškai ne­nau­do­ja­mas. Tai yra didelė problema taikant lanksčią prog­ra­mi­nės įrangos kūrimo metodiką, kai su­dė­tin­gas kodavimo užduotis dažnai atlieka daug žmonių.

Ne­tvar­kin­go kodo ar ne­tin­ka­mos kodo prie­žiū­ros pasekmės yra šios:

  • Kodo „kvapas“: kai kodas rašomas ne­si­lai­kant reikiamų standartų, gali atsirasti va­di­na­ma­sis „kodo kvapas“ arba „smir­dan­tis kodas“, o tai gali sukelti funkcines klaidas ir programų ne­su­de­ri­na­mu­mą.
  • Kodo puvimas: Jei kodas nėra pri­žiū­ri­mas ar taisomas per re­fak­to­rin­gą ar brangią kodo peržiūrą, jis gali me­ta­fo­riš­kai „supūti“ ir visiškai prarasti savo funk­cio­na­lu­mą. Kitas terminas, api­bū­di­nan­tis ne­skai­to­mą, sudėtingą kodą, yra „spagečių kodas“.
  • Saugumo rizika: Kylančios problemos ne­ap­si­ri­bo­ja tik veiklos su­tri­ki­mais, sudėtinga priežiūra ir su­de­ri­na­mu­mo prob­le­mo­mis. Taip pat yra saugumo spragų, kurios suteikia ken­kė­jiš­kai prog­ra­mi­nei įrangai galimybių išnaudoti kodą, įskaitant „zero-day“ pa­žei­džia­mu­mus.

Kas sukūrė SOLID principus?

SOLID principų ištakos siekia keletą principų, kuriuos 2000 m. savo esė „Design Prin­ci­p­les and Design Patterns“ pirmą kartą pristatė Robertas C. Martinas („Dėdė Bobas“), vienas iš agilios prog­ra­ma­vi­mo ini­cia­to­rių. SOLID principus su­for­mu­la­vo Robertas C. Martinas, Ber­tran­das Meyeris ir Barbara Liskov. Įsi­min­ti­ną akronimą iš­po­pu­lia­ri­no Maiklas Featheris, kuris penkių pag­rin­di­nių principų pirmąsias raides išdėstė įsi­min­ti­na tvarka.

Kokie yra panašūs prog­ra­ma­vi­mo principai?

Prog­ra­mi­nės įrangos kūrimo srityje principai – tai bend­ro­sios arba labai konk­re­čios gairės ir re­ko­men­da­ci­jos, kaip elgtis. Be SOLID principų, kurie buvo sukurti ob­jek­ti­nio prog­ra­ma­vi­mo reikmėms, kiti švaraus kodo prog­ra­ma­vi­mo principai apima:

  • DRY principas (Don’t repeat yourself – „Nekartok savęs“) funk­ci­joms, tu­rin­čioms vie­nin­te­lį, unikalų atvaizdą
  • KISS principas (Keep it simple, stupid) – kuo pa­pras­tes­nis kodas
Go to Main Menu