Refaktoriseringsjunkie
Dags att färdigställa det mer yrkesrelaterade av blogginläggen för dagen. Jag hade gärna gjort det tidigare, men hade trevliga, sociala aktiviteter inbokade. För en stund sedan kom jag hem och eftersom jag drack kaffe efter oplanerad söndagmiddag med vänner föreligger viss risk för att det blir svårt att somna.
…
Idag är det alltså Sveriges nationaldag och jag är först och främst ganska trött, behöver vila lite också. Om jag nu vet hur man gör. Sent igår kväll lämnade jag in den avslutande uppgiften för vårens högst prioriterade kurs (se studierapport i föregående inlägg) och håller så smått på att varva ned. Jag har kört rätt hårt på jobbet under våren vilket bl.a. bidragit till att studierna hamnat lite på undantag.
Om jobbet, ja. Jag kör som sagt hårt, inte ens alltid för att jag måste utan för att jag inte kan låta bli (hjälp, jag behöver avgiftning!), men innan någon ringer efter hjälp vill jag påpeka att parentesen var humoristisk. Läget är under kontroll och när det närmar sig för mycket ser jag till att få den återhämtning jag behöver.
Icke desto mindre är jag nog lite av en junkie när det gäller ordning och reda, data och programmering, och för det sistnämnda inte minst refaktorisering.
Det är få saker som är så tillfredsställande som att få städa upp i mossbelupen och mögelangripen gammal bortglömd och försummad kod så att den blir klar, tydlig, begriplig och lätt att uppdatera när ny eller ändrad funktionalitet ska in. Att t.ex. eliminera krångliga språkliga konstruktioner eller vända på villkor, i syfte att förenkla koden och därigenom öka förståelsen, liksom skala av lager efter lager av plack som samlats genom åren och vid mindre uppdateringar. Fantastiskt!
Jag blir ständigt överraskad och förundrad över hur effektivt det är just att vrida och vända och plocka isär och sedan återuppbygga programkod. Buggar gör sig plötsligt uppenbart påminda, död kod rullar ut över bordskanten eller bara blåser bort i en uppfriskande bris när jag jonglerar eller kastar upp alla delar i luften. Det som kommer ner igen är det som behövs, och det som får vara kvar. Typ.
Ett av mina favoritverktyg just nu är visualisering, eller mer specifikt: diagram. Normalt sett ritar jag diagram i huvudet för att hålla reda på och förstå flödet i koden och vad den gör, men vissa saker är för stora för att riktigt få plats eller så behöver jag kommunicera med andra och då kan det underlätta med diagram. I datorn, thank you very much – jag fixar inte att rita för hand på en whiteboard. Avundas lite grann dem som kan, om jag ska vara ärlig. Det är en bra förmåga som gör det enklare för olika människor att kommunicera och förstå varandra.
I min senaste refaktoriseringsuppgift ingick det att dokumentera flödet genom systemet via ett sekvensdiagram och det var ritandet av diagrammet (givetvis med tillhörande noggrann analys) som tog den allra största delen av tiden.
Jag gick grundligt till väga genom att först rita in vartenda litet metodanrop, både inom tjänsten och utåt mot andra tjänster, genom hela flödet och det var banne mig tur att jag jobbade hemifrån, för det resulterande diagrammet var gigantiskt! Min (dock är den inköpt av sambon, så rent tekniskt hans, men det är främst jag som använder den) 27-tumsskärm räckte inte långt, och på jobbet har jag bara två mindre skärmar på 21 eller 22 tum… det hade inte alls funkat särskilt bra.
Eftersom diagrammet blev så stort slog jag isär det och analyserade delarna av flödet var för sig och samtidigt lärde jag mig att man i PlantUML kan använda include-filer. Notera att jag ur ett utifrånperspektiv ritade diagram, medan jag i själva verket analyserade kodens funktion med hjälp av denna visualisering.
Analysen resulterade i en väldigt mycket bättre förståelse för vad som görs, samt ett ifrågasättande av en hel mängd olika anrop till angränsande tjänster.
Varför hämtas Objekt A i ett separat anrop när samma objekt faktiskt kommer in via hämtning av en bunt Objekt B, som alltid måste göras? Den koden försvann.
Och ja, detta är en designförändring som potentiellt kan ge ändrat beteende och därför har jag nogsamt tänkt igenom eventuella följder. Teoretiskt kan det bli fel, men jag kan inte se att det bör kunna bli det i praktiken. Famous last words…
Varför hämtas en bunt Objekt C för att eventuellt läggas in i bunten med Objekt B, när detta redan gjordes när Objekt B-bunten hämtades. Hela denna sista del av initialflödet visade sig alltså också vara överflödig. Även den koden försvann.
Ni ser vart vi är på väg, va? Flera delar av flödet är redan bortstädade och mitt diagram börjar bli hanterbart i storlek. Dags att titta närmare på den egentliga funktionaliteten i flödet, koden där det som ska göras också är det som görs.
Här flyttar jag omkring kodrader och ändrar villkor så att saker står för sig själva så mycket det går och bara det som verkligen hör ihop står tillsammans. Detta uppenbarar en struktur som gör flödet lättare att förstå, men det kan bli bättre.
Jag bryter ut den kod som förbereder och utför hämtningen av ett antal Objekt B till en egen, separat metod (som dessutom blir lätt att testa). Denna får heta just ”hämta Objekt B”. Det blir tydligt för läsaren att grunden är en bunt Objekt B.
På liknande sätt strukturerar jag om så att koden som gör det egentliga jobbet ligger i en klunga och kan brytas ut till en egen metod vid namn ”gör jobbet”. Detta tydliggör uppgiften (förutsatt att man bryter ut rätt saker!) och lämnar utrymme att fokusera på de förberedande åtgärder som måste vidtas innan.
Några kontroller som kan avbryta flödet flyttas upp för att undvika situationen att det vid ett avbrott utförts onödigt arbete. Det är en bra princip, det där att göra så lite så möjligt så sent som möjligt, och som en följd därav kanske inte behöva göra något alls. Prokrastinering som princip. Hm… det tål att tänkas på.
När jag tittade på sekvensdiagrammet undrade jag också varför det gjordes två anrop, direkt efter varandra, mot en viss tjänst. Kunde man inte lika gärna göra bara ett anrop och låta den anropade metoden utföra båda uppgifterna? Efter att ha undersökt hur de två metoderna i övrigt användes i systemet (svar: inte alls) slog jag ihop dem till en enda, givetvis med ett tydligt beskrivande namn.
Och där någonstans kunde jag inte hitta något mer att ta bort och ansåg mig därmed vara klar. Nu är koden luftigt lätt och ledig. Den doftar sommaräng!
Nästa fråga: var och när ska jag få min nästa fix? Jag längtar redan…
Tryckt & kränkt