Siksi joillekin on käsittämätöntä, että refaktorointi on itse asiassa ohjelmoinnin osa-alue, ja se on myös erittäin tärkeä osa ohjelmoijan työtä. Koodi kehittyy jatkuvasti, sitä muutetaan niin kauan kuin on mahdollista lisätä uusia toiminnallisuuksia. Se voi kuitenkin ottaa muodon, joka ei enää mahdollista uusien toiminnallisuuksien tehokasta lisäämistä, ja silloin olisi helpompaa kirjoittaa koko ohjelma uudelleen.
Mitä refaktorointi on?
Yleensä vastaus on, että koodin rakennetta muutetaan soveltamalla useita refaktorointimuunnoksia vaikuttamatta koodin havaittavaan käyttäytymiseen. Tämä on totta. Äskettäin törmäsin myös määritelmään Martin Fowler kirjassaan "Olemassa olevan säännöstön suunnittelun parantaminen" jossa hän kuvailee refaktorointi "suurten muutosten tekeminen pienin askelin". Hän kuvailee refaktorointi koodimuutoksena, joka ei vaikuta sen toimintaan, mutta hän korostaa, että se on tehtävä pienin askelin.
Kirjassa myös kannatetaan, että refaktorointi ei vaikuta koodin toimintaan ja huomauttaa, että sillä ei ole vaikutusta testien läpäisyyn missään vaiheessa. Siinä kuvataan vaihe vaiheelta, miten turvallisesti suoritetaan refaktorointi. Pidin hänen kirjastaan, koska siinä kuvataan yksinkertaisia temppuja, joita voi käyttää jokapäiväisessä työssä.
Miksi tarvitsemme refaktorointia?
Useimmiten saatat tarvita sitä, kun haluat ottaa käyttöön uuden toiminnallisuuden ja koodi nykyisessä versiossaan ei salli sitä tai se olisi vaikeampaa ilman muutoksia koodiin. Se on hyödyllinen myös silloin, kun uusien ominaisuuksien lisääminen ei ole ajallisesti kannattavaa, eli olisi nopeampaa kirjoittaa koodi uudelleen alusta alkaen. Mielestäni joskus unohdetaan, että refaktorointi voi tehdä koodista siistimpää ja luettavampaa. Martin kirjoittaa kirjassaan, miten hän tekee refaktorointia, kun hän tuntee epämiellyttäviä hajuja koodissa, ja miten hän asian ilmaisee, "se jättää aina tilaa paremmalle". Hän yllätti minut tässä yhteydessä näkemällä refaktoroinnin osana jokapäiväistä koodityöskentelyä. Minulle koodit ovat usein käsittämättömiä, niiden lukeminen on hieman kokemus, koska koodi on usein epäintuitiivista.
Hyvin suunnitellun ohjelman tunnusmerkki on sen modulaarisuus, jonka ansiosta riittää, että tunnet vain pienen osan koodista, jotta voit tehdä suurimman osan muutoksista. Modulaarisuus helpottaa myös uusien ihmisten sisäänpääsyä ja työskentelyn aloittamista tehokkaammin. Modulaarisuuden saavuttamiseksi toisiinsa liittyvät ohjelman osat on ryhmiteltävä yhteen, ja yhteydet on ymmärrettävä ja löydettävä helposti. Ei ole olemassa mitään yksittäistä nyrkkisääntöä siitä, miten tämä voidaan tehdä. Kun tiedät ja ymmärrät yhä paremmin, miten koodin on tarkoitus toimia, voit ryhmitellä elementtejä, mutta joskus sinun on myös testattava ja tarkistettava.
Yksi refaktoroinnin säännöistä YAGNI, se on lyhenne sanoista "You Aren't Gonna't Need It" (Et tarvitse sitä), ja se juontaa juurensa sanoista eXtreme-ohjelmointi (XP) käytetään pääasiassa Ketterä ohjelmistokehitys joukkueet. Pitkä tarina lyhyesti, YAGNI sanoo, että vain ajantasaisia asioita pitäisi tehdä. Tämä tarkoittaa periaatteessa sitä, että vaikka jotakin asiaa voitaisiin tarvita tulevaisuudessa, sitä ei pitäisi tehdä juuri nyt. Emme kuitenkaan voi myöskään murskata uusia laajennuksia, ja tässä kohtaa modulaarisuus tulee tärkeäksi.
Kun puhutaan refaktorointion mainittava yksi olennaisimmista tekijöistä eli testit. Osoitteessa refaktorointi, meidän on tiedettävä, että koodi toimii edelleen, koska refaktorointi ei muuta sen toimintaa vaan sen rakennetta, joten kaikki testit on läpäistävä. Testit on parasta suorittaa sille koodin osalle, jonka parissa työskentelemme, jokaisen pienen muutoksen jälkeen. Näin saamme varmistuksen siitä, että kaikki toimii niin kuin pitääkin, ja se lyhentää koko toimenpiteeseen kuluvaa aikaa. Tästä Martin puhuu kirjassaan - aja testit niin usein kuin mahdollista, jotta et joutuisi ottamaan askelta taaksepäin ja tuhlaamaan aikaa etsimällä muunnosta, joka rikkoi jotain.
Koodin uudelleenkäsittely ilman testausta on tuskallista, ja on suuri mahdollisuus, että jokin menee pieleen. Jos se on mahdollista, olisi parasta lisätä ainakin joitakin perustestejä, jotka antavat meille hieman varmuutta siitä, että koodi toimii.
Alla luetellut muunnokset ovat vain esimerkkejä, mutta ne ovat todella hyödyllisiä päivittäisessä ohjelmoinnissa:
- Funktioiden ja muuttujien poisto - jos funktio on liian pitkä, tarkista, onko olemassa pienempiä funktioita, jotka voitaisiin poistaa. Sama koskee pitkiä rivejä. Nämä muunnokset voivat auttaa löytämään koodista päällekkäisyyksiä. Pienten funktioiden ansiosta koodista tulee selkeämpää ja ymmärrettävämpää,
- Funktioiden ja muuttujien uudelleennimeäminen - oikean nimeämiskäytännön käyttäminen on olennaisen tärkeää hyvän ohjelmoinnin kannalta. Muuttujien nimet voivat hyvin valittuna kertoa paljon koodista,
- Toimintojen ryhmittely luokkaan - tämä muutos on hyödyllinen silloin, kun kaksi luokkaa suorittaa samanlaisia toimintoja, sillä se voi lyhentää luokan pituutta,
- Sisäänrakennetun lausekkeen ohittaminen - jos ehto tarkistetaan erityistapauksessa, anna palautuslauseke, kun ehto toteutuu. Tämäntyyppisiä testejä kutsutaan usein varoituslausekkeeksi. Sisäkkäisen ehdollisen lausekkeen korvaaminen poistumislausekkeella muuttaa koodin painotusta. If-else-konstruktiossa molemmille vaihtoehdoille annetaan yhtä suuri painoarvo. Koodia lukevalle henkilölle se on viesti siitä, että kumpikin on yhtä todennäköinen ja tärkeä,
- Erikoistapauksen esittely - jos käytät joitakin ehtoja koodissasi useita kertoja, voi olla syytä luoda niille erillinen rakenne. Näin ollen useimmat erikoistapausten tarkistukset voidaan korvata yksinkertaisilla funktiokutsuilla. Usein yleinen arvo, joka vaatii erityiskäsittelyä, on null. Siksi tätä mallia kutsutaan usein nollakohteeksi. Tätä lähestymistapaa voidaan kuitenkin käyttää missä tahansa erikoistapauksessa,
- Ehdollisen käskyn polymorfismin korvaaminen.
Esimerkki
Tämä on artikkeli aiheesta refaktorointi ja tarvitaan esimerkki. Haluan näyttää alla yksinkertaisen refaktorointinäytteen, jossa käytetään työkalua Sisäänrakennetun lausekkeen ohittaminen ja Ehdollisen käskyn polymorfismin korvaaminen. Oletetaan, että meillä on ohjelmatoiminto, joka palauttaa hash-tiedoston, jossa on tietoa siitä, miten kasveja kastellaan tosielämässä. Tällainen tieto olisi luultavasti mallissa, mutta tässä esimerkissä se on funktiossa.
def watering_info(kasvi)
result = {}
if plant.is_a? Suculent || plant.is_a? Kaktus
result = { water_amount: ", how_to: "Alhaalta", watering_duration: "2 weeks" }
elsif plant.is_a? Alocasia || plant.is_a? Maranta
result = { water_amount: "Big amount", how_to: "As you prefer", watering_duration: "5 päivää" }
elsif plant.is_a? Peperomia
result = { water_amount: "Dicent amount",
how_to: "Alhaalta! ne eivät pidä vedestä lehdillä",
watering_duration: "1 week" }
else
result = { water_amount: "Dicent amount",
how_to: "As you prefer",
watering_duration: "1 week"
}
end
return result
end
Ajatuksena on muuttaa, jos palata:
if plant.isa? Suculent || plant.isa? Cactus
result = { wateramount: ", howto: "Alhaalta",
Osoitteeseen
return { water_amount: ", how_to: "Alhaalta",watering_duration: "2 weeks" } if plant.is_a? Suculent || plant.is_a? Kaktus
return { vesimäärä: "Vähän" , mitento: "Alhaalta", kastelukesto: on: "2 viikkoa" } if plant.isa? Suculent || plant.is_a? Kaktus
Ja niin edelleen, kunnes saamme aikaan funktion, joka näyttää tältä:
def watering_info(kasvi)
return result = { wateramount: ", howto: "Alhaalta", wateringduration: "2 weeks" } if plant.isa? Suculent || plant.is_a? Kaktus
return result = { wateramount: "Big amount", howto: "As you prefer", wateringduration: "5 days" } if plant.isa? Alocasia || plant.is_a? Maranta
return result = { water_amount: "Dicent amount",
howto: "Alhaalta! ne eivät pidä vedestä lehdillä",
wateringduration: "1 week" } if plant.is_a? Peperomia
return result = { water_amount: "Dicent amount",
how_to: "As you prefer",
kastelun_kesto: "1 viikko"
}
end
Aivan lopussa meillä oli jo palautustulos. Ja hyvä tapa on tehdä tämä vaihe vaiheelta ja testata jokainen muutos. Voisit korvata tämän if-lohkon switch-tapauksella, ja se näyttäisi heti paremmalta, eikä sinun tarvitsisi tarkistaa kaikkia if-lohkoja joka kerta. Se näyttäisi tältä:
def watering_info(kasvi)
swich plant.class.to_string
case Sukkulentti, Kaktus
{ wateramount: "A little bit " , howto: "Alhaalta", watering_duration: "2 weeks" }
case Alocasia, Maranta
{ wateramount: "Big amount", howto: "As you prefer", watering_duration: "5 days" }
case Peperomia
{ water_amount: "Dicent amount",
how_to: "Alhaalta! ne eivät pidä vedestä lehdillä",
kastelun_kesto: "1 viikko" }
else
{ water_amount: "Dicent amount",
how_to: "Miten haluat",
kastelun_kesto: "1 week" }
end
end
Ja sitten voit soveltaa Ehdollisen käskyn korvaaminen polymorfismilla. Tämän tarkoituksena on luoda luokka, jossa on funktio, joka palauttaa oikean arvon ja vaihtaa ne oikeisiin paikkoihinsa.
luokka Suculent
...
def watering_info()
return { wateramount: ", howto: "Alhaalta", watering_duration: "2 weeks" }
end
end
luokka Kaktus
...
def watering_info()
return { wateramount: ", howto: "Alhaalta", watering_duration: "2 weeks" }
end
end
luokka Alocasia
...
def watering_info
return { wateramount: "Big amount", howto: "As you prefer", watering_duration: "5 days" }
end
end
luokka Maranta
...
def watering_info
return { wateramount: "Big amount", howto: "As you prefer", watering_duration: "5 days" }
end
end
luokka Peperomia
...
def watering_info
return { water_amount: ,
how_to: "Alhaalta! ne eivät pidä vedestä lehdillä",
kastelun_kesto: "1 viikko" }
end
end
luokka Kasvi
...
def watering_info
return { water_amount: ,
how_to: "As you prefer",
kastelun_kesto: "1 week" }
end
end
Ja pääkastelu_infofunktiossa koodi näyttää tältä:
def watering_info(kasvi)
plant.map(&:watering_info)
end
Tämä toiminto voidaan tietenkin poistaa ja korvata sen sisällöllä. Tämän esimerkin avulla halusin esitellä yleisen refaktorointimalli.
Yhteenveto
Refaktorointi on suuri aihe. Toivottavasti tämä artikkeli kannusti lukemaan lisää. Nämä refaktorointitaidot auttaa sinua löytämään virheet ja parantamaan puhdasta koodia. Suosittelen lukemaan Martinin kirjan (Improving the Design of Existing Code), joka on melko perustavanlaatuinen ja hyödyllinen kokoelma sääntöjä, jotka koskevat refaktorointi. Kirjoittaja näyttää erilaisia muunnoksia askel askeleelta täydellisen selityksen ja motivaation kanssa sekä vinkkejä siitä, miten välttää virheitä. refaktorointi. Monipuolisuutensa ansiosta se on ihastuttava kirja frontend- ja backend-kehittäjät.
Lue lisää
GraphQL Ruby. Entä suorituskyky?