Kódrefaktorálás
1. Bevezetés¶
A kódrefaktorálás a meglévő számítógépes forráskód átalakításának folyamata – az elemek, összetevők (faktorok) megváltoztatása – a külső viselkedés módosulása nélkül. A refaktorálás célja a kód nem funkcionális tulajdonságainak (felépítésének, összetételének és/vagy implementációjának) javítása, miközben megőrzi a szoftver funkcionalitását. A kódrefaktorálás potenciális előnyei közé tartozik, hogy javítja a kód olvashatóságát és csökkenti a bonyolultságát; így könnyebben karbantartható a forráskód, és egyszerűbb, letisztultabb vagy kifejezőbb belső architektúra vagy objektummodell hozható létre a bővíthetőség javítása érdekében.
Refaktorálás közben jellemzően szabványosított kisebb változtatások sorozatát (micro-refactoring) alkalmazzák, amelyek mindegyike (általában) a forráskód apró változtatását jelenti, amely megőrzi a szoftver viselkedését, vagy legalábbis nem változtatja meg a funkcionális követelményeknek való megfelelését. Számos telepítési környezet automatizált támogatást nyújt ezen kis változtatások mechanikai aspektusainak végrehajtásához. Ha jól hajtják végre, akkor a kódrefaktorálás segíthet a szoftverfejlesztőknek a rendszerben nyugvó hibák vagy biztonsági rések felfedezésében és kijavításában, az alapjául szolgáló logika egyszerűsítése által, és a szükségtelen bonyolultsági szintek kiküszöbölésével. Ha rosszul van végrehajtva, akkor megváltoztathatja a szoftver funkcionalitását és/vagy újabb hibákat idézhet elő.
„A kód dizájnjának folyamatos javításával egyre egyszerűbbé és egyszerűbbé tesszük a vele való munkát. Ez éles ellentétben áll azzal, ami általában történik: kevés refaktorálás, és nagy hangsúly az új funkciók gyors implementációján. Ha ráérzel a folyamatos refaktorálás higiénikus szokására, rájössz, hogy sokkal könnyebb lesz bővíteni és karbantartani a kódot.”
2. Motiváció¶
A refaktorálásra általában akkor kerül sor, ha „gyanús kódot” (code smell) észlelnek. Például egy adott metódus túl hosszú, vagy nagyban hasonlít egy másikra.. Amint felismerték, ezeket a problémákat a forráskód refaktorálásával vagy újraírásával oldják meg, mely ugyanúgy viselkedik, de már nem gyanús.
Egy hosszabb metódusból egy vagy több kisebb szubrutint lehet kiemelni; duplikált rutinok esetén a másolat eltávolítható és helyettesíthető egy megosztott függvénnyel. A refaktorálás elmulasztása „technikai adósság” halmozódását eredményezheti; másrészről a refaktorálás a technikai adósság visszafizetésének egyik elsődleges eszköze.
3. Előnyök¶
A refaktorálás előnyeinek két általános kategóriája van.
- Karbantarthatóság. A hibák javítása könnyebb, ha a forráskód könnyen olvasható, és a szerző szándéka könnyen megragadható. Ezt úgy lehet elérni, hogy a nagyméretű monolitikus eljárásokat rövid, jól megnevezett, egycélú metódusok sorozatává redukálják. Az is segít, ha egy metódust egy megfelelőbb osztályba helyezünk, vagy eltávolítjuk a félrevezető megjegyzéseket.
- Bővíthetőség. Az alkalmazás funkcióit könnyebb kibővíteni, ha felismerhető tervezési mintákat használ, és bizonyos rugalmasságot biztosít olyan helyeken, ahol korábban nem létezett ilyen.
A teljesítménytervezés (performance engineering) képes megszüntetni a programok hatékonysági hiányosságait, az úgynevezett szoftverfelfúvódást (software bloat), amely a hagyományos szoftverfejlesztési stratégiákból ered (az alkalmazás fejlesztési idejének minimalizálása a futási idő helyett). A teljesítménytervezés a szoftvert a futtatásához szükséges hardverhez is igazíthatja, például a párhuzamos architektúrák kihasználása érdekében.
4. Kihívások¶
A refaktoráláshoz ki kell emelni a szoftverrendszer struktúráját, az adatmodelleket és az alkalmazáson belüli függőségeket, hogy tudomást szerezzünk a meglévő szoftverrendszer működéséről. A távozó csapattagok miatt a fejlesztőknek hiányos vagy pontatlan ismereteik vannak a rendszer jelenlegi állapotáról és a tervezési döntésekről. A kódmegújítási tevékenységek további erőfeszítéseket igényelhetnek ezen ismeretek visszanyerése érdekében. A refaktorálási tevékenységek architekturális módosításokat eredményeznek, amelyek rontják a szoftverrendszer szerkezeti felépítését, ez pedig befolyásolja például a karbantarthatóságot és az áttekinthetőséget, amelyek a szoftverrendszerek teljes újrafejlesztéséhez vezethetnek.
A kódrefaktoráló tevékenységeket szoftveres intelligencia biztosíthatja, amely eszközöket és technikákat használ, hogy adatokat szolgáltasson a kód algoritmusairól és szekvenciáiról. A szoftverrendszer felépítésének, az adatmodellek és az összetevőkön belüli függőségek belső állapotának áttekinthető formátumban való megjelenítése kritikus rész a magas szintű megértés kialakulásában, mivel ez alapján tudható meg, hogy mit kell módosítani, és hogyan.
5. Tesztelés¶
Az automatikus egységteszteket be kell állítani a refaktorálás előtt, hogy megbizonyosodjanak arról, hogy a rutinok továbbra is a várt eredményeket adják. Az egységtesztelés még nagymértékű refaktorálás esetén is stabilitást eredményezhet, ha a változtatásokat kis lépésekben végzik. Gyakori stratégia a több projektet átfogó refaktorálások esetén hogy az összes projektet egyetlen adattárban (repository) tárolják.
Az egységtesztek végrehajtása során a refaktorálás egy iteratív ciklus formáját ölti, amely során apró kódváltoztatásokat végeznek, teszteléssel megbizonyosodnak róla, hogy ez nem változtatta meg a viselkedést, majd folytatják a változtatásokat. Ha egy teszt bármely pontján kudarcot vall, akkor az utolsó apró változtatást visszavonják és más módon ismétlik meg. Ahhoz, hogy ez az iteratív folyamat praktikus legyen, a teszteket nagyon gyorsan kell lefuttatni, különben a programozók az idejük nagy részét a tesztek végrehajtására fordítanák. Az extrém programozás és más agilis szoftverfejlesztések támogatói ezt a tevékenységet a szoftverfejlesztési folyamat szerves részeként írják le.
6. Technikák¶
Íme néhány példa a mikro-refaktorokra; ezek közül néhány csak bizonyos nyelvekre vagy nyelvtípusokra vonatkozik. Hosszabb lista megtalálható Martin Fowler könyvében és a weboldalon. Számos fejlesztési környezet automatizált támogatást nyújt ezeknek a mikro-refaktoroknak. Például egy programozó rákattinthat egy változó nevére, majd a helyi menüből kiválaszthatja az „Encapsulate field” refaktoráló funkciót. A fejlesztői környezet ezután további részleteket kér, általában észszerű alapértelmezésekkel és a kódváltozások előnézetével. Miután a programozó megerősítette, elvégzi a szükséges változtatásokat a kód egészében.
- Technikák, amelyek lehetővé teszik a megértést
- Programfüggőségi gráf – az adatok és a vezérlőfüggőségek explicit ábrázolása
- Rendszerfüggési grafikon – a programfüggőségi gráfok közötti eljáráshívások ábrázolása
- Szoftverintelligencia – Segít megérteni az alkalmazáson belüli függőségeket
- További absztrakciót lehetővé tevő technikák
- Adatmező egységbe zárása – rákényszeríti a kódot, hogy a mezőt csak getter és setter metódusokkal lehessen elérni
- Típus általánosítása – általánosabb típusok létrehozása a további kódmegosztás érdekében
- Típusellenőrző kód cserélése állapotra/stratégiára
- Feltételek cserélése polimorfizmusra
- A kód logikusabb részekre bontása
- A kód felbontása újrafelhasználható szemantikai egységekre, amelyek tiszta, jól meghatározott, egyszerűen használható felületeket tartalmaznak
- Egy nagyobb osztály egy részének kiemelése és velük egy új osztály létrehozása
- Egy nagyobb metódus (vagy függvény) egy részének kiemelése és velük egy új metódus létrehozása
- Nevek és helyek javítására
- Metódusok vagy adatmezők áthelyezése egy megfelelőbb osztályba vagy forrásfájlba
- Metódusok vagy adatmezők neveinek megváltoztatása olyanra, amelyek jobban leírják a céljukat
- Pull up – áthelyezés szülőosztályba (objektumorientált programozásban)
- Push down – áthelyezés gyerekosztályba (objektumorientált programozásban)
- Kódduplikáció automatikus felismerése
7. Hardver-refaktorálás¶
Míg a refaktorálás kifejezés eredetileg kizárólag a szoftverkód átírására utalt, az utóbbi években a hardverleíró nyelveken (HDL) írt kódot is refaktorálták. A hardver-refaktorálás kifejezést rövidített kifejezésként használják a hardverleíró nyelveken történő refaktorálására. Mivel a hardvermérnökök többsége szerint a HDL nem tekinthető programozási nyelvnek a hardver-refaktorálásra egy külön területként tekintünk.
Az analóg hardverleírások (VHDL-AMS-ben) automatikus refaktorálását Zeng és Huss javasolta. Megközelítésük szerint a refaktorálás megőrzi a hardveres tervezés szimulált viselkedését. A nem funkcionális mérés az, hogy a refaktorált kód standard szintézises eszközökkel feldolgozható, az eredeti kód viszont nem. A digitális HDL-ek refaktorálását szintén a Synopsys munkatársa, Mike Keating vizsgálta. Célja, hogy a komplex rendszerek megértését könnyebbé tegye, ami növeli a tervezők produktivitását.
8. Története¶
Bár a refaktorálás informálisan évtizedek óta jelen volt, a szó (refactoring) legelőször 1990 szeptemberében jelent meg William Opdyke és Ralph Johnson cikkében. Megjegyzendő, hogy a factoring és a factoring out kifejezéseket a Forth közösségben már az 1980-as évek eleje óta ilyen értelemben használták. Leo Brodie Thinking Forth (1984) könyvének hatodik fejezetét a témának szentelték.
William Griswold 1991-es Ph.D. disszertációja az egyik első nagyobb tudományos munka a funkcionális és a procedurális programok refaktorálásáról. Opdyke 1992-es disszertációja az objektumorientált programok refaktorálásáról szólt, bár az elmélet és a technika már régóta elérhető volt program transzformációs rendszerekként. Mindezek az irományok áttekintést adnak a refaktorálás általános módszereiről.
Martin Fowler könyve, a Refactoring: Improving the Design of Existing Code referenciamunkának tekinthető.
9. Automatizált kódrefaktorálás¶
Számos szerkesztőnek és fejlesztői környezetnek van automatikus refaktorálás-támogatása. Lehetséges az alkalmazáskód és a tesztkód refaktorálása is. Alább néhány ilyen szerkesztő vagy úgynevezett refaktoráló böngésző:
- DMS szoftverfejlesztési eszközkészlet (nagyméretű refaktorálást valósít meg C, C ++, C #, COBOL, Java, PHP és más nyelvek számára)
- Eclipse alapú:
- Eclipse (Java, és kisebb mértékben C ++, PHP, Ruby és JavaScript)
- PyDev (Python)
- Photran (Fortran bővítmény az Eclipse IDE-hez)
- Embarcadero Delphi
- IntelliJ alapú:
- AppCode (Objektív-C, C és C ++)
- IntelliJ IDEA (Java)
- PyCharm (Python)
- WebStorm (JavaScript)
- Android Studio (Java)
- JDeveloper (Java)
- NetBeans (Java)
- Smalltalk: A legtöbb dialektus erős refaktoreszközöket tartalmaz. Sokan használják a 90-es évek elején Ralph Johnson által gyártott eredeti refaktorböngészőt.
- Visual Studio alapú:
- Visual Studio (NET és C ++)
- CodeRush (kiegészítő)
- Visual Assist (a Visual Studio kiegészítője a C # és C ++ refaktor támogatásával)
- Wing IDE (Python)
- X kód (C, Objective-C és Swift)
- Qt készítő (C ++, Objective-C és QML esetén)