refaktorálás: a külsőleg megfigyelhető viselkedés megtartásával a szoftver belső struktúrájában végrehajtott olyan változtatás, amely által a szoftver kódja könnyebben érthetővé és olcsóbban módosíthatóvá válik
refaktorálni: szoftvert átstruktúrálni a külsőleg megfigyelhető viselkedés módosítása nélkül!
mikor érdemes refaktorálni?
új funkció hozzáadásakor, bug javításakor, kódszemle alkalmával
refaktorálás szabályai:
legyen alapos tesztkészlet (külső viselkedés nem változott e), kis lépésenként történjen, merjünk változtatni
Duplikált kód: ugyanaz vagy nagyon hasonló kód ismétlődik több helyen
refaktorálás: külön függvénybe/osztályba kiemelés
Hosszú metódus: függvény kódja túl hosszú: túl sok feltételes ág illetve ciklus
refaktorálás: feldarabolás kommentek, feltétel elágazások szerint
Hosszú paraméterlista: a függvényne ktúl sok (háromnál több) paramétere van
refaktorálás: több függvényre bontás, paraméterek egy objektumba vonása
Nagy osztály: az osztálynak túl sok metódusa van (SRP és ISP sérül)
refaktorálás: több osztályra darabolás, ISP használata, öröklési hierarchia készítése
Divergent change: technológiánként más és más osztály
refaktorálás: közös részek stabil absztrakt csomagba szervezése
Shotgun surgery: egy változtatás sok más osztályban apró változtatásokat indukál (pl konstansok beégetésekor, DRY sérül)
refaktorálás: ezek elnevezése, egy helyre gyűjtése, akár erőforrás fájlba kiszervezése (így többnyelvűség támogatása pl)
Feature envy: egy osztály túlságosan érdeklődik egy másik iránt (túl nagy a csatolás köztük)
refaktorálás: szerverből átrakjuk a gyakran hívott függvényeket a kliensbe (nagy kohézió, kis csatolás)
Data clumps: ugyanaz a paramétercsoport ismétlődik több metódushíváson keresztül
refaktorálás: nem OO alapon terveztünk, ezeket osztály mezőibe építsük be
Primitive obsession: adatok primitív típusokban vannak tárolva osztályok helyett
refaktorálás: nem OO alapon terveztünk, ezeket szervezzük osztályokba (akár öröklést is bevethetünk)
Switch statements: túl sok elágazás (sok if-else, null ellenőrzés, nagy switch)
refakotorálás: polimorf viselkedés, Null Object tervezési minta
Öröklési hirearchiák: ha egy osztályból új leszármazott készül, akkor egy másikból is kell leszármazottat készíteni (shotgun surgery egy példája)
refaktorálás: egy osztályba vonjuk
Lusta osztály (lazy class): az osztály túl kevés dolgot csinál
refaktorálás: az ilyen osztályt érdemes törölni
Spekulatív általánosság: az osztály feleslegesen túl nehézsúlyú (túl bonyolult dolgokra készültünk, YAGNI elv sértése)
refaktorálás: elimináljuk a felesleges dolgokat
Temporarí field (ideiglenes mező): egy attribútum csak bizonyos esetekben van használva (pl globális változók, alacsony osztályon belüli kohézió, objektum egy szálon használható csak)
refaktorálás: külön osztályba szervezzük ki ezeket (így nagy lesz a kohéziója)
Message chains: hosszú metódushívási láncok (demeter törvényt sérti (LoD))
refaktorálás: függvények osztályok közti átmozgatása (felelősségek újragondolása), lánc maradékát delegáló függvénybe rejtjük (csak közvetlen szomszédokat ismerik, de elszaporodhatnak a delegálók)
Middle man: túl sok delegálás egy másik osztály felé (az adott osztálynak csak közvetítő szerepe van)
refaktorálás: ezen osztály eliminálása, hívjuk közvetlenül a célosztályt
Inappropriate intimacy: egy másik osztály privát (nempublikus) tagjainak közvetlen elérése (egységbezárás sérül, magas lesz a csatolás)
refaktorálás: felelősségek újragondolása, metódusok átrendezése a két osztály közt
Alternative classes with different interfaces: ugyanarra a feladatra különböző interfészű osztályok
refaktorálás: egyes függvények átnevezése, közös interfészre jutás (Bridge tervezési minta hasznos)
Incomplete library class: egy felhasznált könyvtárbeli osztályt nem tudunk módosítani
refaktorálás: könyvtárbeli osztályt saját osztályba csomagoljuk, delegálással új funkciót adunk neki
Data class: egy osztály csak adatokat tárol
refaktoráls: nem OO módon terveztünk, vigyünk felelősségeket az adatosztályba
Refused bequest (elutasított örökség): egy leszármazottnak nincs szüksége az ős viselkedésére (ősben definiált viselkedés túl magasra került a hierarchiában, vagy üresen definiálja felül a leszármazott az ős metódusát (LSP megsértése), gyerekben egyáltalán nem releváns az ős interfésze)
refaktorálás: függvényt és hozzátartozó attribútumokat vigyük lejjebb az öröklési hierarchiában, vagy átrendezzük az öröklési hierarchiát (ős és leszármazott felcserélése), vagy öröklődés újragondolása (esetleg delegálással helyettesítjük)
Kommentek: túl sok magyarázó komment a kódban
refaktorálás: miért csinálja azt amit (ne azt írja le, hogy MIT csinál hanem hogy HOGYAN)
Downcasting: típuskasztolás és típusellenőrzés (nem használjuk ki a polimorfizmust, OCP sérül, TDA-t is sérthetjük)
Extract class: osztály néhány metódusából és mezőjéből egy másik osztályt képzünk
Inline class: egy osztályt készítünk több osztályból (extract inverze)
Hide delegate: távoli objektumhoz intézett hívást delegációval intézünk
Remove middle man: delegációt egy direkt hívásra cseréljük le
Introduce foraign method: kliens osztályban új metódust készítünk, aminek a szerver paramétere (kliensből, a szerver által nem támogatott funkció adása a szervernek)
Introduce local extension: szerver bővítése leszármazott létrehozásával
Self encapsulate field: mezőt getter-setter metódusokba vagy property-be csomagolunk
Replace data value with object: egyszerű primitív adatokat tároló változók helyett osztály bevezetése
Change value to reference: értékegyenlőség helyett referenciaegyenlőséget vezet be
Change reference to value: referenciaegyenlőség helyett értékegyenlőséget vezet be
Replace array with object: tömb helyett osztály használata az összetartozó elemek csoportosítására
Duplicate observed data: GUI-ban ne tároljunk a modell számára fontos adatokat (GUI függjön a modelltől és ne fordítva)
Change unidirectional association to bidirectional: egyirányú asszociáció helyett kétirányú asszociáció
Changed bidirectional association to unidirectional: kétirányú asszociáció helyett egyirányú asszociáció
Replace magic numbers with symbolic constant: kódban szétszórt számok és string iterálok helyett nevesített konstansok használata
Encapsulate field: nem privát attribútumból privát készítése, és getter-setter vagy property készítése hozzá
Encapsulate collection: gyűjtemény típusú attribútum elrejtése, kifele csak olvashatóvá tétel, módosítás függvényeken keresztül
Replace record with data class: nem OO könyvtárhoz csatlakozás (rekordok helyett adat osztályok használata)
Replace type code with class: típusok intként vagy enumként tárolása helyett osztályokat használjunk
Replace type code with subclasses típusok intként vagy enumként tárolása helyett osztályokat és öröklődést is használjunk
Replace type code with state/strategy: objektum dinamikus viselkedésének kiszervezése state vagy strategy mintával
Replace subclass with fields: ha a leszármazottak semmi hasznosat nem csinálnak, így mezővel helyettesíthetőek
Decompose conditional: feltételes elágazások ágainak külön függvényként reprezentálása
Consolidate conditional expression: egy feltétel többszöri ellenőrzése helyett egyszer legyen kiértékelve és letesztelve
Consolidate duplicate conditional fragments: egy részkifejezés többszöri ellenőrzése helyett egyszer legyen kiértékelve és letesztelve
Remove control flag: kilépést jelző változó break vagy return utasításra
Replace nested conditional with guard clauses: egymásba ágyazott feltételek helyett lapos feltételsorozat (egymás utáni if-ek inkább)
Replace conditional with polymorphism: típusellenőrzés helyettesítése polimorfizmussal
Introduce null object: ne null értékeket tároljunk, hanem Null Object mintát
Introduce assertion: feltételellenőrzés a kód egy adott pontján, ami debug módban hibát dob ha a feltétel sérül (debuggolásra)
Rename method: függvény találóbb névre nevezése
Add parameter: új paraméter a függvénynek
Remove paramtere: nem használt paraméter törlése
Separate query from modifier: 2 metódus készítése, egy lekérdezésre, egy módosításra
Parametrize method: két nagyon hasonló függvény kombinálása eggyé
Replace parameter with explicit methods: egy függvényből több függvény készítése
Preserve whole object: teljes objektum átadása paraméterként, nem csak bizonyos részeit
Replace parameter with method: nem egy metódushívás eredményét adjuk át paraméterként, hanem hagyjuk, hogy ezt a hívást a függvény saját maga intézze el
Introduce parameter object: sok csoportosult paraméter helyettesítése önálló osztállyal
Remove setting method: attribútumok értékét konstruktorban állítjuk be, settereket nem bzitosítunk
Hide method: senki által nem használt publikus függvényt tegyük priváttá
Replace constructor with factory method: objektum létrehozása és inicializálása bonyolultabb egy egyszerű konstruktor hívásnál
Encapsulate downcast: metódus eredményét a klienseknek folyton át kell cast-olniuk, akkor ezt a típus kasztolást tegyük át a metódusba és a metódus térjen vissza a helyes típussal
Replace error code with exception: hibakód és speciális visszatérés helyett használjunk kivételeket
Replace exception with test: kivételek elkapása helyett ellenőrizzük a beadott paramétereket
Pull up field: leszármazottakban levő közös attribútumokat a közös ősbe visszük át
Pull up method: leszármazottakban levő közös metódusokat a közös ősbe visszük át
Pull up constructor body: leszármazottak konstruktorainak közös részeit viszik fel a közös ős konstruktorába
Push down method: a csak a leszármazottak egy részére érvényes metódust lejjebb visszük az öröklési hierarchiában
Push down field: a csak a leszármazottak egy részére érvényes mezőt lejjebb visszük az öröklési hierarchiában
Extract subclass: azokat a viselkedéseket amik csak a leszármazottak egy részére érvényesek, egy önálló osztályba visszük ki, az eredeti leszármazottak tőle fognak mostantól leszármazni
Extract superclass: ha néhány leszármazott egy közös viselkedéssel rendelkezik, ezt a viselkedést egy önálló közös ősbe lehet kiszervezni
Extract interface: néhány osztály publikus interfészében vannak közös részek, akkor az a közös halmaz egy közös interfészbe kiszervezhető
Collapse hierarchy: ha egy leszármazott osztály nem sokat ad az ős viselkedéséhez, akkor azt összevonjuk az őssel
Form template method: ha néhány osztály hasonló metódusokat tartalmaz hasonló lépésekkel azonos sorrendben, akkor a template method mintával vigyük fel őket az ősbe
Replace inheritance with delegation: ha egy leszármazottnak nem minden ősből örökölt dologra van szüksége, akkor használjunk inkább delegációt
Replace delegation with inheritance: ha egy osztály csak delegál egy hasonló viselkedésű osztályhoz, akkor használjuk inkább öröklődést
Tease apart inheritance: ha egy öröklési hierarchia 2 dolgot csinál egyszerre, vágjuk 2 részre
Convert procedural design to objects: adatosztályokhoz felelősségeket (metódusokat) rendelünk
Separate domain from presentation: üzleti logika kivétele a GUI-ból, hozzunk létre önálló csak GUI-val foglalkozó osztályokat
Extract hierarchy: bonyolult osztály feldarabolása komplex öröklési hierarchiára