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í

Obecné zavání objektově orientovaným kódem

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. 1 2 3 Martin, 1999 .
  2. 1 2 Vigorous Hive_CodeSmell .
  3. 1 2 3 4 5 6 7 8 9 10 11 Zapáchající kód .
  4. Counsell_Code Smells, 2010 .
  5. devconf .
  6. 1 2 3 Martin Fowler_Refactoring, 2003 , str. 54.
  7. 1 2 3 Martin Fowler_Refactoring, 2003 , str. 55.
  8. 1 2 3 4 Martin Fowler_Refactoring, 2003 , str. 56.
  9. Martin Fowler_Refactoring, 2003 , str. 56-57.
  10. 1 2 3 4 Martin Fowler_Refactoring, 2003 , str. 57.
  11. Páchnoucí kód , str. 57.
  12. 1 2 3 4 5 Martin Fowler_Refactoring, 2003 , str. 58.
  13. 1 2 3 4 5 Martin Fowler_Refactoring, 2003 , str. 59.
  14. Dočasné pole .
  15. 1 2 3 4 Martin Fowler_Refactoring, 2003 , str. 60.
  16. 1 2 3 4 Refaktorování kódu .
  17. 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.
  • CodeSmell  (anglicky) . Martinfowler.com. Staženo: 13. října 2013.
  • Code Smell  (anglicky) . Společnost Cunningham & Cunningham Inc. (c2.com). Staženo: 23. listopadu 2013.