lördag 31 januari 2009

E1, E2 och F1 - F4

Går vidare med E1, E2 och F1 - F4

E1: Kräver mer än ett steg för att bygga

Din arbetsplats ska vara så automatiserad som möjligt. Faktiskt tycker jag inte att denna punkt går tillräkligt långt. Kompilering och bygge borde ske i bakgrunden och aldrig behöva aktiveras manuellt, utan alltid vara klart. Men självklart ska man inte behöva köra olika skript, flytta filer manuellt för att kunna bygga applikationen. Jag skulle också vilja tillägga att allt ska gå snabbt. Att vänta i 2-3 minuter flera gånger i timmen för att kolla att något fungerar är en enorm tidstjuv.

E2: Kräver mer än ett steg för att köra tester
Inget konstigt och i samma anda som E1. Din arbetsplats skall vara så automatiserad som möjligt. Kommandot för att köra alla tester ska alltid ligga framme för enkel åtkomst och inte kräva att man följer en wizard etc. Snabbt, enkelt och självklart.

F1: För många argument

Metoder som inte tar några argument är bäst. En, två och undantagsvis tre variabler kan vara acceptabelt. Fler variabler i en metod bör utlösa en flod av förslag på förändringar som kan få koden att lösa sin uppgift på ett bättre sätt.

F2: "Output" argument
När man använder outputargument tvingar man läsaren av koden att tänka baklänges. Många klarar att tänka baklänges men för nästan alla kräver det en extra insats. Det är bättre att returnera ett objekt som innehåller de variabler som ska vara tillgänglia efter metodanropet. Detta gäller även för att modifiera collections där det är tydligare om man returnerar den modifierade "samlingen" än lämnar läsaren av koden med frågan om något hände med objektet som stoppades in i metoden.

F3: Boolska flaggor som arguement
En boolean som argument visar ofta att metoden har två uppgifter. Om argumentet är sant gör si och om det är falskt gör så. Bättre då att skriva två olika metoder eller kanske till och med tre metoder. Tre metoder förklaras med att den boolska flaggan bara påverkar en del av metoden och då kan man skriva den gemensamma delen som en metod och sedan två metoder för den delen som styrs av flaggan.

F4: Oanvända funktioner
Funktioner som inte används raderar vi självklart och tveklöst. Vi har versionshanteringssystem för att hitta kod som en gång i tiden funnits.

söndag 18 januari 2009

C1-C5

Försöker att beskriva reglerna C1 till C5
  • C1: Fel information i fel system
  • C2: Felaktiga kommentarer
  • C3: Onödiga kommentarer
  • C4: Dåligt skrivna kommentarer
  • C5: Bortkommenterad kod
C1: Fel information i fel system
Första frågan man måste fråga sig är vilka kommentarer som är lämpliga att ha i programmeringskod. Är det verkligen relevant att ha en kommentar som säger att ändringen utfördes för bugg #34 eller att ha en lista med de 20 senaste ändringarna? Regeln jag följer är att alla kommentarer i koden ska beskriva koden och inte versionenhantering, ärendehantering eller något annat som bör hanteras av system utanför koden. Tex bör ett bra ärendehanteringssystem hålla reda på vilka ändringar i källkoden som gjorts för ett ärende. Det borde inte vara något som ska stå i källkoden.

C2: Felaktiga kommentarer
Vem av oss har inte läst en kommentar som har skickat ut oss på någon timme av felsökning i fel ände av problemet för att koden har förändrat men inte kommentarern. Felaktiga kommentarer förstör värdet av flera hundra bra då de rubbar förtroendet för hela applikationen. Vågar jag verkligen lita på det som står där?

C3: Onödiga kommentarer
De av er som använder Visual Studio har säkert hört talas om Ghostdoc. Det är en liten plugin som utifrån en metodsignatur skapar kommentar. Problemet med Ghostdoc är att de kommentarer som programmet skriver inte tillför något utan enbart är en upprepning av den information som står i metodsignaturer. Det enda som tillförs är fler rader av kod som måste underhållas. Fler kommentarer som efter en ändring riskerar att att ljuga för läsaren. Slutsatsen bör alltså vara att om du inte tänker bidra med något som inte redan står i koden bör du hellre låta bli att skriva kommentaren i första läget. Nu är det säkert något som undrar hur dokumentationssystem som tex javadoc ska hanteras, då de använder formaterade kommentarer för att extrahera ur infomation från källkoden. Svaret hittar vi i C1. Det vore kanske bättre att ha något annat system för att hantera den typen av information.

C4: Dåligt skrivna kommentarer
När man skriver kommentarer ska man inte göra det slentrianmässigt tex som vid användade av Ghostdoc. En kommentar bör värderas högt och man bör lägga en hel del möda på att skriva kommentaren så bra det går. Vad är en dålig kommentar? Den är ju inte felaktig som i C2. En dålig kommentar kan vara felaktigt placerad, vara oprecis och eller onyanserad. Den kanske bara delvis är relevant.Vad ska man göra med en dålig kommentar? Man lämnar den naturligtvis inte det dåliga skicket utan ser till att det antingen blir en bra kommentar eller en raderad kommentar (som man får hitta i versionshanteringssystemet).

C5: Bortkommenterad kod
Här finns det inga ursäkter. Använd ett versionshanteringssystem om ni har ringaste intresse av att den bortkommenterade koden ska gå att återfinna. Så kort och gott, bort med skiten, bortkommenterad kod har inte i en källkodsfil att göra.

lördag 17 januari 2009

De största reglerna

De olika reglerna som Bob Martin beskriver i sin bok finns några som är "större" än de andra. De kanske är självklara på sitt sätt men är långt i från alltid självklart hur man faktiskt ska hantera dem.

  1. G5: Duplicering: Lätt att förstå men svår att faktisk genomföra. Det är så lätt att göra copy and paste. Det finns en mängd trick för att undvika att duplicera koden men vilket ska man använda i vilken situaion. Men som sagt, det är lätt att förstå att det är dåligt att ha samma kod på två ställen.
  2. N1: Använd beskrivande namn: En gång i tiden fick en variabel inte använda mer än åtta tecken, då var man tvungen att skriva btn i stället för Button. En gång i tiden hanterade vi bara bytes, då var det en god idé att ha med typen i variabelnamn för att veta hur man skulle hantera respektive byte. Idag kan vi skapa typer för varje behov. Så använd den frihet vi idag har till att faktiskt skriva vad saker är och ska göra så att det är så tydligt det någonsin kan bli.
  3. G12: Skräp: Allt som inte tillför något är skräp. Det låter svepande men är grunden för flera av de andra reglerna, tex C2, C3, C4, C5, F4 och G9
  4. G27: Struktur över konvention: Att tala om en procedur ska följas är enkelt. Att komma ihåg att man ska följa proceduren är svårare. Därför är det bättre att genom struktur tvinga efterlevnad. Får en klass bara instansieras en gång använd, implementera en singleton i stället för att skriva en kommentar som beskriver användningen.
  5. G6: Kod i fel abstraktions nivå: Vi människor är duktiga på att blanda abstraktionsnivå. Vi kan beskriva stora skeden en sekund och sedan hoppa ner på detaljer i nästa. Det är dock svårt att förstå kod som blandar abstraktionsnivåer. Detta är nog en av de svåraste reglerna att både förstå och sedan följa.

lördag 10 januari 2009

Översättning

Jag ger mig på att försöka att översätta Robert C. Martins "kodregler" ur boken Clean Code lite kortfattat. De beskriver inte saker som nödvändigtvis är felaktiga eller dåliga men situationer och saker där man bör fundera ett varv extra på om man kanske har något som man kanske kan göra bättre.

Om kommentarer
  • C1: Fel information i fel system
  • C2: Felaktiga kommentarer
  • C3: Onödiga kommentarer
  • C4: Dåligt skrivna kommentarer
  • C5: Bortkommenterad kod
Utvecklingsmiljö
  • E1: Kräver mer än ett steg för att bygga
  • E2: Kräver mer än ett steg för att köra tester
Funktioner
  • F1: För många argument
  • F2: "Output" argument
  • F3: Boolska flaggor som arguement
  • F4: Oanvända funktioner
Allmänna
  • G1: Flera språk i samma fil
  • G2: Förväntat beetende är inte implementerat
  • G3: Felaktigt beteende vid gränser (boundaries, cornercases)
  • G4: Borttagna säkerhets funktioner
  • G5: Duplicering
  • G6: Kod i fel abstraktions nivå
  • G7: Klasser beroende av sina arvingar
  • G8: För mycket information
  • G9: Död kod
  • G10: Vertikalt avstånd
  • G11: Inkonsekvens
  • G12: Skräp
  • G13: Artificiella kopplingar
  • G14: Funktionsavundsjuka
  • G15: Val genom argument
  • G16: Kodat uppsåt
  • G17: Felaktigt placerat ansvar
  • G18: Olämpligt användning av static
  • G19: Använd förklarande variabler
  • G20: Funktionsnamn ska säga vad de gör
  • G21: Förstå algoritmen
  • G22: Gör logiska beroenden fysiska
  • G23: Föredra arv före if/else eller switch
  • G24: Följ konventioner enligt standard
  • G25: Ersätt magiska nummer med konstanter
  • G26: Var exakt
  • G27: Struktur över konvention
  • G28: Dölj boolska uttryck
  • G29: Undvik negativa booska uttryck
  • G30: Funktioner bör göra en sak
  • G31: Dolt beroende av tid/ordning
  • G32: Var inte godtycklig
  • G33: Kapsla in gränsfall
  • G34: Funktioner går enbart en abstraktionsnivå ner
  • G35: Håll konfigurerbart data på hög abstraktionsnivå
  • G36: Undvik beroenden på beroende
Namn
  • N1: Använd beskrivande namn
  • N2: Välj rätt namn på rätt abstraktionsnivå
  • N3: Använd standardiserad vokabulär
  • N4: Otvetydiga namn
  • N5: Använd långa namn på stora "scope"
  • N6: Koda inte koden
  • N7: Namn ska beskriva sidoeffekter
Tester
  • T1: Otillräkliga tester
  • T2: Använd test-täcknings verktyg
  • T3: Strunta inte i triviala tester
  • T4: Ett ignorerat test är en fråga om tveksamheter
  • T5: Testa gränsfall
  • T6: Testa mer runt buggar
  • T7: Se mönster för varför tester falerar
  • T8: Testtäckning påvisar mönster
  • T9: Tester ska vara snabba

torsdag 1 januari 2009

Law of Demeter

Hur mycket ska ett objekt känna till om andra objekt. Svaret är enkelt, desto mindre desto bättre. Anledningen är lika enkel som svaret. Om den anropande klassen känner till hur den anropade klassen löser sin uppgift blir det svårt att ändra den anropade klassen. Tänk följande scenario:

public Employee getEmployeeSalary(int idNumber){
Employee employee = Context.getInstance().getSearchService.getEmployeeById(idNumber);
return employee.getCurrentSalary();
}

I metodenovan har vi effektivt låst fast implementationen av hur Context levererar en Employee från dess Id. Om vi skulle göra en förändring av kedjan av anrop kan det bli många ställen att ändra på i koden.

Hur bör man göra då? Den trista lösningen är vi ska lägga in en metod i Context och låta Context ta beslutet för hur Employee ska levereras. Om vi nu skulle vilja flytta getEmployeeById från SearchService till EmployeeService kan vi göra det utan att en mängd beroenden också måste ändras. Det är dock inte helt oproblematiskt att göra på detta sätt. Vi riskerar ett scenario där vi översvämmar Context-klassen med ett stort antal metoder.