Pravidlo 30 – kdy jsou metoda, třída nebo subsystém příliš velké?

Překlad článku Rule of 30 – When is a method, class or subsystem too big?
Nálepky:
Text vyšel původně na autorově webu.
V code review jsem připomínkoval stořádkovou metodu, která mi přišla příliš dlouhá. Hranice může být otázkou osobního vkusu, tak jsem hledal zdroje, čím bych svůj názor podpořil. Narazil jsem přitom na článek Rule of 30 – When is a method, class or subsystem too big?, který napsal Jim Bird. S laskavým svolením autora jsem článek přeložil.
Lidé, kterým záleží na psaní dobrého kódu, neustále kladou otázku: „Jaká je správná velikost metody, funkce, třídy, balíčku nebo jiného kusu kódu? Od určité chvíle může být kód příliš velký na to pořádně ho pochopit – ale jak velké je příliš velké?“
Začíná to na úrovni metody nebo funkce.
V knize Code Complete Steve McConnell říká, že teoreticky nejlepší maximální limit pro metodu nebo funkci je počet řádek, které se vejdou na obrazovku (tj. co vývojář může vidět najednou). Jmenuje studie z 80. a 90. let, podle kterých je ideální velikost funkce mezi 65 a 200 řádky. Takhle velké funkce je levnější vyvinout a mají méně chyb na řádek kódu. Nicméně od určitého místa za 200 řádky vstupujete do nebezpečné zóny, kde kvalita a porozumění kódu bude upadat. Kód, který nelze testovat, nemůže být bezpečně změněn. Případně skončíte u něčeho, čemu Michael Feathers říká „runaway methods“. Funkce jsou dlouhé několik stovek či tisíc řádek, jsou neustále měněny, což je průběžně dělá většími a děsivějšími.
Patrick Duboy se ponořil hlouběji do analýzy délky metod a poukázal na novější studii z roku 2002, která říká, že kód s kratšími funkcemi má méně chyb, což odpovídá intuici a zkušenosti většiny lidí.
Menší musí být lepší
Bob Martin v knize Clean Code dovedl myšlenku „jestli malé je dobré, tak menší musí být lepší“ do extrému.
První pravidlo funkcí je, že by měly být malé. Druhé pravidlo funkcí je, že by měly být ještě menší než to. Funkce by neměly být 100 řádek dlouhé. Funkce by měly být stěží 20 řádek dlouhé.
Martin přiznává: „Tento předpoklad nemůžu dokázat. Nemůžu citovat žádný výzkum, který říká, že velmi malé funkce jsou nejlepší.“ Takže stejně jako mnoho další pravidel a doporučení v komunitě softwarového vývoje je tento soud založen na jejich osobní zkušenosti s psaním kódu, estetických a etických argumentech, spíše než na těch ověřených experimentem. Styl nad hmotu.
Stejný návod „menší je lepší“ platí pro třídy, balíčky a subsystémy – všechny stavební bloky systému. V knize Code Complete je zmíněná studie z roku 1996, která zjistila, že třídy s více funkcemi mají více chyb. Podle knihy Clean Code mají být třídy (stejně jako funkce) rovněž „menší než malé“. Někteří doporučují 200 řádek jako dobrý limit pro třídu (nikoliv metodu) nebo tak málo jako 50 až 60 řádek (Ben Nadel Object Calisthenics). Takové třídy by se měly skládat z „méně než 10“ nebo „ne víc jak 20“ metod. Slavný projekt C3, kde vzniklo extrémní programování, měl v průměru 12 metod na třídu. A nemělo by být víc jak 10 tříd na balíček.
PMD, nástroj statické analýzy, který pomáhá upozornit na problémy ve struktuře a stylu kódu, definuje nějaké výchozí hodnoty pro velikost kódu: 100 řádek na metodu, 1 000 řádek na třídu a 10 metod na třídu. Podobný nástroj Checkstyle navrhuje odlišné limity: 50 řádek na metodu a 1 500 řádek na třídu.
Pravidlo 30
Hledání doporučení jako jsou tato mě přivedlo k „pravidlu 30“ v knize Large Software Projects (Martin Lippert, Stephen Roock).
Skládá-li se element z více jak 30 subelementů, tak je vysoká pravděpodobnost, že je tam vážný problém:
a) Metody by v průměru neměly mít víc jak 30 řádek kódu (nepočítáme prázdné řádky a komentáře).
b) Třída by v průměru měla obsahovat méně jak 30 metod, což je dohromady až 900 řádek kódu.
c) Balíček by neměl obsahovat víc jak 30 tříd, což je dohromady až 27 000 řádek kódu.
d) Subsystému s více jak 30 balíčky bychom se měli vyhnout. Takový subsystém by obsahoval až 900 tříd s až 810 000 řádek kódu
e) Systém s 30 subsystémy by pak obsahoval 27 000 tříd a 24,3 milionů řádek kódu.
Jak to vypadá? Vezměte povětší systém s 1 milionem NCLOC (Non-Comment Line of Code). Ten by se měl rozpadnout do:
- 30 000+ metod
- 1 000+ tříd
- 30+ balíčků
- Snad víc než 1 subsystém
Kolik systémů v reálném světe vypadá stejně a nebo podobně jako tenhle (obzvláště velké systémy, které už tu jsou pár let)?
Jsou tato pravidla užitečná? Jak byste je měli použít?
Použít velikost kódu jako základní pravidlo jako tohle je snadné. Snadné vidět a porozumět. Mnoho lidí by argumentovalo, že až příliš jednoduché: lepší indikátor, zda je kód příliš velký, je cyklomatická složitost nebo jiné metriky kvality kódu. Ale některé nedávné studie ukázaly, že velikost kódu je ve skutečnosti silný indikátor komplexity a kvality.
Metriky komplexity vysoce korelují s řádky kódu, a proto komplexnější metriky neposkytují žádné další informace, které by nemohly být jednoduše změřeny řádky kódu.
V kapitole „Za řádky kódu: Potřebujeme komplexnější metriky?“ v knize Making Software jdou autoři tak daleko, že říkají, že řádky kódu by měly být vždy považovány za „první a jedinou metriku“ pro indikaci defektů, vývoje a údržby modelů.
Uznání takových prostých pravidel velikosti je na vás. Měli bychom je používat? A pokud ano, tak jak?
Líbí se mi myšlenka prostého a jednoduše pochopitelného pravidla, které můžete mít na mysli, když píšete kód nebo když se rozhodujete, jestli by měl být refaktorován. Skutečná hodnota doporučení jako pravidlo 30 je v tom, když revidujete kód a identifikujte rizika a náklady.
Nicméně vynucení takových pravidel silnou rukou na každém kousku kódu je hloupé. Nechcete se zastavit, jakmile začnete psát 31. řádek metody, to by neskutečně zpomalilo práci. Nutit každého rozdělit kód tak, aby splňoval velikostní limity, povede nikoliv k lepšímu, ale k horšímu kódu (ve struktuře budou dominovat krátkodobá rozhodnutí).
Jeff Langer v diskusi s Ken Beck poukázal na čtyři pravidla jednoduchého designu v čistém kódu:
Naším cílem je udržet náš systém malý a stejně tak udržet i malé funkce a třídy. Nicméně toto pravidlo má nejnižší prioritu ze všech čtyř pravidel jednoduchého designu. Ačkoliv je důležité udržet malý počet tříd a funkcí, tak mnohem důležitější je mít testy, eliminovat duplicity a vyjádřit svou myšlenku.
Občas to zabere víc jak 30 řádek (nebo 20 nebo 5 nebo jaký je to limit) vytvořit soudržný kus práce. Je důležitější být opatrný s výběrem správné abstrakce a algoritmů a psát jasný, čistý kód. Pomůže-li k tomu domluvený velikostní limit, tak jej použijte. Jestli ne, tak se tím neobtěžujte.
Aha, tak takhle vznikla ta úchylka v Node.js světě, kdy máte na primitivní webovou aplikaci 400 balíčků (jeden porovnává stringy, druhý inty, atd.), node_modules pak obsahuje několik tisíc souborů a appka má desítky mega před minifikací :-)
No a jak to teda nakonec dopadlo s tím code review, co je zmíněno na začátku článku?
Pull-request jsem s připomínkou schválil, ale domluvili jsme se, že si všichni přečteme knihu Clean code a pak prodiskutujeme.
Lidska DNA ma 46 chromozomu.
A ještě je plná mrtvého kódu, porušuje DRY… Nelze se divit, jak naše civilizace vypadá.
To, že jde o mrtvý kód si myslíme teď … ;-)
To jsem takhle přišel do nové práce. Koukám na ten kód, a říkám si „co je to zase za prasečinu?!“. No a po třech měsících „jo aháá!!, vychytaný!
:-)
„jestli malé je dobré, tak menší musí být lepší“ – tímto primitivním schematem přemýšlí většina ekonomů, pro něž je trojčlenka to nejsofistikovanější, co pochopili. Vývojář by takto přemýšlet neměl. Na to bych reagoval jiným citátem:
„Dělejte věci tak jednoduché, jak to jde. Ale ne jednodušší.“ Albert Einstein
Poučky typu diskutovaných v tomto článku jsou nejlepší cestou do pekel. Ne že by na nich něco nebylo, ale když mi procesačka kdysi v hodnocení vytkla, že cyklomatická složitost některých funkcí má špatnou hodnotu, něco nepěkného jsem si o ní pomyslel. Když se při osobním pohovoru ukázalo, že netuší, mám-li se snažit o hodnoty spíše vyšší či spíše nižší než ona vyhlásila, a tedy že vůbec netuší, o co vlastně jde, jen tupě někde převzala a vyhlásila nějaké číslo, tak ji od facky zachránilo jen to, že to byla žena.
Délka kódu funkce (metody …) závisí od toho, jestli je programátor placen od řádku nebo od byte přeloženého (minimalizovaného …) kódu :-)
Možná by mnohdy bylo výhodnější, kdyby byl placen od rychlosti výsledného programu. Tam by pak přicházela v úvahu nepřímá úměra :-)
U sebe pozoruji jednoznacny trend zkracovani. Pred deseti lety jsem byl schopen byt hrdy na metodu o 500 radcich. Dnes kdyz ma deset tak uz premyslim jak refaktorovat. Prumer mam kolem 5 radku na funkci. Ale patrne na to ma velky vliv volba jazyka a paradigmatu, nejen starnuti.
5 riadkov na metodu? Ked sa to potom zosype, tak stack trace ma aspon 50 levelov? Ja si v praci neviem predstavit, ze by nase metody mali iba 5-10 riadkov… Samozrejme, 500 tiez nie je to prave orechove.
Téma dobré, ale měl bych připomínky k jazyku: