Design is hard
Poslední dobou mám pocit, že v programátorské branži jsou dva typy úkolů, které lze považovat za opravdu těžké:
- Implementace složitých low-level systémů – operačních systémů, kompilátorů, virtuálních strojů, vysoce optimalizovných databázových serverů, apod. Vše typicky v céčku, občas v C++.
- Design rozhraní. Za rozhraní v tomto článku považuju cokoliv, co je používáno uživatelem, ať už je jím uživatel v klasickém smyslu, nebo jiný programátor. Patří sem nové programovací a jiné jazyky, runtime knihovny těchto jazyků, jakékoliv rozsáhlejší API, uživatelské rozhraní netriviálních aplikací, atd.
Na práci na úkolech z první skupiny je těžké to, že je třeba přemýšlet v abstraktní rovině zadání a teoretických principů, na kterých je systém postaven, a zároveň i na úrovni bitů a bajtů, do kterých se vše nakonec zkompiluje. Chce to mít podrobný přehled jak o různých efektivních datových strukturách a algoritmech, tak o hardwarové architektuře, na které systém běží, a k tomu znát spousty implementačních a optimalizačních detailů specifických pro danou oblast.
Při práci a úkolech z druhé skupiny je potřeba především cit a schopnost představit si, jak výsledný produkt bude používat uživatel.
Jak může být někdy design těžký, ukazuje následující příklad: Elliote Rusty Harold se pustil do kritiky třídy list v jazyce Ruby. Přijde mu, že počet jejích metod (78!) je příliš velký a že mnohé se používají natolik zřídka, že nemají právo být v tak často používané třídě. Jenže Rusty je podle všeho člověk vyrostlý na Javě, což je jazyk sice objektový, leč stále v zásadě procedurální. Oproti tomu Ruby je prodchnuto funkcionálním programováním, ve kterém se s kolekcemi místo "opracovávání for-cykly" typicky pracuje přímo pomocí funkcí bez postranních efektů – v případě objektového jazyka tedy pomocí metod. A odtud plyne jejich hojnost v Ruby. Víc se o tom, jak je Rustyho pohled omezený, rozepisuje Slava Pestov.
(Poznámka stranou: Všimli jste si také, jak funkcionální programování prosakuje čím dál tím víc do nových programovacích jazyků, včetně třeba relativně konzervativního C#? Jako doplňkové programovací paradigma zřejmě má své místo.)
Můj názor na věc? Není nijak silný, protože o Ruby jsem jen četl a v praxi ho nepoužívám. Nicméně vím, že ruby má mechanismus mixins, který umožňuje snadné rozšiřování objektů o nové metody a vlastnosti. Malinko se divím, proč ho autoři nevyužili tady a některé pokročilé metody neimplementovali v samostatných třídách, které s uživatel v případě potřeby do konkrétní instance listu zamixuje. Možná se jim zdálo, že dalšími třídami zvětší složitost knihoven víc, než záplavou metod (tj. zvolili zesložitění kvantitativní oproti kvalitativnímu).
Existuje samozřejmě i varianta méně obvyklé metody neimplementovat vůbec a
nechat na jednotlivých uživatelích, ať si základní třídy zdědí a metody v
potomcích implementují dle potřeby. Přiznávám, že chvíli se mi toho zdálo jako
zjevná správná cesta, ale nyní už si tím vůbec jistý nejsem. Podobná "holost"
totiž třeba u C/C++ vedla k tomu, že si mnoho věcí
každý kus kódu implementuje po svém a zkombinovat v jedné aplikaci více knihoven
z různých zdrojů se stává noční můrou (Příklady? Různé definice booleovského
typu v céčku (než se dostal do normy) nebo častý jev "co knihovna, to vlastní
třída String
" v C++).
Princip jednoduchých tříd je částečně použit i v Javě, ale má jednu obrovskou
trhlinu: Klíčové třídy jsou deklarovány jako final
, takže z nich
nejde zdědit a upravit si je podle potřeby. V komentářích mých Javovských
programů se dá na toto téma najít několik ne zrovna dvakrát slušných výroků
směrem k tomu, kdo tohle vymyslel :-)
Jak říká titulek, design is hard, a často se všechny možné varianty zdají špatné. Najít mezi všemi požadavky rovnováhu a to nejen na lokální úrovni jednotlivých tříd či podobných malých jednotek, ale konzistentně v celém navrhovaném systému, je obrovské umění a lidé, kteří to dovedou, mají můj obdiv. Stejně jako lidé, co dovedou implementovat opravdu dobrý operační systém, kompilátor, virtuální stroj nebo vysoce optimalizovaný databázový server...