johannormen skrev:
Bra böcker till ämnet:
Code Complete - MS Press
...
Ja, den boken är bra, inte minst för att den innehåller en hel del referenser till diverse studier. Exempelvis i kapitlet som handlar om längden på metoder/"rutiner" (kapitel 7.4) så propagerar inte författaren för en subjektiv åsikt om hur långa rutinerna ska vara, utan hänvisar till sex olika studier angående vilken längd som leder till minst problem. I det sammanfattande stycket kan man bl.a. läsa följande:
"... From time to time, a complex algorithm will lead to a longer routine, and in those circumstances, the routine should be allowed to grow organically up to 100-200 lines. (A line is a noncomment, nonblank line of source code.) Decades of evidence say that routines of such length are no more error prone than shorter routines...."
Missförstå mig nu inte och tro att jag rekommenderar långa metoder, för det gör jag definitivt inte, men jag vänder mig bara mot följande attityd att det är ett ändamål i sig att hålla ner antalet rader till ett minimum med en övre gräns på 10 rader:
johannormen skrev:
...Skriv metoderna så små ni kan, när det är gjort gör dem ännu mindre ändå. (Försök ha 10 rader som maxkrav...
I sammanhanget kan det även vara värt att kommentera följande bok (som jag också håller med om att den är bra):
johannormen skrev:
Bra böcker till ämnet:
...
Refactoring - Martin Fowler
...
I den boken finns bl.a. en refactoring som heter Inline Method som man kan använda när man har metoder som "are no longer pulling their weight" eller när man "get lost in all the delegation".
Det är med andra ord inte självklart att extrahera metoder till så små metoder som möjligt, såvida man inte vill ifrågasätta existensen av den motsatta refaktoriseringen "Inline Method", men mig veterligen så är den inte kontroversiell (och jag tycker själv inte att den borde vara det, utan att den helt klart kan vara befogad ibland).
Observera alltså att "Inline Method" är en refactoring som går i motsatt riktning som den refactoring Extract Method som användes i exemplet i denna tråd där rekommendationen var att byta ut:
johannormen skrev:
someThingtoHandle.Number = GetNumA * GetNumB - GetNumC + NumberA;
mot en ny extraherad metod:
johannormen skrev:
someThingtoHandle.Number = GetNextValidNumber();
och jag håller inte med det exemplet (med exemplets befintliga metodnamn) såvida inte beräkningen "GetNumA * GetNumB - GetNumC + NumberA" återanvänds, för i så fall är det självklart att extrahera beräkningen till en egen metod.
Så länge metoden inte återanvänds så ser jag ingen anledning till att lägga den i en egen metod (med de metodnamn som används) eftersom semantiken i den anropade metoden inte tillför särskilt mycket. Jag menar, eftersom det finns många sätt för ett nummer att vara "valid" så är "GetNextValidNumber" nästan lika intetsägande som "GetNumA" och "GetNumB". Med ett mer verkligt exempel så skulle det förstås kunna vara på det viset att den extraherade metoden får ett namn som faktiskt beskriver vad man får fram för slags värde, t.ex. genom någon typ av beräkning, och i så fall har den ett större existensberättigande som egen metod, även om den inte återanvänds.
Min poäng är alltså att man inte ska fokusera så mycket på metodlängden för att avgöra huruvida man borde dela upp en metod på flera metoder, utan det är andra parametrar som borde avgöra, bl.a. om den nya metoden kan erbjuda semantik som gör koden mer läsbar. Det är dock inte alltid självklart att en extra metod förbättrar semantiken, vilket den ovanstående länken till "Inline Method" illustrerar, där Fowler refaktoriserar bort metoden "moreThanFiveLateDeliveries()" och istället använder inline-uttrycket "numberOfLateDeliveries > 5" eftersom han anser att det ger lika tydlig kod.
En annan viktig faktor (förutom den förbättrade semantiken som ett metodanrop eventuellt kan erbjuda) som påverkar metodlängden är förstås den nämnda Single Responsibility Principle (SRP) vilket f.ö. är ungefär samma sak som High Cohesion (HC) och i Code Complete så skriver författaren bl.a. att "rutinens cohesion" är en bidragande faktor som påverkar hur lång en metod lämpligen bör vara ("rather than imposing a length restriction per se") tillsammans med bl.a. "depth of nesting", "number of variables" m.m.
För den som programmerar i C# så kan det förresten vara särskilt frestande att utnyttja/missbruka en särskild "feature" nämligen output-variabler så att man låter en metod returnera flera olika värden.
(i java finns inte den direkta möjligheten, men däremot finns liknande möjligheter att indirekt populera flera output-variabler t.ex. via en input-hashtabell så att man därigenom skapar ännu groteskare kod...)
I en sådan situation (med flera output-parametrar) så blir metoden sannolikt längre eftersom den ska plocka ut flera värden, men då är grundproblemet att man inte tillämpar SRP/HC inom metoden, och längden på metoden är förstås beroende på hur många olika saker man låter metoden utföra, och det är detta som man alltså ska fokusera på (dvs fokusera på SRP/HC och inte på att minimera antalet rader i metoden, vilket istället bör bli en bieffekt). Om man tillämpar SRP/HC så blir metoderna kortare än om man inte gör det, vilket är bra (t.ex. är det ju väldigt trevligt att kunna läsa en hel metod på skärmen utan scrollning) men det är alltså inget automatiskt självklart ändamål att minimera antalet rader eller att sikta på högst 10 rader, utan som sagt var så bör man ha i åtanke att:
"...up to 100-200 lines...Decades of evidence say that routines of such length are no more error prone than shorter routines...." (Code Complete, 2:a upplagan, sid 174, kapitel 7.4)
/ Tomas