[Javalist] Segítség! Java7 compiler BUG???

Peter Verhas peter at verhas.com
2012. Júl. 24., K, 23:26:37 CEST


Mitől lesz jó egy pattern? Ezek a saját gondolataim:

1. A legfontosabb, hogy a pattern alapján készült programok működnek, azaz maga a pattern, mint tervezési minta nem hibás. Ez alapvető.

2. Majdnem ilyen fontos, hogy a pattern alapján készült programoknak csak az elenyésző része legyen hibás azon okból kifolyólag, mert rosszul implementálták a patternt. Ha ugyanis van egy olyan pattern-em, ami megfelel az 1-es kritériumnak, de olyan bonyolult, vagy kacifántos, hogy az átlag programozó észre sem veszi, hogy mikor tért el tőle a megvalósítás során, vagy azt nem veszi észre, hogy olyan problémánál használja, amikor az nem megfelelő, mint pattern, akkor azt a pattern-t el kell felejteni, nem tölti be a feladatát.

3. A pattern alapján készülő kódok legyenek hatékonyak, azaz a szükségesnél lényegesen több memóriát, processzor időt, futási időt, és egyéb erőforrásokat ne használjanak. Ez persze a kódolástól is függ, de ha a tipikus kódolási hibákra rá- vagy éppen megvezet egy pattern, akkor az a pattern nem jó.

4. A pattern alapján készülő kódok legyenek karbantarthatóak, azaz egyszerű legyen őket olvasni. Ez persze megint olyan, hogy nem csak a patterntől függ, de a pattern maga ezt nagyban tudja rossz irányba terelni ha maga a pattern nem megfelelő.

5. A pattern alapján készülő kódok legyenek olyanok, hogy hatékony végrehajtható kódot lehessen belőlük fordítani. Ez nem ugyanaz, mint a 3. pont. Ott elsősorban az algoritmikus hatékonyságra kell gondolni, míg itt optimalizációra. Tipikusan ha egy pattern buborék rendezést ír le egy rendezési feladatra (ami a pattern része), azt már optimalizálhatja a fordító amennyit akarja, nem lesz belőle hatékony kód. Ez a 3. pont. Ugyanakkor olyan kódolási pattern-ek, mint felesleges átmeneti változók használata, és hasonlók komoly hatással lehetnek a generált kód sebességére, amennyiben nem áll rendelkezésre egy megfelelően hatékony optimalizáló fordító. A Java esetében rendelkezésre áll, ezért ezt az 5. pontot gyakorlatilag epsilon fontossággal tekinthetjük.

Az, hogy null értéket adunk-e vissza, vagy exception-t dobunk valamilyen tervezési minta szerint igazán a 4. pontot érinti.

Technológiai okok miatt C++ és C# (általánosan .NET) környezetben nem szeretünk exception-t dobni (én magam programozni sem szeretek ezekben a környezetekben, nem is tudok (nagyon), hát még kivételt dobni). Ezekben a környezetekben a kivétel dobása drága, egészen más a kivételek szerkezete, és ezért nem is ad megfelelő információt. Tipikusan nincs benne a stack trace, ezért ha egy szinttel feljebb, mint ahonnan dobták nem kapjuk el, akkor már nem is lehet tudni, hogy honnan dobták. Akkor meg már olcsóbb futási időben a megfelelő hibakód visszaadása, és ennek nagy hagyománya van unix C és Windows C programozási környezetben, régen bevált. [Megjegyzés: ennek a bekezdésnek az egyik fele nem első kézből való információ, csak beszélgettem .NET-es kollégákkal. A másik fele viszont ezer évvel ezelőtti C programozási emlékek megmaradt halvány foszlányai.]

A Java egészen más. Java-ban az exception hordozza a stack trace-t (vagy nem, de inkább igen, mint nem), és ebben nagyon sok szimbolikus információ benne van. Nem kell ott elkapni, ahol dobják, vagy egy szinttel feljebb, mert minden szükséges információ benne van, és ezért elég ha ott kapjuk el, ahol kezelni tudjuk. Ezért lett egyébként kitalálva a hiba dobás, és véleményem szerint a .NET környezet az exception dobás, mint pattern funkcionalitásának egy részét feláldozta a teljesítmény oltárán, amit viszont mostanra (Java6, 7) kezd túlhaladni az idő.

Ezután a bevezető után próbáljuk meg eldönteni, hogy melyik a jobb pattern: null-t visszaadni, vagy kivételt dobni egy speciális helyzetben. Nézzük meg a következő kis kódot:

		BufferedReader r = new BufferedReader(new InputStreamReader(
				new FileInputStream(file)));
		String line = null;
		while ((line = r.readLine()) != null) {
			System.out.println(line);
		}

Aránylag egyszerű, tiszta és világos kód, bár a 'while' feltételben az értékadás egy kicsit C örökség, és nem a Java szokásos stílusa. Hogyan nézne ki ez a kód akkor, ha a 'readLine' nem null-t adna vissza a fájl végén, hanem kivételt dobna:

		try {
			while ((line = r.readLine()) != null) {
				System.out.println(line);
			}
		} catch (IOException e) {
			// and now what?
			e.printStackTrace();
		}

első ránézésre nem világos, hogy mit kell keresnünk a catch ágban. Kihúzták az USB diszket, amit olvastunk vagy véget ért a fájl. Ez el kell döntenünk az IOException alapján. Mondjuk lehetne így:

		try {
			while ((line = r.readLine()) != null) {
				System.out.println(line);
			}
		} catch (EOFException e) {
			// unexpected?
		} catch (IOException e) {
			// and now what?
			e.printStackTrace();
		}

Viszont az EOFException dokumentációja szerint ezt akkor kell dobni, amikor váratlanul értük el a fájl végét. Itt pedig nagyon is vártuk, azért tettük bele egy 'while' ciklusba. Ez így jóval kevésbé olvasható.

Ezért a konkrét pattern ismerete nélkül én nem mondanám, hogy a null visszatérési érték rossz pattern. Vagy rossz, vagy nem.

--
Verhás Péter
peter at verhas.com
+36(30)9306805
skype: verhas




On 2012.07.24., at 9:38, Gábor Garami wrote:

> Nyilvan. Ettol meg rossz pattern lesz a null visszateres, csak vannak
> olyan jol definialt interfacek, amik rossz pattern menten szulettek.
> 
> Garami Gábor
> E-mail: gabor.garami at hron.me
> Tel: +36 20 235 9621
> MSN: hrgy at vipmail.hu
> Skype: hron84
> 
> 
> 2012/7/23 Peter Verhas <peter at verhas.com>:
>> Azért a való életben az is előfordul, hogy nem te szabod meg, hogy a metódus
>> mikor dob kivételt, és mikor tér vissza null értékkel. Ezzel nem mondok
>> neked ellent, csak van olyan, amikor egy jól definiált interface-t
>> valósítasz meg.
>> 
>> --
>> Verhás Péter
>> peter at verhas.com
>> +36(30)9306805
>> skype: verhas

--------- következő rész ---------
Egy csatolt HTML állomány át lett konvertálva...
URL: <http://lists.javaforum.hu/pipermail/javalist/attachments/20120724/be290a21/attachment.html>


További információk a(z) Javalist levelezőlistáról