Category Archives: Uncategorized

Jak poznat vodopád

Dnes budu psát o vývoji pomocí metodiky vodopádu. Pro připomenutí uvedu její popis (přesný a naprosto nezaujatý):

Na začátku od zákazníka získáme dokonalý popis toho co chce. Poté to hodíme analytikům/architektům, kteří udělají bezchybný návrh a předají ho programátorům. Ti to naprogramují a předají testerům na otestování. Výsledek se pak s velkou slávou dodá zákazníkovi. To celé obvykle trvá několik měsíců. Vodopádem se to nazývá proto, že tok je výhradně od shora dolů, návrat je možný jenom mezi sousedními fázemi. Tzn. analytik/architekt může vyžádat upřesnění požadavků, tester může program poslat zpět programátorům atp.

Tento model má několik menších nedostatků, uvedu jich jen pár namátkou:

  1. Zákazník obvykle nemá moc jasno v tom co chce. A i kdyby byl zákazník dokonalý, dokument, který přesně a úplně popisuje netriviální systém je téměř nemožné sepsat.
  2. I kdyby měl architekt dokonalý popis toho co si zákazník přeje, není možné udělat přesný a bezchybný design systému. (Je to možné, ale takového architekta neseženete)
  3. Vývoj trvá zpravidla delší dobu. Nicméně se vstup od zákazníka je možný jenom na počátku procesu. Je téměř jisté, že se požadavky zákazníka za tu dobu změní. Vodopád na to není vůbec připraven.
  4. I kdyby se požadavky uživatele nezměnily, zpětnou vazbu od zákazníka dostaneme až na úplném konci projektu. Kupodivu se často stává, že je zákazník nepříjemně překvapen, že dostává něco úplně jiného než co si představoval (a co potřebuje).

Takže skoro všichni kdo se ve vývoji software pohybují, vědí, že vodopád není ideální. Proto také často tvrdí, že ho už dávno nepoužívají. Všichni používají RUP, Scrum, XP a kdoví co ještě.

Můj soukromý pesimistický a subjektivní pohled ne věc mi našeptává, že jde jenom o zástěrku. Takže někdo dělá vodopád se jménem RUP, někdo dělá vodopád se jménem Scrum a někdo dělá naprosto chaotický a neřízený vývoj a říká tomu XP. Vymyslel jsem si jednoduchý test jak vodopád zaručeně odhalit. Moderní metodiky mají jedno společné. Jsou iterativní. Tzn. jde o sekvenci iterací – malých vodopádů zřetězených za sebou. Vodopádů se vším všudy, tzn. včetně testování, integrace, nasazení a předvedení zákazníkovi (u RUPu je tam pár odlišností). Pokud jsou tyto iterace dostatečně krátké, máme šanci případné chyby opravit, neporozumění napravit a změny zapracovat v další iteraci.

Takže jak zjistit, jestli někdo praktikuje vodopád? Stačí se ho zeptat, kolik má jeho projekt iterací. Pokud odpoví jedna nebo dvě, tak už je jasné, že slyšíme nezaměnitelný hukot vodopádu.

DSL, hudba budoucnosti?

Musím se přiznat, že nejsem moc velký fanda všelijakých těch skriptovacích a jiných podivných jazyků. Nicméně, před časem jsem viděl prezentaci pánů Martina Fowlera a Neala Forda s titulem “Language Oriented programming” (video, prezentace). Tato přednáška můj odpor poněkud nahlodala. Pokud nechápete co všichni mají na Ruby, Groovy a spol, tak si ji určitě pusťte. Pokud nemáte čas na její shlédnutí, prolétněte si alespoň PDF s prezentací. Já se pokusím napsat co jsem si z ní odnesl (a zapamatoval) já.

Prezentace začíná tím, že dnes při programování popisujeme svět pomocí stromových hierarchií. Zatímco na některé problémy je tento popis jak dělaný, na jiné problém už tak vhodný není. Prezentátoři proto navrhují pokusit se použít na některé problémy jazyk místo stromového popisu. Od toho se také odvíjí pojmenování DSL – Domain Specific Language (oborově specifický jazyk). Jaké to má výhody? Za prvé, lidský mozek je zvyklý pracovat s jazykem. Ba co víc, každý obor lidské působnosti má svůj specifický jazyk. Proč ho tedy nepoužít pro popis programu, který se v tomto oboru pohybuje?

Dnes pro řešení specifických problémů využíváme specifická API jako například toto:

Coffee latte = new Coffee(Size.VENTI);
latte.setFatContent(FatContent.NON_FAT);
latte.setWhip(Whip.NONE);
latte.setFoam(Foam.NONE);
latte.setTemperature(Temp.EXTRA_HOT);
latte.setStrength(5);

Kdybychom používali DSL, mohl vypadal by kód vypadat takto:

Venti half-caf, non-fat, extra hot, no foam, no whip latte

Co API v našem případě chybí, je znalost kontextu. Protože API používáme v obecném, univerzálním jazyce, musíme stále dokola opakovat že řešíme to naše kafe a ne třeba lokomotivy. Kdežto v DSL je tato informace součástí kontextu, proto vypadá přehledněji.

Interní DSL

Pod pojmem interní DSL se myslí jazyk, který používá syntaxi základního jazyka (v našem případě Javy). Pěkný příklad je tento z jMocku:


warehouseMock.expects(once())
.method("hasInventory")
.with(eq(TALISKER),eq(50))
.will(returnValue(true));

Ano, je to čistá Java, ale dá se číst jako anglická věta.

Výhodou skriptovacích jazyků je to, že jsou méně striktní. Tím je v nich lépe umožněna tvorba interního DSL. Podíváme-li se na věc v perspektivě DSL, tak jsou Rails jenom interní DSL, který má jako základní jazyk Ruby a jeho oborem jsou webové aplikace.

Externí DSL

Externí DSL jsou jazyky, které používají syntaxi rozdílnou od základního jazyka. Klasickým denně používaným externím DSL je XML. Na externí DSL už potřebujete vlastní parser, interpreter a kdoví co ještě. Takže jsou obtížněji vytvořitelné, na druhou stranu nám ale poskytují více volnosti.

A tím se dostáváme k otázkám které asi napadnou každého:

Nepovede to ke kakofonii jazyků? Kdo se bude sakra pořád učit nové jazyky? Odpovědí je, že my už to přeci dávno děláme. Každá knihovna má svoje API, které se musíme neučit, denně používáme různé typy XML, které mají každé jinou gramatiku. U DSL jenom nikdo nezastírá, že jde o nový jazyk.

Co nám DSL mají přinést?

  • Kód, který dokáže přečíst (ne napsat) i analytik. To může být skvělý nastroj pro ověření, jestli jsme zadání pochopili správně.
  • Programátoři se naučí mluvit podobným jazykem jako uživatelé.
  • Kód je abstrahován až na úroveň business problému.

Tak nevím, skoro mě zviklali, co si o tom myslíte vy?

Autowiring a Spring

Dnes chci psát o autowiringu ve Springu. Nejde o žádnou novinku. Je to funkcionalita, která je ve Springu už od první verze, ale moc jsem ji nepoužíval, protože se mi nelíbila. Nedávno jsem na ni ale změnil názor.

Začněme od toho co to je autowiring. Standardní Spring konfigurace vypadá takto:

<beans>
	<bean id="foo" class="net.krecan.blog.FooImpl1">
		<!--  Some configuration -->
	</bean>
	<bean id="bar" class="net.krecan.blog.Bar">
		<property name="foo" ref="foo"/>
	</bean>
</beans>

Do beanu bar, injektujeme instanci sigletonu foo. Autowiring spočívá v tom, že můžeme Springu říci, aby si závislosti automagicky vyřešil sám.

<beans default-autowire="byType">
	<bean id="foo" class="net.krecan.blog.FooImpl1">
		<!--  Some configuration -->
	</bean>
	
	<bean id="bar" class="net.krecan.blog.Bar"/>
</beans>

Do tagu beans jsem přihodil atribut default-autowire, kterým říkám, ať propojuje beany podle typu (existují i jiné metody viz. zde). Spring si prohlédne všechny nadeklarované beany, projde si jejich set metody a podle typu pozná, že má do beanu bar vložit bean foo.

Ty zvídavější jistě napadne, co se stane, když mapování není jednoznačné.

<beans default-autowire="byType">
	<bean id="foo1" class="net.krecan.blog.FooImpl1">
		<!--  Some configuration -->
	</bean>
	<bean id="foo2" class="net.krecan.blog.FooImpl1">
		<!--  Some configuration -->
	</bean>
	<bean id="bar" class="net.krecan.blog.Bar"/>
</beans>

V tomto případě Spring okamžitě vyhodí výjimku. Ani teď se Autowiringu nemusíme úplně vzdát, ručně musíme vyřešit jenom nejednoznačné závislosti, ostatní, jednoznačné beany se spojí samy.

Když jsem autowiring viděl poprvé, tak se mi zdála hrozně křehký a náchylný na chybu. Proto jsem si beany hezky spojoval ručně a byl jsem spokojen. Nedávno jsem ale přepisoval projekt z EJB 3 do Springu. Smazal jsem všechny EJB anotace a chystal jsem se napsat Spring konfigurační soubor. Po prvních pár beanech mi došlo, že to bude strašlivá práce. Zkusil jsem zapnout autowiring a všechno najednou jelo jako po másle. Stačilo mít jenom ve Spring configu vyjmenované všechny použité beany a doplnit pár chybějících set metod.

Nejen, že mi to ušetřilo práci při migraci, ohromě to i usnadňuje refaktoring. Když přesouvám nebo přidávám DAO do servisní vrstvy, vůbec se nemusím starat o konfiguraci. Změním kód a to je všechno. Myslím si tedy, že ve Springu 2 je autowiring dobrá volba. Pokud používate Spring 1 můžete narazit na problémy s ručně konfigurovanými proxy objekty. Ty vám v některých případech mohou způsobit nejednoznačnost mapování tím, že v kontextu bude vidět jak původní beana, tak obalující proxy, která implementuje stejné rozhraní. Ve Springu 2 se dají proxy snadno generovat automaticky, takže tento problém je méně pravděpodobný.