• Like
  • Save
En introduktion till SOLID-principerna
Upcoming SlideShare
Loading in...5
×
 

En introduktion till SOLID-principerna

on

  • 3,263 views

An introduction to the SOLID principles in Swedish that I gave at the EPiServer developers meetup in june 2010. You probably need to read the comments to understand some of the slides.

An introduction to the SOLID principles in Swedish that I gave at the EPiServer developers meetup in june 2010. You probably need to read the comments to understand some of the slides.

Statistics

Views

Total Views
3,263
Views on SlideShare
2,393
Embed Views
870

Actions

Likes
1
Downloads
22
Comments
0

7 Embeds 870

http://joelabrahamsson.com 854
http://www.valtechlabs.se 8
https://www.linkedin.com 3
http://www.linkedin.com 2
http://static.slidesharecdn.com 1
http://localhost 1
http://abrasoft.episerverhosting.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • Sommaren 2008 var jag och min fru på semester i Egypten. Det var en tvåveckorssemester där vi spenderade en vecka med att kryssa på nilen och en vecka åt sol och bad i Hurghada. En nilenkryssning kanske låter som någonting väldigt avslappnande, iaf om man fokuserar på ordet kryssning. Det kan jag garantera att det inte är! Vi spenderade 14 timmar per dag åt att titta på olika 4000 år gamla tempel och gravar i 40 gradig hetta. Väl i Hurghada kunde vi dock ta det lugnt. Jag har dock ganska svårt att bara ligga på en solstol och inte göra någonting alls så jag hade sett till att ha med mig en bok. Vid den här tidpunkten var jag en hyfsad programmerare som hade hunnit bekanta mig en del med såväl grundläggande datalogi som Java och .NET. Men jag hade på känn att det fanns något mer under ytan och två nyckelord för det verkade vara ”agilt” och ”patterns”. Därför hade jag innan resan begett mig till Adlibris för att beställa en bok.
  • Det slutade med att jag köpte den här boken, Agile Principles, Patterns and Practices in C#. Den innehöll ju trots allt både ordet ”agile” och ordet ”patterns” i titeln så den kunde ju omöjligen vara fel.Jag började läsa boken när vi kom fram till Hurghada och det slutade med att jag läste den från pärm till pärm under den veckan. Med tanke på att den är 700 sidor så blev det inte särskilt mycket badande.Jag hade ju köpt boken med ambitionen att lära mig mera om mitt yrke utöver det rena kodknackandet och den levererade verkligen. I själva verket kom den att ha en väldigt stor påverkan på mig. Dock på ett lite annorlunda sätt än jag hade trott när jag köpte den.
  • Boken som är lite av en tegelsten omfattar väldigt många ämnen. Exempelvis UML, patterns och agila metoder för utveckling. Notera att SCRUM saknas på den här sliden. Det är för att boken är skriven av en utvecklare för utvecklare. Jag menar inte att SCRUM är ointressant för oss utvecklare, men på senare tid har SCRUM och andra projektmetodiker kommit att överskugga vad jag ser som själva fundamentet för agil utveckling, nämligen metoder för att skapa lättrörliga, eller agila, kodbaser.Hur som helst, jag nämnde ju att boken kom att ha en stor påverkan på mig, men på ett lite annorlunda sätt än jag tänkt mig. Jag hade ju köpt boken för att lära mig mera om patterns och också för att lära mig det där agila buzzwordet var för någonting. Som en bok om patterns visade det sig dock att den var ganska medioker. Och även om kapitlen om XP, TDD och så vidare var intressanta beskrev de en verklighet som var så långt ifrån min att det känndes ganska abstrakt. Istället visade det sig att det var kapitlen om designprinciper, främst de för klasser som går under samlingsnamnet SOLID som kom att ha en stor påverkan på mig.
  • Ofta när vi drar igång utvecklingen i ett projekt så är alla entusiastiska vi producerar features i en rask takt. Allt eftersom projektet fortlöper tenderar dock ofta den takten att gradvis avta. Delvis därför att den initiala entusiasmen avtar men också därför att nya funktioner som vi bygger behöver leva i harmoni med de funktioner som vi redan har byggt vilket ofta innebär att vi behöver gå tillbaka och vidareutveckla eller förändra redan levererade funktioner. Sen kanske dessutom några kundkrav ändras och vi behöver återigen modifiera redan existerande funktioner.Om det går riktigt illa ersätts entusiasmen i projektet av en trötthet, och ibland rent av en bitterhet. En bitterhet gentemot kunden för att de ändrar sina krav. Mot leverantörer av ramverk för att de inte gör det enkelt för oss att hantera förändrade krav. Och kanske hyser vi också lite bitterhet gentemot oss själva för att vi var så naiva i början att vi inte förutsåg att kraven skulle ändras.Till slut, ibland redan innan lansering, ibland några år senare, hamnar vi i ett läge där varje estimat för ändringer eller ny funktionalitet som vi ombeds estimera blir löjligt höga eftersom vi upplever systemet som så dåligt.
  • Om vi har tur så arbetar vi med kunder och kollegor som ifrågasätter varför våra estimat är så höga. Vi funderar lite och ofta är svaret att det egentligen inte alls tar så lång tid att göra den förändring som efterfrågas. Men vi är rädda för att andra saker kommer att påverkas om vi genomför förändringen och därför måste ta höjd för de följdfel som kan tänkas uppstå. Dvs vi är rädda att om vi rör funktion A så kommer det att påverka funktion B och kanske även funktion C. Och om vi fixar de följdfel som uppstår kanske de fixarna kommer att orsaka nya följdfel.Enligt min erfarenhet finns det två saker som ofta gör att vi hamnar i den här typen av situationer.
  • Komponenterna, ofta klasser, i vårt system är hårt kopplade till varandra genom att de är beroende av varandra.
  • Vårt system innehåller massor med onödig komplexitet. Ibland har den uppstått genom att vi försökt vara smarta och bygga saker som vi tror oss behöva i framtiden. Ibland genom att kraven, eller vår bild av kraven, har förändrats och vi har implementerat den till synes snabbaste lösningen. Ändrat någon if-sats här. Lagt till ett switch-block där.
  • The Single Responsibility Principle, översatt från engelska, säger att en klass bör ha en och endast en, anledning att ändras.
  • Med andra ord så bör en klass bara göra en sak. Mindre viktiga uppgifter bör delegeras till andra klasser.The Single Responsibility Principle är förmodligen den lättaste av principerna att förstå men i verkligheten visar det sig ofta att det är den svåraste att efterleva. Men det är ofta en förutsättning att man efterlever principen för att kunna efterleva de andra principerna.Ett ganska enkelt sätt som ofta fungerar för att testa om ens klass följer Single Responsibility Principle är att ge den ett namn som beskriver allt som den gör. Om det namnet innehåller ordet ”and” så gör klassen för mycket.
  • The Open/Closed Principle säger att att en klass beteende ska kunna utökas utan att klassen behöver modifieras.Med andra ord så bör vi skriva kod vars beteende vi kan förändra utan att vi behöver ändra i koden. Det finns flera olika sätt att åstadkomma det men normalt sett så menas att det bör gå att förändra en klass beteende genom att ärva från den och overridea en viss metod eller genom att låta vår klass delegera sådant som inte är dess kärnverksamhet till andra klasser och göra dessa utbytbara.Den här principen har tagit mig flera år att förstå, vilket delvis beror på att jag är trög, men också på att den är ganska abstrakt. Låt oss därför titta på ett exempel.
  • The Open/Closed Principle säger att att en klass beteende ska kunna utökas utan att klassen behöver modifieras.Med andra ord så bör vi skriva kod vars beteende vi kan förändra utan att vi behöver ändra i koden. Det finns flera olika sätt att åstadkomma det men normalt sett så menas att det bör gå att förändra en klass beteende genom att ärva från den och overridea en viss metod eller genom att låta vår klass delegera sådant som inte är dess kärnverksamhet till andra klasser och göra dessa utbytbara.Den här principen har tagit mig flera år att förstå, vilket delvis beror på att jag är trög, men också på att den är ganska abstrakt. Låt oss därför titta på ett exempel.
  • Låt oss säga att vi har blivit ombedda att skapa en klass beräknar den totala arean för ett antal rektanglar.
  • Inga problem. Vi skapar en enkel liten klass med en enda metod, Area, som tar en lista med rektanglar som parameter och returnerar deras totala area.
  • Nästa vecka kommer kunden tillbaka till oss och berättar att de har haft ett möte i styrgruppen och det finns även ett behov av att kunna beräkna arean för både rektanglar och cirklar.
  • Inga problem! Vi skapar en basklass för både rektanglar och cirklar kallad shape. Sedan ändrar vi vår Area-metod till att hantera både cirklar och rektanglar.Vår lösning fungerar utmärkt i ytterligare en vecka tills kunden haft ett nytt styrgruppsmöte och det visar sig att man även behöver kunna beräkna arean för trianglar.Så, vi skapar ytterligar en klass som ärver av Shape och gör om vår else-if i Area-metoden till ett switch-block för att hantera alla tre tänkbara figurer.Med den här lösningen behöver vi modifiera vår klass som beräknar areor för figurer varje gång en ny typ av figur läggs till. Vår klass är dessutom beroende av alla typer av figurer som den stödjer vilket innebär att om vi senare vill ta bort en typ av figur eftersom den inte längre används så måste vi återigen ändra i vår klass. Eftersom vi är rädda att det kan leda till buggar tar vi den enkla vägen ut och låter figurtypen som egentligen inte behövs vara kvar. Som resultat har vi en klass i vår applikation som inte används. Men det är det bara vi som vet.Vår klass är inte öppen för utökning och inte stängd för modifiering eftersom det enda sättet att utöka den är genom att modifiera den.
  • En alternativ lösning som satisfierar Open/Closed Principle vore att låta varje form tala om sin egen area och bara summera dem i AreaCalculator. Om vi sedan behöver lägga till, eller ta bort, former så är AreaCalculator lyckligt ovetande om det. Dess beteende är öppet för utökning men stängt för modifiering.
  • Ett exempel på ett ställe i EPiServers API som bryter mot den här principen är DataFactory som implementerar interfacet IPageSource. IPageSource har en property som heter CurrentPage. Anropar man den på DataFactory returneras null.
  • IPageSource implementeras av PageBase, Property, PageControlBase etc. Det implementeras även av DataFactory.GetChildren och GetPage är specifika till ett visst användningsscenario, CurrentPage till ett annat.

En introduktion till SOLID-principerna En introduktion till SOLID-principerna Presentation Transcript

  • Hur uncle Bob förändrade mitt liv
    En introduktion till SOLID principerna
    @joelabrahamsson
  • Agile Principles, Patterns and Practices in C#
    UML (as a sketch)
    Patterns
    Agila arbetssätt som XP, TDD och Refactoring
    Designprinciper för klasser och paket/assemblies
  • Single Responsibility Principle
    Open/Closed Principle
    Liskov Substitution Principle
    Interface Segregation Principle
    Dependency Inversion Principle
  • SOLID
    Fem priciper för objektorienterad utveckling
    Hantera beroenden mellan klasser och reducera onödig komplexitet
    Underlättar testning
    Principer, inte lagar
    Kräver att studeras
  • Single Responsibility Principle
    En klassbör ha en, ochendast en, anledningattändras.
  • Med andra ord...
    En klassskabaragöra en sak.
  • Exempel
    publicclassCustomer
    {
    publicIEnumerable<Order> Orders { get {...} }
    publicboolIsValid() {...}
    publicvoid Save() {...}
    }
  • Single Responsibility Principle
    Är även applicerbar på metoder, paket/assemblies etc.
    Ligger till grund för många av de andra principerna
  • Open/Closed Principle
    Klasserskavaraöppnaförutökning men stängdaförmodifiering.
  • Med andra ord...
    Vi böranvändaarvochpolymorfismförattskrivakodsomintebehöverändrasnärkravengör det.
  • Exempel
    Vi behöver en klasssomberäknarareanförettantalrektanglar.
    publicclassRectangle
    {
    publicdouble Width { get; set; }
    publicdouble Height { get; set; }
    }
  • Let’s do it!
    publicclassAreaCalculator
    {
    publicdouble Area(Rectangle[] shapes)
    {
    double area = 0;
    foreach (var shape in shapes)
    {
    area += shape.Width*shape.Height;
    }
    return area;
    }
    }
  • Ett nytt krav
    Vi glömdeattdetfinnscirklar. Vi behöverberäknaareanförbådecirklarochrektanglar.
  • En basklass och en if-sats -> Done!
    publicabstractclassShape { }
    publicclassAreaCalculator
    {
    publicdouble Area(Shape[] shapes)
    {
    double area = 0;
    foreach (var shape in shapes)
    {
    if (shape isRectangle)
    area += RectangleArea((Rectangle)shape);
    else
    area += CircleArea((Circle) shape);
    }
    return area;
    }
    }
  • En bättre lösning
    publicabstractclassShape
    {
    publicabstractdouble Area();
    }
    publicclassAreaCalculator
    {
    publicdouble Area(Shape[] shapes)
    {
    double area = 0;
    foreach (var shape in shapes)
    {
    area += shape.Area();
    }
    return area;
    }
    }
    • Den viktigasteavprinciperna
    • Kravenändrasständigt…
    • …men vi behöverändåskrivakodsomärstabil
    • Med OO kan vi skapaabstraktioner med stabil design men flexibeltbeteende
    • Närska vi appliceraprincipen?
    Open/Closed Principle
  • Dependency Inversion Principle
    A. Högnivåmodulerskaintevaraberoendeavlågnivåmoduler. Bådaskavaraberoendeavabstraktioner.
    B. Abstraktionerskaintevaraberoendeavdetaljer. Detaljerskavaraberoendeavabstraktioner.
  • Med andra ord...
    Våraklasserskaintevaraberoendeavandraklasser. De skavaraberoendeavabstraktioner.
  • Möjliggör att en klass kan använda en annan komponent utan att känna till vilken specifik implementation det är
    Åstadkoms genom Dependency Injection ellerService Locator
    Inversion of Control
  • Ett exempel
  • IoC leder till flexibel design
  • Den som använder vår klass måste tillhandahålla instanser av de klasser som den behöver
    Constructor Injection
    Property Injection
    Dependency Injection
  • The consumer retrieves the component it depends upon from a third party, a Service Locator
    Use Dependency Injection instead if you can
    Service Locator
  • Liskov Substitution Principle
    Subklassermåstevarautbytbara mot dessbasklasser.
  • Med andra ord...
    Användareavvårsubklassskaintebehövabry sig omhuruvida de användersubklassenellerbasklassen.
  • Ett enkelt exempel
    publicabstractclassAnimal
    {
    publicabstractvoidMakeNoise();
    }
  • Ett enkelt exempel
    publicclassCat : Animal
    {
    publicoverridevoid MakeNoise()
    {
    Console.WriteLine("Mjau");
    }
    }
  • Ett enkelt exempel
    publicclassSnail : Animal
    {
    publicoverridevoid MakeNoise()
    {
    thrownewNotImplementedException();
    }
    }
  • Liskov Substitution Principle
    Detär OK attförsvagaförhandsvillkorochstärkaefterhands-villkori en subklass men intetvärtom.
    Om vi bryter mot LSP såtyderdetpåatt vi behöverrefaktoriseravårklasshierarki
    En princip, inte en lag
  • Interface Segregation Principle
    Användareavett interface skaintetvingasvaraberoendeavmetodersom de inteanvänder.
  • Med andra ord...
    Skapa interface somärsmåochlogisktsammanhängande.
  • Exempel - IPageSource
    publicinterfaceIPageSource
    {
    PageDataCollectionGetChildren(PageReferencepageLink);
    PageDataGetPage(PageReferencepageLink);
    PageDataCurrentPage { get; }
    }
  • Exempel - IPageSource
    publicclassDataFactory : IPageSource
    {
    publicPageDataGetPage(PageReferencepageLink)
    { ... }
    publicPageDataGetChildren(PageReferencepageLink)
    { ... }
    publicPageDataCurrentPage
    {
    get
    {
    returnnull;
    }
    }
    }
  • Mer om SOLID-principerna
    Agile Principles, Patterns and Practices in C#
    butunclebob.com
    blog.objectmentor.com
    Stefan Forsbergs serie på EPiServer World
    www.codingefficiency.com
  • Mer av uncle Bob
  • Sammanfattning
    Uncle Bob, Robert C.Martin, är en författare vi kan lära mycket av
    Läs Agile Principles, Patterns and Practices in C#!
    Läs Clean Code!
    SOLID är fem principer för objekt orienterad utveckling som hjälper oss hantera beroenden och komplexitet
  • @joelabrahamsson
    http://joelabrahamsson.com