Kihagyás

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)