Category Archives: Uncategorized

Trable s Mavenem

Poslední měsíc jsem strávil konverzí hromady Ant skriptů do Mavenu, cítím se tedy kvalifikován trochu si do Mavenu rýpnout. Předem chci upozornit, že si myslím, že Maven je nejlepší nástroj ve svém oboru dostupný pod open source licencí. Jenže jak kdosi chytrý řekl, to že je něco nejlepší ještě neznamená, že je to dobré.

Nedostatečná dokumentace

Asi největší chyba Mavenu je mizerná dokumentace. Trochu to zachraňuje volně dostupná kniha „Better builds with Maven“. I stránky projektu se za poslední dobu zlepšily. Stále ještě ale nejsou na dostatečné úrovni. Pokročilejší témata člověk musí hledat po různých konferencích a hlavně ve zdrojovém kódu. Ten stojí opravdu za to. Pokud někdo chcete vidět zdrojáky bez kousku JavaDocu, podívejte se do Mavenu. To je velká chyba, podle mě to hodně brání většímu zapojení komunity.

Špatná úroveň pluginů

Pluginy jsou to, na čem Maven stojí. Často je to ale i tím na čem Maven padá. Není neobvyklé, že plugin spadne a vyhodí kryptickou výjimku, z které člověk vůbec nepozná co se děje. Obvykle je chyba na straně uživatele, ale bez průzkumu zdrojových kódu je těžké přijít na to kde je a jak ji napravit. Často je také problém najít vhodný plugin na to, co zrovna člověk potřebuje. Pamatuji se, že když jsem hledal plugin na JAXB2, tak mi zafungoval až pátý nalezený.

Nekvalitní repository

Repository je další silná stránka Mavenu. Zároveň je to ale také jeho slabina. U projektů, které nejsou buildovány Mavenem je velká pravděpodobnost, že budou mít v repository špatná metadata. Zrovna dnes jsem narazil na to, že nejnovější hibernate-entitymanager závisí na verzi hibernate-commons-annotation, která není vůbec v centrálním repository. Tzn. není možné tuto knihovnu použít, aniž by člověk nestrávil nějaký čas hledáním, jak daný problém vyřešit. (V tomto případě použitím jboss repository.)

Na téma repository mám pár dalších příkladů. Oba se týkají Springu. Pokud se pokusíte zadat verzi Springu intervalem a ne přesnou, konkrétní verzí, tak vám Maven bude tvrdit, že nejnovější verze Springu je 2.0-m4. Může za to tento soubor. Stejně tak zamrzí, když se vám v IDE nezobrazí zdrojové kódy Springu, pokud nemáte závislost na celém Springu, ale jen na nějaké jeho části. Důvodem je zase nekompatibilní přístup autorů Springu a Mavenu.

Se všemi uvedenými problémy se člověk dokáže vyrovnat. Všechny ale dělají křivku učení hodně strmou. Pro člověka, který s Mavenem začíná a nemá nikoho kdo by mu pomohl, je neuvěřitelně těžké se přes počáteční obtíže dostat. Jediné čím se může utěšovat je to,že pokud je překoná, čeká ho kýžená odměna ve formě velké pomoci s build procesem.

Proč dělám certifikáty

Není důležitý cíl, ale cesta.

Také bych chtěl přispět svým názorem do dnešní diskuze ohledně certifikátů (viz. Dagblog a Vávrů). Aby bylo jasno, musím se na úvod přiznat, že jsem držitelem SCJP, SCWCD a čerstvě i SCBCD. Pro skládání certifikátů mám následující důvody:

Motivace

To, že se člověk přihlásí na certifikát je veliká motivace k tomu, konečně se ponořit do studia. Kdybych neskládal certifikát, asi bych nenašel důvod pro to studovat základy Javy. Proč taky když o Javě vím úplně všechno. Až poté, co si člověk udělá pár testů nanečisto (nám se osvědčil Whizlab) zjistí, že jsou oblasti v kterých se moc neorientuje.

Naučení se nových věcí

Já jsem se díky přípravě na SCJP pořádně naučil používat regulární výrazy, zjistil k čemu je LinkedHashMap a objevil, že existuje něco tak zrůdného jako nestatický inicializační blok. Při přípravě na SCWCD jsem se konečně naučil dělat vlastní tagy a používat tag files. No a SCBCD mě donutil konečně pochopit EJB v celé jejich obludnosti.

Peníze

Asi není pochyb, že vlastnictví certifikátu zvedne cenu člověka na trhu práce. Navíc můj zaměstnavatel vyplácí za složené certifikáty prémie.

Nápad s přispíváním OS komunitě je zajímavý. Sám se o to ve volném čase snažím. Příprava na certifikát má ale tu výhodu, že se dá dělat v pracovní době, například v čase mezi projekty. Zveřejňování kódu, který člověk napíše v pracovní době pravděpodobně není triviální z právního hlediska.

Na druhou stranu je zřejmé, že Sun certifikáty mají daleko k ideálu. Některé otázky a témata jsou v praxi nepoužitelné. Marně například čekám na okamžik, kdy se mi bude hodit to, že umím vyjmenovat a správně určit, které role mají jaké zodpovědnosti při vývoji EJB. Nicméně si myslím, že čas věnování přípravě na certifikát nebyl vynaložen zbytečně i kdyby ten papír nakonec neměl vůbec žádnou cenu.

Neměnitelné třídy

Dnes bych chtěl psát o jedné technice, která se mi celkem osvědčuje – o neměnitelných třídách (immutable classes). Kdo četl knihu od Joshuy Blocha Java Efektivně, pro toho to nebude žádná novinka. Pro ty, kteří ji nečetli nebo si ji nepamatují připomenu.

Neměnitelná třída je taková třída třída, jejíž instance nejde změnit. Všechny informace v ní obsažené se poskytnou při jejím vytváření a jsou pak pevně dány po celou dobu jejího života.[Bloch]

Klasickými příklady jsou String, BigInteger a BigDecimal. Zamysleme se nad tím, co nám neměnitelné třídy přináší.

Vezměme třídu Address, která obsahuje informace o ulici, číslu a PSČ. Pokud je měnitelná, má příslušné get i set metody. Prostě třída, kterých vyrobíme denně několik. Měnitelným třídám bychom měli věnovat zvláštní péči. Měli bychom řešit co se stane, když je mění několik vláken najednou. Měli bychom vytvářet defenzivní kopie, když je někomu dáváme ke zpracování. Měli bychom hlídat jestli se nám nestane například něco takového:



1     Client client1 = new Client();
2     Client client2 = new Client();
3     Address address = new Address("Petrova","15","110 00");
4     client1.setAddress(address);
5     client2.setAddress(address);
6     
7     client1.getAddress().setNumber("16");

Tady jsme nechtěně přestěhovali i druhého klienta. Při použití OR mapovacích nástrojů musíme rovněž přemýšlet, jestli se nám provedené změny zapíší do databáze automaticky nebo jestli je musíme explicitně uložit.

Zkrátka a dobře, pokud bychom chtěli programovat pořádně, měli bychom kolem měnitelných tříd spoustu práce a přemýšlení. Protože ale přemýšlíme hrozně neradi, existuje pro nás snadné řešení. Jsou to právě neměnitelné třídy. Obvykle je realizuji tak, že jim jednoduše nedám žádné set metody a všechna potřebná data nastavím v konstruktoru. Pokud navíc třída obsahuje nějaká měnitelná data, musím si ještě vytvořit defenzivní kopii při jejich vložení a při jejich vracení.



01 public class Foo {
02   private final Date date;
03   private final List<String> list;
04   
05   public Foo(Date date, List<String> list) {
06     super();
07     this.date = new Date(date.getTime());
08     this.list = new ArrayList<String>(list);
09   }
10   
11   public Date getDate() {
12     return new Date(date.getTime());
13   }
14   public List<String> getList() {
15     return Collections.unmodifiableList(list);
16   }
17   
18 }

[Updated 27.8.2007 – Peter mě v komentáři správně upozornil, že jsem u polí zapomněl final]

Pokud bych na defenzivní kopírování zapomněl, mohl by mi někdo měnit data pod rukama a třída by nebyla neměnitelná. Pan Bloch ještě navíc radí zamezit zastiňování metod, aby mi někdo nemohl udělat měnitelného potomka neměnitelné třídy. Protože ale obvykle nepíší veřejná rozhraní, tak jsem většinou toto riziko nést.

Co mi neměnitelné třídy přinesou? Zjednoduší mi život. Nemusím řešit co se stane, když je změním. Nemusím řešit synchronizaci vláken. Jejich instance mohu bez obav sdílet. Dobře se mi z nich staví další objekty. Dobře se mi píše metoda equals a hashCode. Zkrátka a dobře programování s nimi je mnohem méně náchylné k chybám.

Samosebou to není žádný všelék. Některé třídy je často nutné udělat měnitelné. Z jejich povahy prostě plyne, že je nutné je měnit. Občas se mi stane, že tak zatvrzele trvám na tom, že chci udělat třídu neměnitelnou, až si tím zkazím celý návrh.

Specifickým případem je použití MVC frameworku. Pokud chci třídu plnit daty z UI formuláře, tak ji prostě set metody dát musím. Nicméně platí následující:

Třídy by měly být neměnitelné, pokud neexistuje velmi dobrý důvod k tomu, učinit je měnitelnými [Bloch]