SOLID-prin­cip­per­ne består af fem ret­nings­linjer for ren, ved­li­ge­hol­del­ses­ven­lig og fleksibel kode i ob­jekt­ba­se­ret pro­gram­me­ring. An­ven­del­se og over­hol­del­se af prin­cip­per­ne re­sul­te­rer i et let­for­stå­e­ligt software-design over lange ud­vik­lings­pe­ri­o­der. Med disse prin­cip­per kan man ikke kun skrive bedre kode, men også ved­li­ge­hol­de ek­si­ste­ren­de kode lettere.

Hvad er SOLID-prin­cip­per­ne, og hvem har udviklet dem?

God kildekode starter med regler, pro­gram­me­rings­pa­ra­dig­mer og en passende pro­gram­me­rings­stil for effektiv og ren kode. Det er netop det, de fem SOLID-prin­cip­per, der er opfundet af Robert C. Martin, Bertrand Meyer og Barbara Liskov, sikrer. Ved at følge disse prin­cip­per i ob­jekt­o­ri­en­te­ret pro­gram­me­ring (OOP) med sprog som Python eller Java skriver du ikke kun bedre kode, men sikrer også mere effektiv ko­de­ved­li­ge­hol­del­se, bæ­re­dyg­tigt og flek­si­belt software-design og større sikkerhed på lang sigt.

Navnet SOLID er re­præ­sen­ta­tivt for det solide pro­gram­me­rings­grund­lag, som alle, der ønsker at lære pro­gram­me­ring, bør have. Akronymet blev skabt af Michael Feathers, der tog de første bogstaver i hvert af de fem prin­cip­per for at skabe det:

  • Prin­cip­pet om en­kel­tansvar: En klasse bør have én og kun én grund til at ændre sig.
  • Åben-lukket-prin­cip­pet: Softwa­re­en­he­der (klasser, moduler, funk­tio­ner osv.) bør være åbne for udvidelse, men lukkede for ændringer.
  • Liskovs sub­sti­tu­tions­prin­cip: Un­der­klas­ser skal kunne arve og im­ple­men­te­re alle metoder og egen­ska­ber fra over­klas­sen.
  • Prin­cip­pet om græn­se­fla­de­se­gre­ge­ring: Græn­se­fla­der bør ikke indeholde flere metoder, end der er nød­ven­digt for at im­ple­men­te­re klasser.
  • Prin­cip­pet om af­hæn­gig­heds­in­ver­sion: Klasser bør ikke være afhængige af andre klasser, men af græn­se­fla­der eller abstrakte klasser.

Hvilke fordele giver SOLID-prin­cip­per­ne?

Hvor der ikke er regler, opstår der kaos, og dette bliver især mærkbart ved pro­gram­me­ring. Selv små fejl, unøj­ag­tig­he­der og mangler kan gøre god kildekode fuld­stæn­dig ubrugelig på lang sigt, hvis de ikke bliver “behandlet”. Nogle gange er det nok med komplekse klasser, der gør im­ple­men­te­rin­gen vanskelig, eller un­der­klas­ser, der mangler in­di­vi­du­el­le egen­ska­ber fra deres over­klas­ser. SOLID-prin­cip­per­ne sikrer, at så lidt kode som muligt skal repareres med re­fak­to­re­ring.

SOLID-prin­cip­per­ne skaber kode:

  • Tydelig, ren og attraktiv: Software og koder er lettere at forstå, mere effektive og ser sim­pelt­hen bedre ud.
  • Let at ved­li­ge­hol­de: Den enkle og klare struktur gør det lettere for flere sam­ar­bejds­part­ne­re at ved­li­ge­hol­de og ad­mi­ni­stre­re både ny kode og ældre kode.
  • Kan tilpasses, udvides og genbruges: Gennem forbedret læsbarhed, reduceret kom­plek­si­tet og ansvar samt mindre af­hæn­gig­hed af klasser kan koden bedre redigeres, tilpasses og udvides gennem græn­se­fla­der og genbruges flek­si­belt.
  • Mindre fejl­be­hæf­tet: Ren kode med en enkel struktur betyder, at ændringer i en del af koden ikke util­sig­tet påvirker andre områder eller funk­tio­ner.
  • Sikker og mere pålidelig: Reduktion eller eli­mi­ne­ring af sår­bar­he­der, ufor­e­ne­lig­he­der og fejl forbedrer et systems funk­tio­na­li­tet og på­li­de­lig­hed, hvilket igen forbedrer sik­ker­he­den.

Hvad betyder hvert af SOLID-prin­cip­per­ne?

SOLID-prin­cip­per­ne hører til de gyldne regler for god pro­gram­me­ring og bør være velkendte for alle, der arbejder med ob­jekt­ba­se­ret pro­gram­me­ring. Nedenfor forklarer vi hvert princip i detaljer.

SRP: Prin­cip­pet om enkelt ansvar

Robert C. Martin skabte den op­rin­de­li­ge de­fi­ni­tion for dette princip i ‘Agile Software De­ve­l­op­ment: Prin­cip­les, Patterns and Practices’, hvor han skrev:

Citat

“Hvert softwa­re­mo­dul bør have én og kun én grund til at ændre sig”.

Single Re­spon­si­bi­li­ty Principle (SRP) fastslår, at hver klasse i ob­jekt­o­ri­en­te­ret pro­gram­me­ring (OOP) kun skal have ét ansvar. Dette betyder, at der kun skal være én grund til at ændre en klasse. I mod­sæt­ning til al­min­de­li­ge for­tolk­nin­ger betyder dette ikke, at en klasse eller et modul kun kan have én opgave. Det betyder snarere, at den kun skal være ansvarlig for spe­ci­fik­ke opgaver, som ideelt set ikke over­lap­per med andre områder.

En over­lap­ning af an­svars­om­rå­der, såsom at tilbyde funk­tio­ner til for­skel­li­ge for­ret­nings­seg­men­ter, kan påvirke klassens funk­tio­na­li­tet, når der foretages ændringer i et segment. At have flere an­svars­om­rå­der og mange af­hæn­gig­he­der kan medføre, at en enkelt ændring i et område medfører kodefejl eller behov for yder­li­ge­re ændringer.

Single Re­spon­si­bi­li­ty Principle (SRP) er designet til at skabe sam­men­hæn­gen­de moduler med spe­ci­fik­ke, vel­de­fi­ne­re­de funk­tio­ner eller objekter. Takket være dets klare, struk­tu­re­re­de opsætning med minimale af­hæn­gig­he­der og uaf­hæn­gi­ge im­ple­men­te­rin­ger kan ændringer og ju­ste­rin­ger foretages mere effektivt, hurtigt og pro­blem­frit.

Note

Klaser, også kendt som ob­jekt­ty­per, er de centrale elementer i ob­jekt­o­ri­en­te­ret pro­gram­me­ring (OOP). De kan ses som blu­e­prints for objekter, der skitserer deres at­tri­but­ter, så det er muligt at genskabe virkelige objekter og koncepter i software. Klasser, også kendt som moduler, sam­men­lig­nes ofte med filtyper.

OCP: Åben-lukket-prin­cip­pet

Ifølge Robert C. Martin og Bertrand Meyer i ‘Object Oriented Software Con­struction’ lyder OCP således:

Citat

“Softwa­re­en­he­der (klasser, moduler, funk­tio­ner osv.) bør være åbne for udvidelse, men lukkede for ændringer”.

OCP sikrer, at du ikke behøver at omskrive softwa­rens kerne for at im­ple­men­te­re ændringer. Hvis der kræves dybt­gå­en­de ko­de­mo­di­fi­ka­tio­ner, er der risiko for subtile fejl og kodelugt. En vel­struk­tu­re­ret kode bør indeholde græn­se­fla­der, der kan bruges til at udvide den med yder­li­ge­re funk­tio­ner. Nøg­le­or­det her er klassearv.

Nye funk­tio­ner og ud­vi­del­ser med klare nye funk­tio­ner og metoder, der skal im­ple­men­te­res, kan nemt tilføjes til en su­per­klas­se via en græn­se­fla­de i form af un­der­klas­ser. På denne måde behøver du ikke at ændre den skrevne, stabile kode. Det forenkler ved­li­ge­hol­del­sen og op­da­te­rin­gen af software og forbedrer ef­fek­ti­vi­te­ten af genbrug af stabile ko­de­e­le­men­ter via græn­se­fla­der be­ty­de­ligt.

LSP: Liskovs sub­sti­tu­tions­prin­cip

Ifølge Barbara H. Liskov og Jeannette M. Wing i ‘Be­havi­o­ral Subtyping Using In­va­ri­ants and Con­straints’ fastslår LSP, at:

Citat

”Lad q(x) være en egenskab, der kan bevises for objekter x af typen T. Så bør q(y) kunne bevises for objekter y af typen S, hvor S er en undertype af T”.

Det lyder måske kryptisk, men det er faktisk ret nemt at forstå: Forbundne eller udvidede un­der­klas­ser skal fungere som deres over­klas­ser eller ba­se­klas­ser. Det betyder, at hver un­der­klas­se skal bevare egen­ska­ber­ne fra sin respek­ti­ve over­klas­se gennem arv, og disse egen­ska­ber må ikke ændres i un­der­klas­sen. De skal i prin­cip­pet kunne erstattes, deraf sub­sti­tu­tions­prin­cip­pet. Over­klas­ser kan derimod ændres.

For at forklare det, lad os se på det klassiske eksempel fra Robert C. Martin om rek­tang­ler og firkanter. I geo­me­tri­un­der­vis­nin­gen lærer vi følgende princip: alle firkanter er rek­tang­ler, men ikke alle rek­tang­ler er firkanter. En firkant har ikke kun retvink­le­de sider som rek­tang­ler, men alle dens sider er også lige lange.

I pro­gram­me­ring fører an­ta­gel­sen om, at lignende eller til­sy­ne­la­den­de identiske klasser er re­la­te­re­de eller afhængige af hinanden, til fejl, mis­for­stå­el­ser og uklar kode. Af denne grund er klassen ‘Rectangle’ i pro­gram­me­ring ikke en firkant, og klassen ‘Square’ er ikke et rektangel. Begge er adskilt og im­ple­men­te­ret separat. Uden en in­te­gre­ret for­bin­del­se mellem klasserne kan mis­for­stå­el­ser ikke føre til fejl på tværs af klasser. Dette øger sik­ker­he­den og sta­bi­li­te­ten, når man bytter im­ple­men­te­rin­ger i un­der­klas­ser eller over­klas­ser uden kon­se­kven­ser.

ISP: Prin­cip­pet om græn­se­fla­de­se­gre­ge­ring

Ifølge Robert C. Martin i “The Interface Se­gre­ga­tion Principle” defineres ISP som følger:

Citat

“Kunder bør ikke tvinges til at være afhængige af græn­se­fla­der, som de ikke bruger”.

ISP fastslår, at brugerne ikke bør være nødt til at bruge græn­se­fla­der, som de ikke har brug for. Med andre ord: For at kunne tilbyde kunderne funk­tio­ner i bestemte klasser skræd­der­sys nye, mindre græn­se­fla­der til spe­ci­fik­ke krav. Dette for­hin­drer, at græn­se­fla­der­ne bliver for store, og sikrer, at der ikke opstår stærke af­hæn­gig­he­der mellem klasserne. Fordelen er, at software med afkoblede klasser og flere små græn­se­fla­der, der er skræd­der­sy­et til spe­ci­fik­ke krav, er nemmere at ved­li­ge­hol­de.

DIP: Af­hæn­gig­heds­in­ver­sions­prin­cip­pet

Ifølge Robert C. Martin i ‘The De­pen­den­cy Inversion Principle’ er det femte og sidste af SOLID-prin­cip­per­ne som følger:

Citat

”A. Moduler på højt niveau bør ikke være afhængige af moduler på lavt niveau. Begge bør være afhængige af ab­strak­tio­ner. B. Ab­strak­tio­ner bør ikke være afhængige af detaljer”.

DIP sikrer, at spe­ci­fik­ke funk­tio­na­li­te­ter og af­hæn­gig­he­der inden for kil­de­ko­dela­ge­ne er baseret på abstrakte græn­se­fla­der og ikke direkte på hinanden. Softwa­rear­ki­tek­tu­rer er typisk or­ga­ni­se­ret i højere bru­ger­ni­veau­er og lavere, mere abstrakte niveauer. Logisk set kunne man tro, at det abstrakte fundament påvirker de øverste lag. DIP iden­ti­fi­ce­rer imid­ler­tid et po­ten­ti­elt problem her, da det skaber af­hæn­gig­he­der for de højere niveauer på de lavere niveauer, hvilket kan føre til problemer.

I stedet for at forbinde højere niveauer med lavere niveauer bør klasser på høje og lave niveauer afhænge af abstrakte, mel­lem­lig­gen­de græn­se­fla­der. Græn­se­fla­der­ne henter funk­tio­na­li­te­ter, der er nød­ven­di­ge på højere niveauer, fra lavere niveauer og gør dem til­gæn­ge­li­ge. På denne måde kan man undgå en bottom-up-hierarki af af­hæn­gig­he­der, som med tiden kan føre til fejl i koden. Dette letter gen­brug­bar­he­den af moduler og gør det muligt at foretage ændringer i lavere klasser uden at påvirke højere niveauer.

Hvad sker der, hvis SOLID-prin­cip­per­ne ikke over­hol­des?

At skabe ren, læsbar kode, der forenkler ved­li­ge­hol­del­sen, bør være et primært mål i softwa­re­ud­vik­lin­gen. Hvis udviklere overser vigtige ret­nings­linjer som SOLID-prin­cip­per­ne, kan koden blive alvorligt forringet på grund af sår­bar­he­der, re­dun­dan­ser, ak­ku­mu­le­re­de fejl og over­drev­ne af­hæn­gig­he­der. I ekstreme tilfælde kan koden blive ubrugelig med tiden. Dette er et væ­sent­ligt problem i agil softwa­re­ud­vik­ling, hvor mange mennesker ofte arbejder med komplekse kod­nings­op­ga­ver.

Kon­se­kven­ser­ne af uren kode eller dårlig ved­li­ge­hol­del­se af kode omfatter:

  • Kodestank: Når kode ikke er skrevet i over­ens­stem­mel­se med de nød­ven­di­ge stan­dar­der, kan dette forårsage kodestank eller ‘stinkende kode’, hvilket kan føre til funk­tions­fejl og in­kom­pa­tib­le pro­gram­mer.
  • Ko­de­ned­bryd­ning: Hvis koden ikke ved­li­ge­hol­des eller repareres ved hjælp af re­fak­to­re­ring eller en kostbar ko­de­gen­nem­gang, kan den bil­led­ligt talt ‘nedbrydes’ og miste sin funk­tio­na­li­tet fuld­stæn­digt. Et andet udtryk for ulæselig, indviklet kode er spa­ghet­ti­ko­de.
  • Sik­ker­heds­ri­si­ci: De problemer, der opstår, er ikke begrænset til nedbrud, kompleks ved­li­ge­hol­del­se og kom­pa­ti­bi­li­tets­pro­ble­mer. Der er også sik­ker­heds­hul­ler, der giver malware mulighed for at udnytte koden, herunder zero-day-exploits.

Hvem udviklede SOLID-prin­cip­per­ne?

SOLID-prin­cip­per­ne stammer fra en række prin­cip­per, der først blev in­tro­du­ce­ret af Robert C. Martin (“Uncle Bob”), en af ini­ti­a­tiv­ta­ger­ne til agil pro­gram­me­ring, i 2000 i hans essay med titlen “Design Prin­cip­les and Design Patterns”. SOLID-prin­cip­per­ne blev opfundet af Robert C. Martin, Bertrand Meyer og Barbara Liskov. Det fængende akronym blev populært af Michael Feathers, der om­ar­ran­ge­re­de de første bogstaver i de fem væ­sent­li­ge prin­cip­per i en let huskbar ræk­ke­føl­ge.

Hvilke lignende pro­gram­me­rings­prin­cip­per findes der?

I softwa­re­ud­vik­ling er prin­cip­per generelle eller meget spe­ci­fik­ke ret­nings­linjer og an­be­fa­lin­ger til handling. Ud over SOLID-prin­cip­per­ne, som blev udviklet til ob­jekt­o­ri­en­te­ret pro­gram­me­ring, omfatter andre pro­gram­me­rings­prin­cip­per for ren kode:

  • DRY-prin­cip­pet (Don’t repeat yourself) for funk­tio­ner med en enkelt, unik re­præ­sen­ta­tion
  • KISS-prin­cip­pet (Keep it simple, stupid) for kode, der er kon­stru­e­ret så enkelt som muligt
Gå til ho­ved­me­nu­en