window.pipedriveLeadboosterConfig = { bas: 'leadbooster-chat.pipedrive.com', företagId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2, } ;(funktion () { var w = fönster if (w.LeadBooster) { console.warn('LeadBooster finns redan') } annars { w.LeadBooster = { q: [], on: funktion (n, h) { this.q.push({ t: "o", n: n, h: h }) }, trigger: funktion (n) { this.q.push({ t: 't', n: n }) }, } } })() thecodest, Author at The Codest - Page 8 of 18

Därför är det obegripligt för vissa att Refaktorisering är faktiskt ett område inom programmering, och det är också en mycket viktig del av programmerarens arbete. Koden är i ständig utveckling, den kommer att modifieras så länge det finns möjlighet att lägga till nya funktioner. Den kan dock anta en form som inte längre gör det möjligt att effektivt lägga till nya funktioner och det skulle då vara enklare att skriva om hela programmet.

Vad är refaktorisering?

Vanligtvis får man svaret att det handlar om att ändra kodens struktur genom att tillämpa en serie refaktoriseringstransformationer utan att påverka kodens observerbara beteende. Detta är sant. Nyligen kom jag också över en definition av Martin Fowler i sin bok "Förbättra utformningen av befintlig kod" där han beskriver Refaktorisering som "att göra stora förändringar i små steg". Han beskriver Refaktorisering som en kodändring som inte påverkar dess funktion, men han betonar att det måste göras i små steg.

Boken förespråkar också att Refaktorisering inte påverkar kodens funktion och påpekar att det inte har någon effekt på att klara testerna vid någon tidpunkt. Den beskriver steg för steg hur man på ett säkert sätt utför Refaktorisering. Jag gillade hans bok eftersom den beskriver enkla knep som kan användas i det dagliga arbetet.

Varför behöver vi refaktorisering?

 Oftast kan du behöva det när du vill införa en ny funktionalitet och koden i sin nuvarande version inte tillåter det eller det skulle vara svårare utan ändringar i koden. Det är också användbart i fall där det är olönsamt tidsmässigt att lägga till fler funktioner, det vill säga att det skulle vara snabbare att skriva om koden från grunden. Jag tror att det ibland glöms bort att Refaktorisering kan göra koden renare och mer läsbar. Martin skriver i sin bok hur han utför refaktorisering när han känner obehagliga lukter i koden och, som han uttrycker det, "det lämnar alltid utrymme för det bättre". Och han överraskade mig här genom att se refaktorisering som en del av det dagliga kodarbetet. För mig är koderna ofta obegripliga, att läsa den är lite av en upplevelse eftersom koden ofta är ointuitiv.

Det som utmärker ett väl utformat program är dess ModularitetTack vare detta räcker det med att känna till en liten del av koden för att göra de flesta ändringar. Modularitet gör det också lättare för nya personer att komma in och börja arbeta mer effektivt. För att uppnå denna modularitet måste relaterade programelement grupperas tillsammans, och kopplingarna måste vara begripliga och lätta att hitta. Det finns ingen enskild tumregel för hur detta kan göras. Allt eftersom du vet och förstår mer och mer av hur koden är tänkt att fungera bättre kan du gruppera elementen, men ibland måste du också testa och kontrollera.

En av reglerna för refaktorisering i YAGNIär en akronym för "You Aren't Gonna Need It" och härstammar från eXtreme-programmering (XP) används främst i Agil Utveckling av programvara lag. För att göra en lång historia kort, YAGNI säger att endast aktuella saker ska göras. Det betyder i princip att även om något kan behövas i framtiden, så ska det inte göras just nu. Men vi kan inte heller krossa ytterligare tillägg och det är här modularitet blir viktigt.

När man talar om Refaktoriseringmåste ett av de viktigaste inslagen nämnas, nämligen testerna. I Refaktoriseringmåste vi veta att koden fortfarande fungerar, eftersom Refaktorisering ändrar inte hur den fungerar, utan dess struktur, så alla tester måste godkännas. Det är bäst att köra tester för den del av koden som vi arbetar med efter varje liten förändring. Det ger oss en bekräftelse på att allt fungerar som det ska och det förkortar tiden för hela operationen. Det är detta som Martin pratar om i sin bok - kör tester så ofta som möjligt för att inte behöva ta ett steg tillbaka och slösa tid på att leta efter en transformation som förstörde något.

Refaktorisering av kod utan testning är jobbigt och det finns en stor risk att något går fel. Om det är möjligt är det bäst att lägga till åtminstone några grundläggande tester som ger oss en liten försäkran om att koden fungerar.

De omvandlingar som anges nedan är endast exempel men de är till stor hjälp vid daglig programmering:

Exempel

Detta är en artikel om Refaktorisering och ett exempel behövs. Jag vill visa ett enkelt refaktoriseringsexempel nedan med användning av Åsidosätta det nästlade uttalandet och Ersättning av den villkorliga instruktionspolymorfismen. Låt oss säga att vi har en programfunktion som returnerar en hash med information om hur man vattnar växter i verkligheten. Sådan information skulle förmodligen finnas i modellen, men i det här exemplet har vi den i funktionen.

def vattning_info(anläggning)
     resultat = {}
     om anläggningen.är_en? Sukulent || växt.är_en? Kaktus
         resultat = { vatten_mängd: "Lite grann" , how_to: "Från botten", vattning_duration: "2 veckor" }
     elsif plant.is_a? Alocasia || plant.is_a? Maranta
         resultat = { vattenmängd: "Stor mängd", hur_to: "Som du vill", vattning_duration: "5 dagar" }
     elsif plant.is_a? Peperomia
         result = { water_amount: "Dicent mängd",
             hur_till: "Från botten! de gillar inte vatten på bladen",
             vattning_duration: "1 vecka" }
     annat
         resultat = { vattenmängd: "Dicent mängd",
             how_to: "Som du vill",
             vattning_duration: "1 vecka"
             }
     slut
     returnera resultat
 slut

Tanken är att förändra om man ska återvända:

om plant.isa? Suculent || plant.isa? Kaktus

     resultat = { vattenmängd: "Lite grann" , howto: "Från botten",

Till

return { vatten_mängd: "Lite grann" , how_to: "Från botten",vattning_duration: "2 veckor" } if plant.is_a? Sukulent || plant.is_a? Kaktus

returnera { vattenmängd: "Lite grann" , hurtill: "Från botten",vattningvaraktighet: "2 veckor" } if plant.isa? Sukulent || plant.is_a? Kaktus

Och så vidare med allt, tills vi kommer till en funktion som ser ut så här:

def vattning_info(anläggning)

returnera resultat = { vattenmängd: "Lite grann" , howto: "Från botten", vattningduration: "2 veckor" } if plant.isa? Sukulent || plant.is_a? Kaktus

return resultat = { vattenmängd: "Stor mängd", howto: "Som du vill", vattningens varaktighet: "5 dagar" } if plant.isa? Alocasia || plant.is_a? Maranta

return resultat = { vattenmängd: "Dicent mängd",

          hur man gör: "Från botten! de gillar inte vatten på bladen",
          vattnets varaktighet: "1 vecka" } if plant.is_a? Peperomia

return resultat = { vattenmängd: "Dicent mängd",

          hur_to: "Som du föredrar",

          vattning_duration: "1 vecka"

          }

slut

 I slutet hade vi redan ett returresultat. Och en god vana är att göra detta steg för steg och testa varje förändring. Du kan ersätta det här if-blocket med ett switch-fall och det skulle se bättre ut direkt, och du skulle inte behöva kontrollera alla if:ar varje gång. Det skulle se ut så här:

def vattning_info(anläggning)

swich växt.klass.till_sträng

fall Suckulent, Kaktus

     { vattenmängd: "Lite grann" , howto: "Från botten", vattning_duration: "2 veckor" }

fall Alocasia, Maranta

     { vattenmängd: "Stor mängd", howto: "Som du vill", vattning_duration: "5 dagar" }

fall Peperomia

     { vattenmängd: "Dicent mängd",

          hur_till: "Från botten! de gillar inte vatten på bladen",

          vattning_duration: "1 vecka" }

annat

     { vatten_belopp: "Dicent mängd",

            hur_to: "Som du föredrar",

       vattning_duration: "1 vecka" }

Slut

slut

Och sedan kan du använda Ersätta den villkorliga instruktionen Polymorfism. Detta för att skapa en klass med en funktion som returnerar rätt värde och byter ut dem på rätt plats.

klass Suckulenta

...

def vattning_info()

     return { vattenmängd: "Lite grann" , howto: "Från botten" , watering_duration: "2 veckor" }

slut

slut

klass Cactus

...

def vattning_info()

     return { vattenmängd: "Lite grann" , howto: "Från botten" , watering_duration: "2 veckor" }

slut

slut

klass Alocasia

...

def vattning_info

     return { vattenmängd: "Stor mängd", howto: "Som du föredrar", vattning_duration: "5 dagar" }

slut

slut

klass Maranta

...

def vattning_info

     return { vattenmängd: "Stor mängd", howto: "Som du föredrar", vattning_duration: "5 dagar" }

slut

slut

klass Peperomia

...

def vattning_info

     return { vatten_belopp: "Dicent belopp",

      hur_till: "Från botten! De gillar inte vatten på bladen",

      vattning_duration: "1 vecka" }

slut

slut

klass Växt

...

def vattning_info

     return { vatten_belopp: "Dicent belopp",

              hur_till: "Som du föredrar",

              vattning_duration: "1 vecka" }

Slut

slut

Och i huvudfunktionen watering_infofunction kommer koden att se ut så här:

def vattning_info(anläggning)

    växt.karta(&:vattning_info)

slut

Naturligtvis kan denna funktion tas bort och ersättas med dess innehåll. Med det här exemplet ville jag presentera den allmänna mönster för refaktorisering.

Sammanfattning

Refaktorisering är ett stort ämne. Jag hoppas att den här artikeln var ett incitament att läsa mer. Dessa refaktoriseringskompetens hjälpa dig att fånga dina buggar och förbättra din rena kodverkstad. Jag rekommenderar att du läser Martins bok (Improving the Design of Existing Code), som är en ganska grundläggande och användbar uppsättning regler för Refaktorisering. Författaren visar olika omvandlingar steg för steg med en fullständig förklaring och motivation och tips om hur man undviker misstag i Refaktorisering. På grund av sin mångsidighet är det en förtjusande bok för frontend- och backend-utvecklare.

Bli junior Ruby-utvecklare

Läs mer om

GraphQL Ruby. Hur är det med prestanda?

Räls och andra transportmedel

Rails-utveckling med TMUX, Vim, Fzf + Ripgrep

sv_SESwedish