Dagblog

Dagblg

11/13/2009

CZ Podcast #33 - reloaded

Možná jste se už báli, že nás postihla ptačí, prasečí či jiná chřipka, ale my jsme opět tady (jenom Filemon měl nějakou dětskou nemoc). Každopádně další díl jsme věnovali novinkám kolem nás. Roumen pohovořil o open source procesu kolem IntelliJ IDEA, já o zážitcích s .NET a Filemon o MDA (generátorech kódu). Bavte se.

Štítky:

11/01/2009

Do pranice: Vhodnost ORM

Dvakrát se mi v poslední době stalo, že jsem se snažil někoho přesvědčit o nevhodnosti použití Hibernate a obecně ORM nástrojů pro přístup do databáze. ORM přístup má svoje výhody, ale i věci, které činí jeho použití obtížné.

Faktory, které ovlivňují jestli je ORM vhodná volba.

  • Aplikace pracuje pouze s více typy databází. V takovém případě přináší ORM neocenitelné služby v oblasti přenositelnosti. Ta nemusí být dokonalá, ale určitě převáží nad práci vynaloženou nad portací vrstvy pro přístup k datům pro N dalších typů databáze.
  • Aplikace potřebuje číst a zapisovat košaté objektové struktury. Zde nám ORM neušetří práci na psaní dotazů, ale ušetří nám hromadu kódu, který bude potřeba na jejich zpracování. Mám na mysli především kód, který prochází ResultSet a staví objektový strom a naopak kód, který prochází objektový strom a staví PreparedStatement.
  • Aplikace si může dovolit upravit RDBMS schéma, aby vyhovovalo objektově-relačnímu mapování. Ačkoliv Hibernate nabízí doslova kouzla pro namapování čehokoliv na cokoliv je lepší upravit RDBMS schéma, tak aby vyhovovalo.

Jednou z charakteristik ORM frameworků je jejich snadná počáteční adopce. Tyto řešení fungují velice snadno pro vzorová schémata typu: potřebuji namapovat one-to-many vztah, potřebuji získat entitu na základě jejího identifikátoru. Řekl bych, že tato vlastnost a databázová přenositelnost je pozlátko, které hodně vývojářů zláká. Bohužel je zde i temná strana síly, se kterou zahrávati neradno je a počítati musí se s ní.

Osobně bych to vyjádřil takto, pokud nemáte v týmu někoho se zkušeností s ORM, čeká vás plno nemilých překvapení. To je dané komplexností ORM a vy pravděpodobně nemáte ani tucha co je pod kapotou. První vystřízlivění nastává ve chvíli kdy si zapnete výpis SQL dotazů následované LazyInitializationException a zakončeno magickými zápisy do databáze, které vám nedávají smysl.

To střízlivění a bolehlav je důsledkem komplexnosti, kterou ORM představuje. Takže kromě toho, že se učíte jazyk vlastního frameworku, musíte vstřebat a pochopit právě tuto komplexnost. Stejně jako máme návrhové vzory pro objektově orientovaný návrh nebo návrh enterprise systémů, tak máme i vzory pro to jak úspěšně používat ORM. A věřte mi, že máte problém pokud ty vzory neznáte.

Nerad bych, aby tenhle článek vyzněl tak, že ORM je špatné. To v žádném případě není. Jenom je dobré si uvědomit, že jako každé řešení se pro některé úkoly hodí více, pro některé méně a pro některé vůbec. Samozřejmě je na místě otázka co jiného když ne ORM. Docela dobrý kompromis mezi komplexním ORM a nízkoúrovňovým JDBC představuje framework iBatis (viz třeba Honza Novotný iBatis 3.0 preview – část první), kdy mapujete objektový graf na SQL dotazy namísto tabulek.

Budu nesmírně rád pokud mi zde pod článkem vyjádřite svůj názor o vašich zkušenostech s ORM.

Štítky:

10/18/2009

Testování aplikací - panelová diskuze

Co se stane, když dáte dohromady javistu, dotnetaka, pythonistu a rubyistu a necháte je diskutovat o testování aplikací. Po pravdě řečeno jsem nevěděl co od toho čekat, ale rád jsem přijal pozvání, které mi adresoval Jarda Jirava na akci Testování aplikací - panelová diskuze. Spolu se mnou diskutoval ještě Karel Minařík (Ruby), Jan Král (Python), Borek Bernard (Flex, .NET) a Michael Juřek (.NET) za účasti osmdesáti posluchačů.

Na začátek musím předeslat, že akce byla opravdu povedená a moji spoluřečníci byli skvěle připraveni. Na internetu se objeví dokonce i audio záznam. Rád bych zde shrnul to nejzajímavější co jsem si z diskuze odnesl.

V případě dynamických jazyků jako Ruby nebo Python jsou testy alfou a omegou celého psaní. Testy zde zněla jako mantra takřka pro jakoukoliv softwárovou disciplínu. Test sloužil zároveň jako jeho design a měřidlo kvality kódu. Přístup Test first byl dosti často citován jako způsob pro to kde začít s kódem. Jak správně zaznělo z publika od Pavla Jetenského psát aplikace postavené nad staticky typovým jazykem ještě jde, ale dělat to za použití dynamického jazyka je problém.

Téma, na kterém jsme se zasekli, by vydalo určitě na samostatný článek. Jednalo se o přípravu dat pro testy. Jedna z pouček o psaní testů říká, že příprava vlastních dat pro test by neměla záviset na žádné aplikační logice. Líbilo se mi, že se nám doufám podařilo shodnout, že při psaní aplikací postavených nad databází je toto pravidlo pouze teorie a jakákoliv redundantní příprava dat postupem času dosti rychle ztrácí dech. Například kvůli tomu, že databázové schéma či aplikační omezení se stále vyvíjí a je těžké je držet konzistentní.

Z naší diskuze mě zaujalo ještě pár střípků

  • Carbon footprint - čím dřív začnete testovat na nižší úrovni abstrakce tím menší počet počítačů je potřeba (ekologický fundamentalismus dotažený k dokonalosti? ;-).
  • Pex - je rozšíření Visual Studia, které dokáže projít a zanalyzovat váš kód a na základě této znalosti vygenerovat odpovídající testy.
  • Borkova ilustrace složitosti psaní testů pro jednotlivé typy kódu. Nejjednoduší bylo povětšinou psát testy pro klasické knihovny oproti například desktopovým aplikacím. Dobrý argument na někoho kdo mi bude doporučovat jeho vlastní framework.

10/10/2009

Chudokrevný model, chudý příbuzný objektově orientovaného návrhu?

Nedávno se mě jeden kolega zeptal jestli budeme mít anemic domain model (chudokrevný?). Byl jsem trošku v rozpacích co tím myslí. Po krátke diskuzi jsme si vyjasnili termíny (problém jsem znal, ale termín jsem zapomněl) a já jsem prohodil, že asi budeme. Když nad tím přemýšlím, musím říci, že to byla blbost.

Pokud si přečtete výše uvedeny článek Martina Fowlera dostane se vám erudovaného vysvětlení co to je chudokrevný doménový model model. Pokud to dělat nechcete, pak se budete muset spokojit s mojí interpretací. Chudokrevný doménový model je takový model, kdy doménové třídy reprezentující business entity systému neobsahují žadnou logiku. Jsou to pouze "přenosky" dat se settry a gettry.

Fowler dále správně upozorňuje na fakt, že chudokrevný doménový model vede k příliš těžkopádné a tlusté aplikační vrstvě. V té se mísí všechna aplikační logika namísto toho, aby ležela právě v doménovém modelu kam patří. Pokud jste v posledních pár letech dělali nějakou vícevrstvou aplikaci, pak se schválně podívejte na velikost všech tříd, které v názvu obsahují slovo Service. Jsou to u vás největší molochy v celém projektu jako u mě?

Problém s těmito molochy je v tom, že jsou jenom velice těžce jakýmkoliv způsobem refaktorovatelné. Samozřejmě pokud pominu fakt, že z metody o pětsistech řádcích uděláme pět malých o sto řádcích. Představa nějakého objektového re-designu je skoro nemožná.

Každý chytrý J2EE tutoriál či článek nám radí jak je dobré členit náš program do vrstev. Máme tak vrstvu servisní (aplikační logiky), vrstvu prezentační a vrstvu persistence (ukládání dat). Bohužel už nikde, až na pár míst, se nedočteme jak správně by měly tyto vrstvy vypadat. Výsledkem je, že sice správně separuje kód se stejnou odpovědností (UI, persistence), ale neděláme to objektově správně. Ve smyslu, že kód který patří do doménového modelu daváme do vrstev kam vůbec nepatří.

Jenže co to je objektově správně a potřebujeme to vůbec? Dokázali jsme žít se špatným objektovým návrhem léta a naše programy fungovaly dobře. Ovšem to by neměl být důvod nesnažit se jejich strukturu zlepšit, pokud víme, že je něco špatně. Hodně jsem přemýšlel o tom jakým způsobem to udělat a přijde mi, že nejlépe to řeší Domain Driven Design (zkráceně DDD).

Klíčove je, že aplikačni logika, která leží v servisné vrstvě, nebo nedej bože ve vrstvě persistence, se přesune do doménových tříd. To neznamená ovšem, že by najednou měla každá z těchto tříd vědět jakým způsobem se má uložit do databáze nebo snad ovládat transakční logiku. Doménové třídy například požadavek na uložení delegují na vrstvu persistence.

Servisní vrstva a vstva pro ukládání dat by měla zůstat co nejtenčí. V podstatě to znamená, že slouží jenom k tomu, aby došlo k správnému překladu jedné objektové reprezentace na druhou a kordinaci s infrastrukturou. Nemyslim si, že je jednoduché takto aplikace vytvářet. Největší problém je v tom, že s doménovými třídami nakládáme obvykle v kódu jinak než s třídami jiných vrstev.

Třidy z doménového modelu vytváříme povětšinou konstruktorem. V takovém případě máme problém jak do nich dostat právě třídy jiných vrstev. No ale to už je na jiný článek.

Na závěr dám k dobru ješte pár dobrých článků k tématu

8/12/2009

Pálit trasírkami

Někdo z pravidelných čtenářů tohoto blogu by mohl následující přirovnání považovat za můj násilný pokus nalézt paralelu v umění válečném. Nicméně to o čem budu povídat není nejen z mojí hlavy, ale i termíny jsou původní.

Volně převyprávěno z Tracer Bullets and Prototypes - Pragmatic Programmers Andy Hunt and Dave Thomas talk with Bill Venners about the importance of getting feedback during development by firing tracer bullets and building prototypes.

Představte si, že ležíte ve tmě někde v buši a máte zasáhnout cíl. Máte dvě možnosti. První, znáte přibližnou polohu cíle, povětrnostní podmínky, atd. a z těchto údajů spočítáte balistickou dráhu kulky, nastavíte mířidla, zatajíte dech a vystřelíte. Pokud jste počítali dobře, vaše údaje se shodovaly s reálnými a cíl se nepohnul tak možná trefíte.

Druhou možností je použít značkovací munici též zvanou trasírky. Trasírka je speciální kulka, která za sebou po vystřelení nechává svítící stopu. V zásobníku bývá napáskováná každá n-tá střela tohoto typu. Při použití značkovací munice prostě vystřelíte a podle dráhy střely, kterou vidíte, zkorigujete náměr, tak aby pokud možno další střela našla cíl a nebo se mu alespoň přiblížila.

Nyní je pravá chvíle na uvedení paralely se softwárovým vývojem. Představte si, že stojíte před vývojem nového softwaru a nebo na prahu nového releasu. Někde na jeho konci je doručení finální podoby. Stejně jako při té střelbě v buši je mnohdy obtížné vědět přesnou polohu a čas od času se cíl pohne (kdo by to byl čekal). Některé požadavky dopadnou více či méně včas, některé jsou nejasné, a některé si vyložíme jinak. V takovém případě postup, kdy uděláme jeden velký odhad (předpoklad) na začátku a potom doručíme na konci (vystřelíme) kompletní řešení, často selhává.

Oproti tomu trasírky se dají do řeči softwárového vývoje převést asi následovně. Na začátku uděláme nějaký předpoklad, provedeme podle něj vývoj a po čase to vezmeme a ukážeme zákazníkovi. On nám řekne jak blízko nebo daleko jsme od jeho představ. Uděláme korekci a v další iteraci a opět ukážeme zákazníkovi. Tak společnými silami, postupným korigováním dráhy střely, dojdeme k řešení po kterém zákazník touží.

Mě se pálení trasírkami zdá jako vhodný způsob, ačkoliv v něm vidím jedno nebezpečí. Občas se stane, především pokud nešijeme na míru jenom jednomu zákazníkovi, že to co si vymyslí jeden zákazník, se jeví jako nepoužitelné pro jiného zákazníka, protože jeho představa je diametrálně odlišná. Tím chci říci, že není úplně nejlepší, aby korekci vaší hlavně dělal zákazník bez vaší asistence, protože by to také mohlo skončit tím, že se střelíte do nohy.