Nenuťte mě myslet

Nenuťte mě myslet (Do not make me think, Steve Krug) je kniha, na kterou často narazíte na stolech nebohých programátorů. A to i přesto, že se převážně zabývá použitelností webových stránek a ne aplikací. A jak tak koukám, tak to dokonce vyšlo i česky, pod názvem Nenuťte uživatele přemýšlet. Hmm, a dokonce jsou na internetu i recenze (1, 2, 3, 4). Tak si říkám, že nemá moc cenu, abych nosil dříví do Atén a přidával další recenzi.

Takže jen krátce: Mě se na knížce nejvíc líbilo, že se dobře čte, je relativně krátká a hlavně, že si při její četbě člověk hodně uvědomí o tom, jak se lidi na internetových stránkách chovají. Z pohledu programátora aplikací je asi nejužitečnější kapitola o uživatelských testech použitelnosti. Prostě o tom, jak zjišťovat, jak se potencionálnímu uživateli bude s naší stránkou a potažmo i aplikací pracovat. To je hodně zajímavé a užitečné. Takže dávám knize osm hvězdiček z deseti.

Java puzzlers

Tušíte správně, dneska vás čeká pidirecenze známé knihy Java Puzzlers od Joshuy Blocha a Neala Gaftera. Kniha obsahuje 95 krátkých hříček, rébusů a hádanek, které pěkně prozkouší vaši pozornost a znalosti temných zákoutí Javy.

Kniha je to zajímavá, člověk si toho hodně připomene, popřípadě naučí. Když má dost trpělivosti a nepřeskakuje rovnou na řešení, tak si může pěkně polámat hlavu. Schválně, kdo z vás by uhodl jak nadeklarovat i, tak aby byl následující cyklus nekonečný.

while (i==i+1){}

Řešení nebudu prozrazovat, nechám vám to za domácí úkol.

Nejen že jsem se u knihy pobavil, dokonce jsem se i naučil jeden docela užitečný trik. Je to řešení rébusu číslo 53.

Mějme třídu

public class Thing
{
	public Thing(int t){...}
	...
}

Implementujeme jejího potomka, v kterém potřebujeme spočítat nějakou hodnotu, tu si uložit a zároveň ji předat do konstruktoru předka. Tzn. potřebujeme udělat něco takového:

public class MyThing extends Thing
{
	private final int arg;
	public MyThing(){
		super(arg = SomeOtherClass.func());
	}
	...
}

Samozřejmě, návratová hodnota dané funkce se často mění a my potřebujeme aby naše řešení sneslo zátěž z více vláken. Zapoměl jsem se zmínit, že předchozí kód nejde zkompilovat, kompilátor vám vynadá, že nemůžete referencovat arg před tím, než zavoláte konstruktor předka.

Já vím, že vám je to naprosto jasné. Vzpomínám si ale, že jsem jednou narazil na podobný problém a nakonec jsem ho nevyřešil. Musel jsem to nějak obejít. A přitom je řešení tak snadné a elegantní. Tak co přijdete na něj sami?

public class MyThing extends Thing
{
	private final int arg;
	public MyThing(){
		this(SomeOtherClass.func());
	}
	private  MyThing(int i)
	{
		super(i);
		arg = i;
	}
	...
}

Docela užitečná finta.

Takže abych to shrnul, knížka je to zábavná i poučná. Naučíte se spoustu věcí o různých podivnostech v Javě. Na můj vkus je v knize trochu moc hádanek týkajících se různých celočíselných přetečení, zaokrouhlovacích chyb a podobně. To jsou podle mého názoru věci, s kterými se setkáte opravdu výjimečně. Ale i tak si myslím, že si kniha zaslouží sedm hvězdiček z deseti. Tomu kdo si chce počkat až to zfilmujou, doporučuji následující trailer.

Zpětná kompatibilita

Dnes budu psát o zpětné kompatibilitě v Javě. Předem upozorňuji, že nejsem expert na dané téma, spíš si chci jen ujasnit myšlenky. Takže když někdo narazíte na chybu v mých jinak bezchybných myšlenkách, tak to prosím pěkně rozmázněte v diskuzi pod článkem. Rád se něco přiučím.

Co to tedy je zpětná kompatibilita? Zpětná kompatibilita je, když moje staré programy běží i v novém prostředí. Kdo chce vznešenější definici, ať si ji laskavě najde sám. Jednoduchý příklad. Vezmu starou hru pro DOS a pustím jí ve Windows. Když poběží, vím že byla zachována zpětná kompatibilita, když ne, tak si přečtu skvělý článek od Joela, v kterém vysvětluje proč tomu tak není.

V Javě se její autoři snaží zpětnou kompatibilitu zachovávat. Ale aby to nebylo tak jednoduché, tak hlavně binární. To znamená, že program zkompilovaný pod Javou 1.4 spustím v JRE verze 6. Super. Samozřejmě naskytnou i výjimky, ale je velká pravděpodobnost, že ten program poběží. Což potěší naše zákazníky. Ti mohou program, který před lety draze zakoupili, používat i na nejnovějších JRE.

To je binární kompatibilita. Ale co zdrojáky? Ty by teoreticky měly být taky kompatibilní. Měl bych být schopen zkompilovat staré zdrojové kódy novým JDK. Tady už můžu narazit na víc problémů. Naštěstí se je SUN snaží vyjmenovat v dokumentaci (Java 5, Java 6). Takže to vypadá, že i na straně zdrojových kódů by mělo být vše v pořádku. Tedy až na pár obskurních případů.

To by bylo taky super, kdyby to ovšem byla pravda. V té dokumentaci se tak nějak zapomněli zmínit, že přidávají metody do existujících rozhraní. Nejlépe je to vidět na třídě java.sql.Connection. Pokud jenom používáte instance tříd implementujících toto rozhraní, tak je všechno v pohodě. Pokud si ho ale troufnete implementovat sami, narazíte na problém (viz. tento chudák). V nové verzi vaše implementace nebude úplná, bude jí chybět pár metod. Pokud namítáte, že není moc časté implementovat si JDBC driver, tak si představte, že chcete vytvořit prachobyčejný wrapper. Třeba kvůli logování. To je věc, s kterou už se v životě můžete setkat. Váš wrapper bude skvěle fungovat do té doby, než se ho pokusíte zkompilovat pod novou verzí. Kompatibilita na úrovni zdrojového kódu jde do háje. Nejen to. Představte si situaci, kdy ten wrapper bude zkompilovaný ve staré knihovně, kterou jen používáte. Když zavoláte třeba Connection.getNClob(), tak to samozřejmě spadne. To už není tak super.

(Měl bych brzdit, aby se na mě Roumen zas nenaštval.) Ono udržet zpětnou kompatibilitu a zároveň jazyk rozvíjet je hodně těžké. Možná i nemožné. Můžeme si vybrat to nebo ono, obojí mít nemůžeme. Proto se ozývají hlasy, že by Java měla zpětnou kompatibilitu zahodit. Já s nimi nesouhlasím. Občas se totiž pohybuji mezi konzervativními klienty. Nedávno se mě jeden člověk od AS400 zeptal něco v tomto smyslu. „My máme program v Cobolu, který je asi dvacet let starý. Nejen že jsme schopni ho dodnes provozovat, ale i upravovat. Je něco podobného možné i v Javě?“ Jako odpověď jsem blekotal něco v tom smyslu, že když bude mít všechny knihovny a kompilátor a JRE tak asi ano. Ale moc jistý si nejsem. A to jsme naštěstí nezabrousili do témat jako je podpora starších verzí atp. (pokud se chcete vyděsit, klikněte zde).

Takže abych to uzavřel, zpětná kompatibilita je dobrá věc. Nikdy se ale nedá udržet na 100%. Tedy dá, ale jen za cenu stagnace. Jak tak sleduji situaci kolem vývoje Javy, tak stojíme na křižovatce. Rozhoduje se jestli chceme stagnovat nebo se chceme vyvíjet. Nerad to přiznávám, ale jsem spíš pro tu stagnaci. Respektive velmi opatrný vývoj. Pokud chcete nové cool věci, používejte třeba Groovy. To mi připadá jako rozumný kompromis. Konzervativci zůstanou u Javy a ti ostatní se mohou vrhnout na neprobádaná pole skriptovacích jazyků. Když je budou pouštět v JVM tak se za nimi možná časem vydají i ti konzervativci.