Zabalit kód
Aktuální verze stránky ještě nebyla zkontrolována zkušenými přispěvateli a může se výrazně lišit od
verze recenzované 17. února 2021; kontroly vyžadují
7 úprav .
Pachový kód ( odor code , zapáchající kód anglicky code zápach ) je označení pro kód se znaky (pachy) problémů v systému. Zavedl jej Kent Beck [1] a použil Martin Fowler ve své knize Refaktoring. Vylepšení stávajícího kódu [1] .
Vůně kódu jsou klíčovými znaky potřeby refaktorizace [2] . Existují pachy specifické jak pro programovací paradigmata , tak pro specifické jazyky . Hlavním problémem, s nímž se vývojáři potýkají s pachy kódu, je to, že kritéria pro včasnost refaktoringu nelze jasně formalizovat, aniž by apelovali na estetiku a konvenční smysl pro krásu. Kódové pachy nejsou souborem jasných pravidel, ale popisem míst, kterým je třeba věnovat pozornost při refaktorování [3] . Jsou snadno detekovatelné, ale ne ve všech případech indikují problémy [1] .
Pachový kód vede k rozbití kódu, vývojáři by se měli snažit pachy eliminovat aplikací jednoho nebo více refaktorů [4] . Proces refaktoringu odstraňuje pachy kódu, což umožňuje aplikaci pokračovat ve vývoji stejnou nebo vyšší rychlostí. Nedostatek pravidelného refaktorování může projekt v průběhu času zcela paralyzovat, takže pachy kódu je třeba eliminovat brzy [2] . Existují nástroje k nalezení a opravě pachů kódu [5] , ale zkušenosti ukazují, že žádná výsledková karta nemůže konkurovat lidské intuici založené na informacích [6] .
Kód voní
Duplikace kódu
Duplikace kódu je použití stejných struktur kódu na více místech. Kombinací těchto struktur se zlepší programový kód [6] .
Příklady duplicit a způsoby jejich odstranění:
- Stejný výraz je přítomen ve dvou metodách stejné třídy: musíte použít "Extract Method" a volat kód vytvořené metody z obou bodů;
- Stejný výraz existuje ve dvou podtřídách na stejné úrovni: musíte použít metodu extraktu na obě třídy a následně metodu Pull Up Field nebo Form Template Method , pokud je kód podobný, ale není úplně stejný. Pokud obě metody provádějí totéž pomocí různých algoritmů, můžete si vybrat ten, který je z těchto algoritmů přehlednější, a použít „Algoritmus substituce“ (Substitute Algorithm);
- Duplicitní kód je ve dvou různých třídách: musíte použít Extract Class v jedné třídě a pak použít novou komponentu v jiné [6] .
Long Method
Mezi objektovými programy žijí nejdéle programy s krátkými metodami . Čím delší je procedura, tím je obtížnější ji pochopit. Pokud má metoda dobré jméno, nemusíte se dívat na její tělo [3] .
Měla by se dodržovat heuristika: pokud cítíte potřebu se k něčemu vyjádřit, musíte napsat metodu. Má smysl oddělit i jeden řádek do metody, pokud to potřebuje objasnění [7] .
- Pro redukci metody stačí použít metodu extraktu;
- Pokud místní proměnné a parametry brání extrakci metody, můžete použít Nahradit teplotu dotazem, Zavést parametrický objekt a Zachovat celý objekt [3] ;
- Podmíněné příkazy a smyčky naznačují možnost oddělení do samostatné metody. Decompose Conditional je vhodný pro práci s podmíněnými výrazy. Pro práci s cyklem - "Metoda vytahování" (Metoda vytahování) [7] .
Velká třída
Když třída implementuje příliš mnoho funkcí, zvažte podtřídu některého kódu. To vývojářům ušetří nadměrné množství atributů, které třída má, a duplikování kódu [7] .
- Chcete-li snížit třídu, použijte Extract Class nebo Extract Subclass. Zároveň je třeba věnovat pozornost shodnosti názvů atributů a tomu, zda je třída používá všechny současně [3] ;
- Pokud je velká třída třídou GUI , možná budete chtít přesunout její data a chování do samostatného objektu domény. Může však být nutné ukládat kopie některých dat na dvě místa a zajistit jejich konzistenci. Duplicate Observed Data naznačuje způsob, jak toho lze dosáhnout [8] .
Dlouhý seznam možností
Dlouhé seznamy parametrů jsou obtížně srozumitelné, nekonzistentní a obtížně použitelné. Použití objektů umožňuje v případě změn v přenášených datech upravit pouze samotný objekt. Při práci s objekty byste měli předat právě tolik, aby metoda mohla získat data, která potřebuje [8] .
- "Nahradit parametr metodou" se používá, když můžete získat data voláním metody na objektu. Tímto objektem může být pole nebo jiný parametr.
- Zachovat celý objekt umožňuje převzít skupinu dat přijatých z objektu a nahradit ji samotným objektem.
- "Introduce Parameter Object" se používá, pokud existuje několik datových prvků bez logického objektu [8] .
Divergentní modifikace
Problém nastává, když při úpravě systému nelze vyčlenit konkrétní místo, které je potřeba změnit. Je to důsledek špatné softwarové struktury [8] nebo programování copy-paste .
- Pokud je třeba změnit sadu metod pokaždé, když jsou v kódu provedeny určité úpravy, použije se třída extraktu (například tři metody se změní pokaždé, když je připojena nová databáze , a čtyři, když je přidán finanční nástroj) [3 ] .
Střelba z brokovnice
Jakákoli úprava zahrnuje mnoho malých změn velkého počtu tříd. Brokovnice je podobná Divergent Modification, ale je jejím opakem. K divergentní modifikaci dochází, když existuje jedna třída, která provádí mnoho různých změn, zatímco Shotgun je jedna změna, která ovlivňuje mnoho tříd [9] .
- Přesunutí všech změn do jedné třídy umožní „Metodu přesunu“ (Metoda přesunu) a „Přesunout pole“ (Přesunout pole);
- Pokud neexistuje žádná vhodná třída, měla by být vytvořena nová třída;
- V případě potřeby použijte Inline Class [3] .
Funkce závisti
Metoda přistupuje k datům jiného objektu častěji než k vlastním datům [3] .
- "Metoda přesunu" se používá, pokud je třeba metodu explicitně přesunout na jiné místo;
- Extrahovat metodu se vztahuje na část metody pouze v případě, že tato část přistupuje k datům jiného objektu;
- Metoda využívá funkce několika tříd: určí se, která třída obsahuje nejvíce dat, a metoda se do třídy umístí spolu s těmito daty, nebo se metodou Extract Method rozdělí na několik částí a ty se umístí do různá místa [10] .
Základním pravidlem je, že věci, které se mění ve stejnou dobu, by měly být uloženy na jednom místě. Data a funkce, které tato data využívají, se obvykle mění společně, existují však výjimky [10] .
Datové skupiny
Skupiny dat, které se vyskytují společně, by měly být převedeny do samostatné třídy [10] .
- "Metoda extrahování" se používá pro pole;
- "Introduce Parameter Object" nebo "Preserve Whole Object" pro parametry metody [11] .
Dobrým testem je odstranit jednu z datových hodnot a zjistit, zda ostatní stále dávají smysl. Pokud ne, je to jasné znamení, že data žádají o sloučení do objektu [10] .
Posedlost elementárními typy
Problém souvisí s používáním elementárních typů místo malých objektů pro malé úkoly, jako je měna, rozsahy, speciální řetězce pro telefonní čísla atd.
- "Nahradit datovou hodnotu objektem";
- "Nahrazení pole objektem" (Nahradit pole objektem);
- Pokud se jedná o typový kód, použijte Nahradit typový kód třídou, Nahradit typový kód podtřídami nebo Nahradit typový kód stavem/strategií) [3] .
switch příkazy
Jedním zjevným znakem objektově orientovaného kódu je relativně vzácné použití příkazů switch (nebo case) . Často stejný blok přepínačů skončí rozptýlený na různých místech v programu. Při přidávání nové možnosti musíte vyhledat všechny tyto bloky přepínačů a upravit je. Zpravidla, když si všimnete bloku přepínače, měli byste přemýšlet o polymorfismu [12] .
- Pokud se přepínač přepíná podle typového kódu, měli byste použít "Nahradit typový kód podtřídami" nebo "Nahradit typový kód stavem/strategií";
- Možná budete muset "Extract Method" a "Move Method" izolovat přepínač a umístit jej do správné třídy;
- Po nastavení struktury dědičnosti byste měli použít Nahradit podmíněné polymorfismem [3] .
Paralelní hierarchie dědičnosti
V kódu s tímto zápachem pokaždé, když podtřídíte jednu z tříd, musíte vytvořit podtřídu jiné třídy [12] .
- Běžnou strategií deduplikace je přimět instance jedné hierarchie odkazovat na instance jiné hierarchie a poté hierarchii v odkazující třídě odstranit pomocí metody Přesunout a Přesunout pole [12] .
Líná třída
Třída, jejíž náklady na existenci nejsou pokryty funkcemi, které vykonává, by měla být odstraněna [12] .
- Pokud existují podtřídy s nedostatečnou funkčností, zkuste Collapse Hierarchy;
- Téměř nepotřebné součásti by měly být podrobeny třídě Inline [12] .
Teoretická obecnost
K tomuto případu dochází, když je v určité fázi života programu poskytnuta sada mechanismů, které mohou některé budoucí funkce potřebovat. V důsledku toho je program obtížnější pochopit a udržovat [13] .
- Pro nepoužívané abstraktní třídy použijte sbalit hierarchii;
- Zbytečné delegování lze odstranit pomocí Inline Class;
- Metody s nepoužitými parametry musí být podrobeny "Remove Parameter" [3] .
Časové pole
Dočasná pole jsou pole, která objekt potřebuje pouze za určitých okolností. Tento stav věcí je těžké pochopit, protože se očekává, že objekt bude potřebovat všechna svá pole [14] .
- Dočasná pole a veškerý kód, který s nimi pracuje, by měly být umístěny v samostatné třídě pomocí Extract Class;
- Podmíněně spustitelný kód můžete odstranit pomocí objektu Introduce Null Object k vytvoření alternativní komponenty [13] .
Řetězec hovorů
K řetězci volání dochází, když klient požaduje jiný objekt od jednoho objektu, jiný objekt požaduje jiný objekt atd. Takové sekvence volání znamenají, že klient je spojen s navigací ve struktuře třídy. Jakékoli změny mezičlánků znamenají nutnost úpravy klienta [13] .
- K odstranění řetězce volání se používá technika Hide Delegate [13] .
Zprostředkovatel
Nadměrné používání delegování může vést ke třídám, ve kterých se většina metod skládá pouze z volání metody jiné třídy [13] .
- Pokud třída deleguje většinu metod na jinou třídu, musíte použít "Remove Middle Man" [15] .
Chybně umístěná blízkost
„Nesprávná blízkost“ nastává, když jsou třídy častěji, než by měly být ponořeny do uzavřených částí jedna druhé [15] .
- "Nevhodné blízkosti" se můžete zbavit pomocí "Metoda přesunu" (Metoda přesunu) a "Přesunout pole" (Posunout pole);
- Pokud je to možné, měli byste se uchýlit k "Změnit obousměrné přidružení na jednosměrné", "Extrahovat třídu" nebo použít "Skrýt delegáta" [15] .
Alternativní třídy s různými rozhraními
Dvě třídy, ve kterých je část funkcionality společná, ale metody, které ji implementují, mají odlišné parametry [16] .
- Použijte "Metodu přejmenování" na všechny metody, které provádějí stejné akce, ale liší se v signaturách [15] .
Neúplnost třídy knihovny
Knihovny po čase přestanou splňovat požadavky uživatelů. Přirozeným řešením je změnit některé věci v knihovnách, ale neměnit třídy knihoven. Měli byste používat metody refaktorování speciálně navržené pro tento účel [16] .
- Pokud potřebujete přidat několik metod, použijte "Introduce Foreign Method";
- Pokud potřebujete vážně změnit chování třídy, použijte "Introduce Local Extension" (Introduce Local Extension) [16] .
Datové třídy
Datové třídy jsou třídy, které obsahují pouze pole a metody pro přístup k nim, jsou to jednoduše kontejnery pro data používaná jinými třídami [16] .
- Použít Encapsulate Field a Encapsulate Collection [3] .
Zřeknutí se dědictví
Pokud dítě používá jen malou část zděděných metod a vlastností rodiče, je to známka špatné hierarchie.
- Musíte vytvořit novou třídu na stejné úrovni jako dítě a pomocí metody Push Down a Push Down Field do ní vložit všechny nečinné metody. Tím je zajištěno, že nadřazená třída obsahuje pouze to, co je sdíleno [17] .
Komentáře
Často komentáře hrají roli „deodorantu“ kódu, který se v něm objevuje jen proto, že je kód špatný. Když cítíte potřebu napsat komentář, zkuste restrukturalizovat svůj kód tak, aby se všechny komentáře staly nadbytečnými [17] .
- Pokud stále potřebujete komentář k vysvětlení akcí bloku, zkuste použít metodu extrahování;
- Pokud je metoda již zvýrazněna, ale stále potřebujete komentář k vysvětlení její operace, použijte Rename Method;
- Pokud chcete uvést nějaká pravidla o požadovaném stavu systému, použijte Úvodní tvrzení [17] .
Viz také
- Antipattern
- Kategorie:Principy programování
- Nástroje pro analýzu statického kódu
Poznámky
- ↑ 1 2 3 Martin, 1999 .
- ↑ 1 2 Vigorous Hive_CodeSmell .
- ↑ 1 2 3 4 5 6 7 8 9 10 11 Zapáchající kód .
- ↑ Counsell_Code Smells, 2010 .
- ↑ devconf .
- ↑ 1 2 3 Martin Fowler_Refactoring, 2003 , str. 54.
- ↑ 1 2 3 Martin Fowler_Refactoring, 2003 , str. 55.
- ↑ 1 2 3 4 Martin Fowler_Refactoring, 2003 , str. 56.
- ↑ Martin Fowler_Refactoring, 2003 , str. 56-57.
- ↑ 1 2 3 4 Martin Fowler_Refactoring, 2003 , str. 57.
- ↑ Páchnoucí kód , str. 57.
- ↑ 1 2 3 4 5 Martin Fowler_Refactoring, 2003 , str. 58.
- ↑ 1 2 3 4 5 Martin Fowler_Refactoring, 2003 , str. 59.
- ↑ Dočasné pole .
- ↑ 1 2 3 4 Martin Fowler_Refactoring, 2003 , str. 60.
- ↑ 1 2 3 4 Refaktorování kódu .
- ↑ 1 2 3 Martin Fowler_Refactoring, 2003 , str. 61.
Literatura
- Fowler, M. Kapitola 3. Páchnoucí kód // Refaktoring. Zlepšení stávajícího kódu = Refaktoring: Zlepšení návrhu stávajícího kódu / Per. z angličtiny. S. Makkaveeva. - 1. vyd. - Petrohrad. : Symbol-Plus, 2003. - S. 54-62. - 432 s. — ISBN 5-93286-045-6 .
- Mantyla MV, Vanhanen J., Lassenius C. Bad vůně-lidé jako kritici kódu (anglicky) // Software Maintenance, 2004. Proceedings. 20. mezinárodní konference IEEE na téma: časopis. - 2004. - S. 399-408 . — ISSN 1063-6773 . Archivováno z originálu 1. srpna 2014.
Odkazy
- Dočasné pole . codingcraft.ru Staženo: 5. listopadu 2013. (neurčitý)
- CodeSmell (anglicky) . Martinfowler.com. Staženo: 13. října 2013.
- Code Smell (anglicky) . Společnost Cunningham & Cunningham Inc. (c2.com). Staženo: 23. listopadu 2013.