SOLID-principerna består av fem riktlinjer för ren, underhållbar och flexibel kod i objektbaserad programmering. Genom att tillämpa och följa principerna får man en lättförståelig programvarudesign under långa utvecklingsperioder. Med dessa principer kan man inte bara skriva bättre kod, utan också underhålla befintlig kod på ett enklare sätt.

Vad är SOLID-principerna och vem har utvecklat dem?

Bra källkod börjar med regler, programmeringsparadigmer och en lämplig programmeringsstil för effektiv och ren kod. Det är precis vad de fem SOLID-principerna, myntade av Robert C. Martin, Bertrand Meyer och Barbara Liskov, säkerställer. Genom att följa dessa principer i objektorienterad programmering (OOP) med språk som Python eller Java skriver du inte bara bättre kod, utan säkerställer också effektivare kodunderhåll, hållbar och flexibel programvarudesign och större säkerhet på lång sikt.

Namnet SOLID representerar den solida programmeringsgrund som alla som vill lära sig programmering bör ha. Akronymen skapades av Michael Feathers, som tog de första bokstäverna i var och en av de fem principerna för att skapa den:

  • Enkel ansvarsprincip: En klass ska ha en, och endast en, anledning att ändras.
  • Öppen-stängd-principen: Programvaruenheter (klasser, moduler, funktioner etc.) bör vara öppna för utökning, men stängda för modifiering.
  • Liskovs substitutionsprincip: Underklasser bör kunna ärva och implementera alla metoder och egenskaper från överklassen.
  • Principen om gränssnittssegregation: Gränssnitt bör inte innehålla fler metoder än vad som krävs för att implementera klasser.
  • Principen om beroendeinversion: Klasser bör inte vara beroende av andra klasser, utan av gränssnitt eller abstrakta klasser.

Vilka fördelar erbjuder SOLID-principerna?

Om det inte finns några regler uppstår kaos, och detta blir särskilt märkbart vid programmering. Även små fel, felaktigheter och luckor kan göra bra källkod helt oanvändbar på lång sikt om de lämnas “obehandlade”. Ibland räcker det med komplexa klasser som gör implementeringen svår eller underklasser som saknar enskilda egenskaper hos sina överklasser. SOLID-principerna säkerställer att så lite kod som möjligt behöver repareras med refactoring.

SOLID-principerna skapar kod:

  • Tydligt, rent och attraktivt: Programvara och koder är lättare att förstå, mer effektiva och ser helt enkelt bättre ut.
  • Lätt att underhålla: Den enkla och tydliga strukturen gör det enklare för flera medarbetare att underhålla och hantera både ny kod och äldre kod.
  • Anpassningsbar, utbyggbar, återanvändbar: Genom förbättrad läsbarhet, minskad komplexitet och ansvar samt minskat beroende av klasser kan koden redigeras, anpassas och utökas bättre via gränssnitt och återanvändas på ett flexibelt sätt.
  • Mindre felbenägen: Ren kod med en enkel struktur innebär att ändringar i en del av koden inte av misstag påverkar andra områden eller funktioner.
  • Säker och mer tillförlitlig: Att minska eller eliminera sårbarheter, inkompatibiliteter och fel förbättrar systemets funktionalitet och tillförlitlighet, vilket i sin tur förbättrar säkerheten.

Vad betyder var och en av SOLID-principerna?

SOLID-principerna tillhör de gyllene reglerna för god programmering och bör vara bekanta för alla som arbetar med objektbaserad programmering. Nedan förklarar vi varje princip i detalj.

SRP: Principen om en enda ansvarighet

Robert C. Martin skapade den ursprungliga definitionen för denna princip i ”Agile Software Development: Principles, Patterns and Practices” och skrev:

Citatum

”Varje programvarumodul bör ha en och endast en anledning att ändras”.

Principen om enstaka ansvar (SRP) innebär att varje klass i objektorienterad programmering (OOP) endast ska ha ett enda ansvar. Detta innebär att det endast ska finnas ett enda skäl att modifiera en klass. I motsats till vad många tror innebär detta inte att en klass eller modul endast kan ha exakt en uppgift. Det innebär snarare att den endast ska ansvara för specifika uppgifter som helst inte överlappar andra områden.

En överlappning av ansvarsområden, såsom att erbjuda funktioner för olika affärssegment, kan påverka klassens funktionalitet när ändringar görs i ett segment. Att ha flera ansvarsområden och många beroenden kan leda till att en enda ändring i ett område orsakar kodfel eller behov av ytterligare ändringar.

Principen om enstaka ansvar (SRP) är utformad för att skapa sammanhängande moduler med specifika, väldefinierade funktioner eller objekt. Tack vare dess tydliga, strukturerade uppbyggnad med minimala beroenden och oberoende implementationer kan modifieringar och justeringar göras mer effektivt, snabbt och smidigt.

Notis

Klasser, även kända som objekttyper, är de centrala elementen i objektorienterad programmering (OOP). De kan ses som ritningar för objekt, som beskriver deras egenskaper så att det är möjligt att återskapa verkliga objekt och begrepp i programvara. Klasser, även kända som moduler, jämförs ofta med filtyper.

OCP: Öppen-stängd princip

Enligt Robert C. Martin och Bertrand Meyer i ”Object Oriented Software Construction” lyder OCP:

Citatum

”Programvaruenheter (klasser, moduler, funktioner etc.) bör vara öppna för utökning, men stängda för modifiering”.

OCP säkerställer att du inte behöver skriva om kärnan i programvaran för att implementera ändringar. Om djupgående kodändringar krävs finns det en risk för subtila fel och kodfel. En välstrukturerad kod bör tillhandahålla gränssnitt som kan användas för att utöka den med ytterligare funktioner. Nyckelordet här är klassarv.

Nya funktioner och tillägg med tydliga nya funktioner och metoder som behöver implementeras kan enkelt läggas till en superklass via ett gränssnitt i form av underklasser. På så sätt behöver du inte ändra den skrivna, stabila koden. Det förenklar underhållet och skötseln av programvaran och förbättrar avsevärt effektiviteten i återanvändningen av stabila kodelement via gränssnitt.

LSP: Liskovs substitutionsprincip

Enligt Barbara H. Liskov och Jeannette M. Wing i ”Behavioral Subtyping Using Invariants and Constraints” anger LSP att:

Citatum

”Låt q(x) vara en egenskap som kan bevisas om objekt x av typ T. Då bör q(y) kunna bevisas för objekt y av typ S, där S är en undertyp av T”.

Det kan låta kryptiskt, men det är faktiskt ganska lätt att förstå: Länkade eller utökade underklasser måste fungera som sina överklasser eller basklasser. Detta innebär att varje underklass måste behålla egenskaperna hos sin respektive överklass genom arv och att dessa egenskaper inte får ändras i underklassen. De måste i princip vara utbytbara, därav substitutionsprincipen. Överklasser, å andra sidan, får modifieras.

För att förklara detta kan vi titta på det klassiska exemplet från Robert C. Martin om rektanglar och kvadrater. I geometrilektionerna lär vi oss följande princip: varje kvadrat är en rektangel, men inte varje rektangel är en kvadrat. En kvadrat har inte bara rätvinkliga sidor som rektanglar, utan alla dess sidor är också lika långa.

I programmering leder antagandet att liknande eller till synes identiska klasser är relaterade eller beroende av varandra till fel, missförstånd och otydlig kod. Av denna anledning är klassen “Rektangel” inte en kvadrat och klassen “Kvadrat” inte en rektangel i programmering. Båda är frikopplade och implementeras separat. Utan en integrerad koppling mellan klasserna kan missförstånd inte leda till fel mellan klasserna. Detta förbättrar säkerheten och stabiliteten när man byter implementationer i underklasser eller överklasser, utan konsekvenser.

ISP: Principen om gränssnittssegregering

Enligt Robert C. Martin i ”The Interface Segregation Principle” definieras ISP på följande sätt:

Citatum

”Kunderna ska inte tvingas att vara beroende av gränssnitt som de inte använder”.

ISP anger att användare inte ska behöva använda gränssnitt som de inte behöver. Med andra ord: För att kunna erbjuda kunderna funktioner i vissa klasser skräddarsys nya, mindre gränssnitt efter specifika krav. Detta förhindrar att gränssnitten blir för stora och säkerställer att det inte uppstår starka beroenden mellan klasserna. Fördelen är att programvara med avkopplade klasser och flera små gränssnitt som är skräddarsydda efter specifika krav är lättare att underhålla.

DIP: Principen om beroendeinversion

Enligt Robert C. Martin i “The Dependency Inversion Principle” är den femte och sista av SOLID-principerna följande:

Citatum

”A. Moduler på hög nivå bör inte vara beroende av moduler på låg nivå. Båda bör vara beroende av abstraktioner. B. Abstraktioner bör inte vara beroende av detaljer”.

DIP säkerställer att specifika funktioner och beroenden inom källkodslager är beroende av abstrakta gränssnitt, inte direkt av varandra. Programvaruarkitekturer är vanligtvis organiserade i högre användarnivåer och lägre, mer abstrakta nivåer. Logiskt sett kan man tro att den abstrakta grunden påverkar beteendet hos de övre lagren. DIP identifierar dock ett potentiellt problem här, eftersom det skapar beroenden för de högre nivåerna på de lägre nivåerna, vilket kan leda till problem.

Istället för att koppla högre nivåer till lägre nivåer bör klasser på höga och låga nivåer vara beroende av abstrakta, mellanliggande gränssnitt. Gränssnitten hämtar funktioner som krävs på högre nivåer från lägre nivåer och gör dem tillgängliga. På så sätt kan man undvika en bottom-up-hierarki av beroenden, som med tiden kan leda till fel i koden. Detta underlättar återanvändningen av moduler och möjliggör ändringar i lägre klasser utan att det påverkar högre nivåer.

Vad händer om SOLID-principerna inte följs?

Att skapa ren, läsbar kod som förenklar underhållet bör vara ett primärt mål inom mjukvaruutveckling. Om utvecklare förbiser viktiga riktlinjer som SOLID-principerna kan koden försämras avsevärt på grund av sårbarheter, redundanser, ackumulerade fel och överdrivna beroenden. I extrema fall kan koden bli oanvändbar med tiden. Detta är ett betydande problem inom agil mjukvaruutveckling, där många personer ofta arbetar med komplexa kodningsuppgifter.

Konsekvenserna av oren kod eller dålig kodunderhåll inkluderar:

  • Kodlukt: När kod inte skrivs i enlighet med nödvändiga standarder kan detta orsaka kodlukt eller ”luktande kod”, vilket leder till funktionsfel och inkompatibla program.
  • Kodförfall: Om koden inte underhålls eller repareras genom refaktorisering eller en kostsam kodgranskning kan den bildligt talat ”förfalla” och helt förlora sin funktionalitet. Ett annat uttryck för oläslig, invecklad kod är spagettikod.
  • Säkerhetsrisker: De problem som uppstår är inte begränsade till avbrott, komplex underhåll och kompatibilitetsproblem. Det finns också säkerhetsluckor som ger skadlig programvara möjligheter att utnyttja koden, inklusive zero-day-exploits.

Vem utvecklade SOLID-principerna?

SOLID-principerna har sitt ursprung i flera principer som först introducerades av Robert C. Martin (”Uncle Bob”), en av initiativtagarna till agil programmering, år 2000 i hans essä med titeln ”Design Principles and Design Patterns”. SOLID-principerna myntades av Robert C. Martin, Bertrand Meyer och Barbara Liskov. Den fängslande akronymen populariserades av Michael Feathers, som ordnade om de fem grundläggande principernas initialer i en minnesvärd ordning.

Vilka liknande programmeringsprinciper finns det?

Inom mjukvaruutveckling är principer allmänna eller mycket specifika riktlinjer och rekommendationer för åtgärder. Förutom SOLID-principerna, som utvecklades för objektorienterad programmering, finns även andra programmeringsprinciper för ren kod, bland annat:

  • DRY-principen (Don’t repeat yourself) för funktioner med en enda, unik representation
  • KISS-principen (Keep it simple, stupid) för kod som är konstruerad så enkelt som möjligt
Gå till huvudmeny