{"id":98,"date":"2007-10-20T06:07:00","date_gmt":"2007-10-20T06:07:00","guid":{"rendered":"http:\/\/www.tutego.de\/blog\/javainsel\/?p=98"},"modified":"2007-10-20T06:07:00","modified_gmt":"2007-10-20T06:07:00","slug":"buchkritik-das-java-codebook","status":"publish","type":"post","link":"https:\/\/www.tutego.de\/blog\/javainsel\/2007\/10\/buchkritik-das-java-codebook\/","title":{"rendered":"Buchkritik: Das Java Codebook"},"content":{"rendered":"<p><i>Marcus Wiederstein, Marco Skulschus, Mark Donnermeyer, Dirk Brodersen, Benjamin Rusch. Addison-Wesley. ISBN 3-8273-2059-3. 2003. 858 Seiten<br \/><\/i>Programmabschnitte, sog. Snippets, gibt es im Internet genug (wir w\u00e4re es alternativ mit dem <a href=\"http:\/\/www.exampledepot.com\/\">Java-Almanac<\/a>?) und wer eine Suchmaschine bedienen kann, wird immer, ja immer, die Bibliothek oder den Quellcode-Schnippsel finden, die er sucht. Um so erstaunlicher finde ich es, wenn Verlage Quellcode-Kochb\u00fccher ver\u00f6ffentlichen, ob sie nun Codebook oder Cookbook hei\u00dfen. Ernsthaft: Wer eine Klasse zur Bruchrechnung sucht oder ein Beispielprogramm zum Aufbau eines Swing-Fensters, geht sicherlich nicht zum Regal, sucht im Index nach &#8222;Bruch&#8220; und holt sich dann die Klasse von der CD. Daher die Frage &#8211; ist ein Buch wie &#8222;Das Java Codebook&#8220; notwendig? Das Positive zuerst: Die Kapitel \u00fcber regul\u00e4re Ausdr\u00fccke und Applets (Daten im Cookie speichern, Uploads, Applet-Konverter f\u00fcr Tags), die kleinen Beispielprogramme, in denen man etwa \u00fcber ein BufferedImageOp.filter Bilder heller\/dunkler macht, sowie Hinweise zur Transparenz und der Index finde ich prima. Eigentlich sind B\u00fccher mit Quellcode gut, denn Software-Entwickler lesen im Allgemeinen zu wenig. Das Studium von Quellcode hilft jedem Entwickler, neue Idiome zu lernen und seine F\u00e4higkeiten zu verbessern. Je nach Schwerpunkt des Buches lernt man weitere M\u00f6glichkeiten der Standardbibliothek kennen oder neue Open-Source-Bibliotheken. Soweit die M\u00f6glichkeiten guter Codebooks. Leider hat das Java Codebook dann doch die eine oder andere Schwachstelle, so dass man Software-Entwicklern vielleicht doch besser direkt zur Google-Suche raten sollte. (Immerhin gibt es das Buch als PDF.) Die Probleme im Detail: Die Klasse<\/p>\n<pre>public class CalcExample {<br \/> static final BigDecimal ZERO = new BigDecimal(0);<br \/> static final BigDecimal ONE = new BigDecimal(1);<br \/> static final BigDecimal FOUR = new BigDecimal(4);<\/pre>\n<p><\/p>\n<p>deklariert drei Variablen (Sichtbarkeit k\u00f6nnte auch anders sein), doch vergisst, dass es ZERO, ONE, TEN schon in BigDecimal gibt. In anderen Beispielen gef\u00e4llt mir die Schreibweise der Felder nicht. Einiges ist nach der Bauart String []array, also Typ, Leerzeichen, Variablenname aufgebaut. Das habe ich nach 11 Jahren Java hier zum ersten Mal gelesen. Zumal sich die Autoren hier uneins zu sein scheinen, denn sie verwenden auch String[]. Die f\u00fcnf Autoren des Buchs folgen demnach keiner einheitlichen Coding-Konvention. Ein weiteres Thema betrifft die Methodennamen: \u00dcberwiegend werden englische Bezeichner (setNumber, less100, \u2026) gebraucht, doch lassen sich innerhalb eines Beispiels Vermischungen mit deutschen Variablennamen entdecken, wie das Feld ZEHN. Einige Autoren m\u00f6gen (immer noch) die Klassen Hashtable und Vector, andere nutzen doch besser List und Map &#8211; hat denn keiner der Autoren die anderen Kapitel gelesen und kommentiert? Bei den Datenstrukturen frage ich mich wirklich, was denn arrayList.add(new String(new java.util.Date().toString())); f\u00fcr eine Anweisung sein soll. Und warum wird ein Stack noch mal neu implementiert? OK, der Original-Stack erbt von Vector, was vom Design total verpfuscht wurde, aber dann k\u00f6nnte man doch immer noch den neuen Stack so implementieren, das er an den alten Stack delegiert, anstatt alle Operationen komplett mit einer ArrayList neu zu implementieren. (Und dann noch die fragw\u00fcrdige Methode search() zu \u00fcbernehmen.) Eine weitere Schwachstelle, die ich in der Insel weitestgehend versuche zu vermieden, sind Windows-spezifische Pfadangaben, wie etwa bei new FileOutputStream(&#8222;c:\\\\buecher.ser&#8220;). Bei IO-Beispielen fehlt oft das close() im finally. Vor allem bei HTTP-Servern ist das kritisch. Im JSP-Kapitel findet sich pl\u00f6tzlich ein JDBC-Close im finally; also hat es nicht jeder der Autoren vergessen. Frage: Was gibt dieses Programm bei Argumenten auf der Kommandozeile aus?<\/p>\n<pre>package javacodebook.io.stdout;<br \/>public class StdOut {<br \/> public static void main(String[] args) {<br \/>  String text = \"Hallo Welt\";<br \/>  \/\/Wenn Text angegeben, dann diesen ausgeben<br \/>  if(args.length &lt; 1)<br \/>   for(int i = 0; i &lt; args.length; i++)<br \/>    System.out.println(args[i]);<br \/>  else<br \/>   System.out.println(text);<br \/>  }<br \/>}<\/pre>\n<p><\/p>\n<p>Dass ist wohl eher eine Zertifizierungsfrage statt eines sinnvollen Codebeispiels, denn ist die Anzahl der Argumente kleiner 1, gibt es keine Argumente und die Schleife ist nutzlos. Genauso falsch ist der Satz &#8222;JDBC benutzt dabei die Interfaces Connection, Driver und DriverManager.&#8220;&nbsp;Schade, denn DriverManager ist eine Klasse. Sollte es auch, denn aus dieser Zentrale erh\u00e4lt man durch die statische Methode getConnection() eine Verbindung. Im Anhang finden sich dann noch ein paar Dreher in der Gro\u00df-\/Kleinschreibung. Z. B. beginnen einige Bezeichner in der Tabelle &#8222;Java Native Interface Typen&#8220; mit Gro\u00dfbuchstaben. Besser w\u00e4ren &#8222;int&#8220; statt &#8222;Int&#8220; sowie &#8222;void&#8220; statt &#8222;Void&#8220; usw. \u00c4hnliches gilt f\u00fcr JscrollPane, was zu JScrollPane werden sollte. Unter &#8222;Relationale Operatoren&#8220; findet sich folgender Satz bei ==-Operator: &#8222;a == b ergibt true, wenn a gleich b ist. Handelt es sich bei a und b um Referenztypen, so ist der R\u00fcckgabewert dann true, wenn beide auf dasselbe Objekt zeigen.&#8220; Wir sollten den Sonderfall a = b = NaN aber nicht Au\u00dferacht lassen, denn gerade dann ist a = b, aber das Ergebnis <i>nicht <\/i>true. In der Tabelle &#8222;Klassenobjekte f\u00fcr den primitiven Datentyp&#8220; sollte Void besser nicht auftauchen, da es sich nicht um einen primitiven Datentyp handelt. Oder Void stehen lassen, aber die \u00dcberschrift anpassen. Einige Kritikpunkte betreffen die Auswahl der Klassen. Die Klasse Fraction sollte vielleicht besser einer bekannten Open-Source-Bibliothek entstammen und die Matrizen sowie der umfangreiche Quellcode nicht unbedingt abgebildet werden. F\u00fcr CSV-Dateien w\u00e4ren popul\u00e4re Standard-Klassen sinnvoller. Der Tipp 186 f\u00fcr Timer sollte diesen nicht selbst implementieren, sondern die zwei (!) Timer-Klassen der Java-Lib vorstellen. Da ein Codebook grunds\u00e4tzlich eine unendliche Sache ist, k\u00f6nnten weitere Snippets eingebracht werden. Bei den Zufallszahlen w\u00e4re z. B. SecureRandom gut untergebracht. Das Beispiel FindInFile, was h\u00e4ndisch nach einem String in einer Datei sucht, l\u00e4sst sich viel effektiver mit NIO (mit <a href=\"http:\/\/72.5.124.55\/javase\/6\/docs\/technotes\/guides\/io\/example\/Grep.java\">Standard-Beispiel von Sun<\/a>) l\u00f6sen. Das NIO-Kapitel kommt mit nur zwei Beispielen daher (Datei kopieren und File-Lock). Das ist eine magere Ausbeute. Sp\u00e4ter kommt noch ein NIO-Server dazu. Der Verweis auf eine einfache NIO-Bibliothek (wie <a href=\"http:\/\/xsocket.sourceforge.net\/\">xSocket<\/a>) w\u00e4re dann w\u00fcnschenswert. Um ein Fenster mittig zu positionieren, muss man nicht rechnen, hier reicht <i>eine<\/i> Java-Funktion. Wenn es sich schon um ein Java 1.4 Buch handelt, dann sollte ImageIO Grafiken laden. Die Swing-Beispiele sind relativ unspektakul\u00e4r. Hier w\u00e4re es wohl sinnvoller statt &#8222;wie erzeuge ich einen Button&#8220; oder &#8222;wie etwas mehr mit den Modellen zu machen&#8220;, einen Dateibaum in ein JTree zu setzen. Und stilistisch wertvoll ist der Hinweis mit der JDBC-Verbindung in einem JSP-Tag sicher nicht. Und wo sind die <a href=\"http:\/\/java.sun.com\/blueprints\/corej2eepatterns\/Patterns\/DataAccessObject.html\">DAO<\/a>s? Bei JMS stimmt es zwar grunds\u00e4tzlich, dass in einer Tabelle bei Programmiersprachenunabh\u00e4ngigkeit &#8222;Nein&#8220; steht und bei HTTP &#8222;Ja&#8220;, doch allgemeing\u00fcltig ist das nicht. F\u00fcr <a href=\"http:\/\/activemq.apache.org\/\">ActiveMQ<\/a> gibt es ein standardisiertes Protokollformat (<a href=\"http:\/\/activemq.apache.org\/openwire.html\">OpenWire<\/a>) und APIs f\u00fcr diverse andere Programmiersprachen. Das gleiche gilt auch f\u00fcr IBMs WebSphere MQ (fr\u00fcher MQSeries) &#8211; sicherlich eines der besten MOMs -, das heterogene Plattformen verbindet. Einen XML-Parser \u00fcber die Anweisung org.apache.xerces.parsers.DOMParser parser = new org.apache.xerces.parsers.DOMParser(); statt \u00fcber JAXP zu erfragen ist nicht sch\u00f6n sondern fast grob fahrl\u00e4ssig. Zudem haben auch die JAXP-Parser Features, obwohl die String-Kennungen dann immer ein wenig anders aussehen. Zu Tipp 196: Wann immer man sich mit getGraphics() einen Grafik-Kontext holt, sollte man ihn auch wieder freigeben. Dieser Hinweis fehlt leider in den Beispielen. Farbkonstanten sollten gro\u00df geschrieben sein, also Color.WHITE, statt Color.white, zumindest seitdem Sun diese Konvention in Java 1.4 eingef\u00fchrt hat.<\/p>\n<blockquote><p><\/p>\n<p>Erst wenn der letzte Programmierer eingesperrt und die letzte Idee patentiert ist, werdet ihr merken, dass Anw\u00e4lte nicht programmieren k\u00f6nnen. <\/p>\n<\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>Marcus Wiederstein, Marco Skulschus, Mark Donnermeyer, Dirk Brodersen, Benjamin Rusch. Addison-Wesley. ISBN 3-8273-2059-3. 2003. 858 SeitenProgrammabschnitte, sog. Snippets, gibt es im Internet genug (wir w\u00e4re es alternativ mit dem Java-Almanac?) und wer eine Suchmaschine bedienen kann, wird immer, ja immer, die Bibliothek oder den Quellcode-Schnippsel finden, die er sucht. Um so erstaunlicher finde ich es, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","_links_to":"","_links_to_target":""},"categories":[6],"tags":[],"class_list":["post-98","post","type-post","status-publish","format-standard","hentry","category-rezension"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/98","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/comments?post=98"}],"version-history":[{"count":0,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/98\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/media?parent=98"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/categories?post=98"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/tags?post=98"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}