pondělí 21. února 2011

Kapitální úlovek - pravidla kladená na metody

Kapitální úlovek - maximetoda

Dnes se mi podařilo objevit skutečného maxikapra. Plaval si ukrytý ve stojatých vodách našich objektů a snažil se tvářit nenápadně. Objevil jsem ho čistě náhodou při dohledávání jedné konstrukce. Posuďte sami, zda-li se jedná o vzácný kousek nebo se to ve Vašich projektech takovými chlapáky jenom hemží:

  • Délka metody: 1524 řádků
  • Počet vstupních argumentů: 12
  • Počet lokálních proměnných: více jak 100
  • Počet if konstrukcí: 235
  • Počet switch konstrukcí: 14

Chvilku jsem tento nechtěný úlovek rozdýchával a přemýšlel kolik doporučení a pravidel tato metoda nebohého objektu porušuje. Věřte mi, že hodně. Pojďme se na ně postupně podívat.

Malé metody a ještě menší

Metody by měly být v rozsahu pouze několika málo řádků. Rozumná horní hranice délky metody je 10 řádků. Delší metody ztrácí na přehlednosti a obvykle porušují pravidlo jedné věci - metoda toho dělá příliš mnoho.

V jedné metodě by měla být nejvýše jedna řídící struktura if, switch, while nebo podobná. V každé větvi takové struktury by pak měl být nejvýše jeden řádek, který je zřejmě opět voláním další metody nebo se jedná o přiřazení. Úroveň odsazení ve funkci je jedna maximálně dvě. Autor metody zde prokázal více než velkou oblíbenost if větvení.

Dělejte jen jednu věc

Každá metoda by měla dělat pouze jednu věc. Pokud jich dělá více, je to špatně. Obvykle pak název neodpovídá očekávané funkcionalitě metody a to už je pouze krůček k jejímu chybnému použití a vyvolání problémového aplikačního stavu.

Důležité je umět řešený problém rozložit na různé úrovně abstrakce. Pokud metoda řeší posloupnost kroků na stejné úrovni abstrakce, je to v pořádku a v našem chápání problému řeší pouze jednu věc. Pokud však zamíchá více úrovní abstrakce je to špatně.

Šetřete s argumenty

Jak tvrdí Robert C. Martin, ideální počet argumentů je 0 (12 argumentů si určitě ani nedokáže představit ;-). Tři a víc argumentů již obvykle indikují chybný návrh a měl by to pro Vás být impuls k refaktorování. Metoda pravděpodobně dělá více věcí najednou a míchá úrovně abstrakcí.

Zkušení vývojáři také varují před předáváním logických argumentů (bool hodnot). Obvykle jsou použity uvnitř metody pro rozhodování mezi dvěmi cestami zpracování. To samo o sobě porušuje pravidlo jedné věci. Vytvořte raději metody dvě a volejte v if konstrukci nadřízené úrovně abstrakce konkrétní metodu.

Pokud metoda přesto vyžaduje více argumentů než dva, zauvažujte o sloučení argumentů do objektu typu struktura, kterou pak předáte jako jeden argument.

Výstupní argumenty (ne návratové hodnoty) nepoužívejte. Pokud by měla naše metoda v rámci sebe něco změnit, ať změní pouze vnitřní stav svého objektu.

Vypilujte názvosloví

Přesný a výstižný název metody je velmi důležitý a pro klienta metody je samodokumentující. Klient této metody bude přesně vědět, co od ní může očekávat. Ušetříte mu čas, který by v případě pochybností ztratil tím, že se musí podívat dovnitř metody, jak je implementována. Někdy se ani nemá kam podívat, pokud se jedná o veřejnou metodu nějaké překompilované assembly.

Na druhou stranu by pro Vás měl být název zavazující a neměli byste v metodě dělat nic navíc než jejím názvem deklarujete. V opačném případě zavádíte do metody vedlejší efekty a bude docházet k neočekávanému způsobu použití.

Název je samozřejmě důležitý i u argumentů. Používejte terminologii z domény, kterou metoda řeší. Nepoužívejte více různých termínů pro stejnou věc. Udržujte si doménový slovník.

Chybové stavy a výjimky

Pro indikaci problému při provádění metody nepoužívejte návratovou hodnotu (např. oblíbená -1). Použijte raději výjimky, která jsou pro tyto účely určeny k uchování kontextu chyby. Návratová hodnota je určena k něčemu jinému.

Měli byste mít samostatnou metodu na zachycení výjimky a samostatnou metodu na její zpracování.

Testovatelnost

Zajímalo by mě, jak se taková metoda s 12 argumenty a více než stovkou lokálních proměnnných testuje? Tuny funkcionality, které by měly být refaktorovány do mnoha malých samostatně testovatelných tříd, jsou ukryty v jedné metodě. Testovatelnost je prakticky nulová. Vývoj této metody musel stát extrémně mnoho času.

Robustnost

V tomto ohledu nás zajímá, jak je snadné upravit část kódu tak, abychom splnili požadavek na změnu a zároveň nezanesli chybu na jiné místo algoritmu. Pokud máme problémovou testovatelnost, bude zřejmě nízká i robustnost systému. V algoritmu metody, který je na 1500 řádcích bude velmi problematické provést izolovanou změnu a domyslet všechny její důsledky. Proto se autor rozhodl, že stejný algoritmus v dalším roce zkopíruje do nové metody a tu pouze mírně modifikuje tak, aby původní funkcionalita zůstala zachována. Tím pádem nám vznikl bráška původní metody, který podvýživou také zrovna netrpí. Nešvary mají tendenci se znásobovat!

Neopakujte se

Rozpoznejte zdvojení kódu a refaktorujte ho do samostatné metody. Nedělám si iluze, že naše maximetoda neobsahuje množství zdvojeného kódu.

Závěrem

Dávejte si na podobné programové zrůdky pozor. Mohou se objevit v každém systému, pokud nemáte dostatečné zajišťovací sítě a neprovádíte pravidelnou deratizaci. Zkuste použít statickou analýzu kódu, která Vám pomůže odhalit podobné defektní záležitosti. Používejte a vyhodnocujte metriky kódu, které Vám mnohé napoví o zdraví Vašeho projektu. Dělejte Code Review a upozorňujte se vzájemně na problémy, které může někdo z Vás přehlédnout. Refaktorujte tak často, jak je to jen potřeba.

A hlavně se snažte ze svých chyb poučit. Chybovati je lidské, ale opakující se chyby jsou obvykle drahé a zbytečné a budou Vás strašit tak dlouho, dokud je neopravíte nebo nedáte výpověď ;-)

Žádné komentáře:

Okomentovat