SOLID-prinsippene består av fem retningslinjer for ren, vedlikeholdbar og fleksibel kode innen objektorientert programmering. Ved å anvende og følge disse prinsippene oppnås et programvaredesign som er lett å forstå, selv over lengre utviklingsperioder. Med disse prinsippene kan man ikke bare skrive bedre kode, men også vedlikeholde eksisterende kode på en enklere måte.

Hva er SOLID-prinsippene, og hvem utviklet dem?

God kildekode bygger på regler, programmeringsparadigmer og en passende programmeringsstil som sikrer effektiv og ren kode. Dette er nettopp hva de fem SOLID-prinsippene, utviklet av Robert C. Martin, Bertrand Meyer og Barbara Liskov, sikrer. Ved å følge disse prinsippene i objektorientert programmering (OOP) med språk som Python eller Java, skriver du ikke bare bedre kode, men sikrer også mer effektiv vedlikehold av koden, bærekraftig og fleksibel programvaredesign og større sikkerhet på lang sikt.

Navnet SOLID står for det solide grunnlaget i programmering som alle som ønsker å lære seg å programmere bør ha. Forkortelsen ble oppfunnet av Michael Feathers, som tok de første bokstavene i hvert av de fem prinsippene for å danne den:

  • Prinsippet om én ansvarsområde: En klasse bør ha én, og bare én, grunn til å endres.
  • Åpen-lukket-prinsippet: Programvareenheter (klasser, moduler, funksjoner osv.) bør være åpne for utvidelse, men lukkede for endring.
  • Liskovs substitusjonsprinsipp: Underklasser bør kunne arve og implementere alle metoder og egenskaper fra overklassen.
  • Prinsippet om grensesnittsegregering: Grensesnitt bør ikke inneholde flere metoder enn det som er nødvendig for å implementere klasser.
  • Prinsippet om avhengighetsinversjon: Klasser bør ikke være avhengige av andre klasser, men av grensesnitt eller abstrakte klasser.

Hvilke fordeler gir SOLID-prinsippene?

Der det ikke finnes regler, oppstår kaos, og dette blir særlig tydelig når man programmerer. Selv små feil, unøyaktigheter og mangler kan gjøre god kildekode fullstendig ubrukelig på sikt hvis de ikke blir «rettet opp». Noen ganger er det nok med komplekse klasser som gjør implementeringen vanskelig, eller underklasser som mangler enkelte egenskaper fra overklassene sine. SOLID-prinsippene sikrer at så lite kode som mulig må rettes opp gjennom refaktorisering.

SOLID-prinsippene danner grunnlaget for koden:

  • Oversiktlig, ryddig og tiltalende: Programvare og koder blir lettere å forstå, mer effektive og ser rett og slett bedre ut.
  • Enkel å vedlikeholde: Den enkle og oversiktlige strukturen gjør det enklere for flere samarbeidspartnere å vedlikeholde og administrere både ny kode og eldre kode.
  • Tilpassbar, utvidbar, gjenbrukbar: Gjennom forbedret lesbarhet, redusert kompleksitet og ansvar, samt redusert avhengighet av klasser, kan koden redigeres, tilpasses og utvides bedre gjennom grensesnitt, og gjenbrukes fleksibelt.
  • Mindre feilutsatt: Ren kode med en enkel struktur betyr at endringer i én del av koden ikke ved et uhell påvirker andre områder eller funksjoner.
  • Sikker og mer pålitelig: Å redusere eller eliminere sårbarheter, inkompatibiliteter og feil forbedrer systemets funksjonalitet og pålitelighet, noe som igjen forbedrer sikkerheten.

Hva betyr hvert av SOLID-prinsippene?

SOLID-prinsippene er blant de gyldne reglene for god programmering og bør være kjent for alle som arbeider med objektorientert programmering. Nedenfor forklarer vi hvert prinsipp i detalj.

SRP: Prinsippet om enkeltansvar

Robert C. Martin formulerte den opprinnelige definisjonen av dette prinsippet i «Agile Software Development: Principles, Patterns and Practices», hvor han skrev:

Quote

«Hver programvaremodul bør ha én og bare én grunn til å endres».

Prinsippet om én ansvarsområde (SRP) fastslår at hver klasse i objektorientert programmering (OOP) kun skal ha ett ansvarsområde. Dette innebærer at det kun bør være én grunn til å endre en klasse. I motsetning til vanlige tolkninger betyr dette ikke at en klasse eller modul kun kan ha nøyaktig én oppgave. Det betyr snarere at den kun skal være ansvarlig for bestemte oppgaver som ideelt sett ikke overlapper med andre områder.

En overlapping av ansvarsområder, for eksempel når funksjoner tilbys for ulike forretningssegmenter, kan påvirke klassens funksjonalitet når det gjøres endringer i ett segment. Når en klasse har flere ansvarsområder og mange avhengigheter, kan en enkelt endring på ett område føre til kodefeil eller behov for ytterligere endringer.

Prinsippet om enkeltansvar (SRP) er utviklet for å skape sammenhengende moduler som har spesifikke, veldefinerte funksjoner eller objekter som oppgave. Takket være den klare, strukturerte oppbygningen med minimale avhengigheter og uavhengige implementeringer, kan endringer og justeringer gjennomføres mer effektivt, raskt og smidig.

Note

Klasser, også kjent som objekttyper, er de sentrale elementene i objektorientert programmering (OOP). De kan betraktes som maler for objekter, som beskriver deres egenskaper slik at det blir mulig å gjenskape objekter og begreper fra den virkelige verden i programvare. Klasser, også kjent som moduler, sammenlignes ofte med filtyper.

OCP: Åpen-lukket-prinsippet

Ifølge Robert C. Martin og Bertrand Meyer i «Object Oriented Software Construction» lyder OCP som følger:

Quote

«Programvareenheter (klasser, moduler, funksjoner osv.) bør være åpne for utvidelse, men lukkede for endring».

OCP sikrer at du ikke trenger å omskrive selve kjernen i programvaren for å implementere endringer. Hvis det kreves omfattende endringer i koden, er det fare for skjulte feil og «code smells». En velstrukturert kode bør inneholde grensesnitt som kan brukes til å utvide den med flere funksjoner. Nøkkelordet her er klassearving.

Nye funksjoner og utvidelser med tydelige nye funksjoner og metoder som må implementeres, kan enkelt legges til en overklasse via et grensesnitt i form av underklasser. På denne måten slipper man å endre på den eksisterende, stabile koden. Dette forenkler vedlikeholdet av programvaren og forbedrer effektiviteten ved gjenbruk av stabile kodeelementer via grensesnitt betydelig.

LSP: Liskovs substitusjonsprinsipp

Ifølge Barbara H. Liskov og Jeannette M. Wing i «Behavioral Subtyping Using Invariants and Constraints» fastslår LSP at:

Quote

«La q(x) være en egenskap som kan bevises for objekter x av typen T. Da bør q(y) kunne bevises for objekter y av typen S, der S er en undertype av T».

Det kan høres kryptisk ut, men det er faktisk ganske enkelt å forstå: Koblede eller utvidede underklasser må fungere på samme måte som sine overklasser eller baseklasser. Dette betyr at hver underklasse må beholde egenskapene til sin respektive overklasse gjennom arv, og at disse egenskapene ikke må endres i underklassen. De må i prinsippet kunne erstattes, derav substitusjonsprinsippet. Overklasser kan derimot endres.

For å forklare dette, la oss se på det klassiske eksemplet fra Robert C. Martin om rektangler og kvadrater. I geometritimene lærer vi følgende prinsipp: Ethvert kvadrat er et rektangel, men ikke ethvert rektangel er et kvadrat. Et kvadrat har ikke bare rettvinklede sider, slik rektangler har, men alle sidene er også like lange.

I programmering fører det til feil, misforståelser og uklar kode å anta at lignende eller tilsynelatende identiske klasser er relatert til eller avhengige av hverandre. Av denne grunn er klassen «Rectangle» ikke et kvadrat, og klassen «Square» er ikke et rektangel. Begge er adskilt og implementert separat. Uten en integrert forbindelse mellom klassene kan misforståelser ikke føre til feil på tvers av klassene. Dette forbedrer sikkerheten og stabiliteten når man bytter implementeringer i underklasser eller overklasser, uten konsekvenser.

ISP: Prinsippet om grensesnittsegregering

Ifølge Robert C. Martin i «The Interface Segregation Principle» defineres ISP som følger:

Quote

«Kunder bør ikke bli tvunget til å være avhengige av grensesnitt de ikke bruker».

ISP-prinsippet slår fast at brukere ikke bør måtte bruke grensesnitt de ikke trenger. Med andre ord: For å gi klienter tilgang til funksjonene i bestemte klasser, utformes nye, mindre grensesnitt som er tilpasset spesifikke behov. Dette hindrer at grensesnittene blir for store og sikrer at det ikke oppstår sterke avhengigheter mellom klassene. Fordelen er at programvare med avkoblede klasser og flere små grensesnitt tilpasset spesifikke behov er enklere å vedlikeholde.

DIP: Prinsippet om avhengighetsinversjon

Ifølge Robert C. Martin lyder «prinsippet om avhengighetsinversjon», det femte og siste av SOLID-prinsippene, som følger:

Quote

«A. Moduler på høyt nivå bør ikke være avhengige av moduler på lavt nivå. Begge bør være avhengige av abstraksjoner. B. Abstraksjoner bør ikke være avhengige av detaljer.»

DIP sikrer at bestemte funksjoner og avhengigheter i kildekodelagene er avhengige av abstrakte grensesnitt, ikke direkte av hverandre. Programvarearkitekturer er vanligvis organisert i høyere brukernivåer og lavere, mer abstrakte nivåer. Logisk sett kunne man tro at det abstrakte fundamentet påvirker oppførselen til de øvre lagene. DIP påpeker imidlertid et potensielt problem her, da det skaper avhengigheter mellom de øvre og de nedre nivåene, noe som kan føre til problemer.

I stedet for å koble høyere nivåer til lavere nivåer, bør klasser på høye og lave nivåer være avhengige av abstrakte, mellomliggende grensesnitt. Grensesnittene henter funksjonaliteter som kreves på høyere nivåer fra lavere nivåer og gjør dem tilgjengelige. På denne måten kan man unngå en hierarki av avhengigheter som bygger seg opp nedenfra og opp, noe som over tid kan føre til feil i koden. Dette letter gjenbruk av moduler og gjør det mulig å endre klasser på lavere nivåer uten at det påvirker høyere nivåer.

Hva skjer hvis SOLID-prinsippene ikke følges?

Å lage ren og lesbar kode som forenkler vedlikeholdet, bør være et hovedmål i programvareutvikling. Hvis utviklere overser viktige retningslinjer som SOLID-prinsippene, kan koden forringes betydelig på grunn av sårbarheter, overflødig kode, akkumulerte feil og for mange avhengigheter. I ekstreme tilfeller kan koden bli ubrukelig etter hvert som tiden går. Dette er et betydelig problem i agil programvareutvikling, hvor mange ofte arbeider med komplekse programmeringsoppgaver.

Konsekvensene av dårlig kode eller mangelfull vedlikehold av koden omfatter:

  • Kodelukt: Når koden ikke er skrevet i samsvar med de nødvendige standardene, kan dette føre til «kodelukt» eller «stinkende kode», noe som igjen kan føre til funksjonsfeil og inkompatible programmer.
  • Kodeforfall: Hvis koden ikke vedlikeholdes eller repareres gjennom refaktorisering eller en kostbar kodegjennomgang, kan den figurativt «råtne» og miste all funksjonalitet. Et annet begrep for ulæselig, innfløkt kode er spaghettikode.
  • Sikkerhetsrisikoer: Problemene som oppstår er ikke begrenset til driftsavbrudd, komplisert vedlikehold og kompatibilitetsproblemer. Det finnes også sikkerhetshull som gir skadelig programvare muligheter til å utnytte koden, inkludert zero-day-angrep.

Hvem utviklet SOLID-prinsippene?

Opprinnelsen til SOLID-prinsippene ligger i flere prinsipper som først ble introdusert av Robert C. Martin («Uncle Bob»), en av initiativtakerne til agil programmering, i år 2000 i hans essay med tittelen «Design Principles and Design Patterns». SOLID-prinsippene ble myntet av Robert C. Martin, Bertrand Meyer og Barbara Liskov. Det fengende akronymet ble popularisert av Michael Feathers, som omorganiserte begynnelsesbokstavene i de fem grunnleggende prinsippene til en minneverdig rekkefølge.

Hvilke lignende programmeringsprinsipper finnes det?

I programvareutvikling er prinsipper generelle eller svært spesifikke retningslinjer og anbefalinger for hvordan man bør gå frem. I tillegg til SOLID-prinsippene, som ble utviklet for objektorientert programmering, omfatter andre programmeringsprinsipper for ren kode:

  • DRY-prinsippet (Don’t repeat yourself) for funksjoner med én enkelt, unik representasjon
  • KISS-prinsippet (Keep it simple, stupid) for kode som er konstruert så enkelt som mulig
Go to Main Menu