Sunday, July 29, 2007

Java Exception Handling Antipattern

Der Artikel "Exception-Handling Antipattern" auf java.net erklärt wie Exceptions in Java verwendet und nicht verwendet werden sollten.

Der Artikel ist für jeden Java-Entwickler lesenswert. Die in dem Artikel genannten Antimuster sind:

  • Log and Throw
  • Throwing Exception
  • Throwing the Kitchen Sink
  • Catching Exception
  • Destrutice Wrapping
  • Log and Return Null
  • Catch and Ignore
  • Throw from within Finally
  • Multi-Line Log Messages
  • Unsupported Operating Returning Null
  • Ignoring InterruptedException
  • Relying on getCause()

Die Regeln sollten eigentlich (weitgehend) Common Sense sein, aber (nach leidvoller Erfahrung der letzten Monate) bin ich der Meinung, dass man kann selbst Common Sense nicht oft genug wiederholen.

Ich würde noch drei Empfehlungen hinzufügen, die vielleicht zu offensichtlich sind, aber dennoch irgendwie in die Liste passen. Java-Pros werden wahrscheinlich (zumindest für Empfehlung 1) Gegenbeispiele finden, aber grundsätzliche sind dies gute Ratschläe.

  1. Niemals Exceptionen von Error und Untertypen werfen.
    "Error" ist in der Regel einzig und allein der Virtuell Maschine und dem SDK vorbehalten sein und sollte so nur in Ausnahmefällen von Benutzercode gefangen werden. Schon gar nicht sollte Benutzercode Error-Exceptions werfen.
    In der Dokumentation zu Error heisst es:
    <blockquote>
      <p>An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions.</p>
    </blockquote>
    
    <p>In der Regel verwendet man eine Error-Klasse für einen ganz anderen Zweck als in der Dokumentation angegeben, nur weil der Name passend klingt z.B. VerifyError für die Verifikation von Benutzereingaben. Eigene Exceptions oder RuntimeExceptions für problematische Zustände sind die oft die bessere Wahl.</p>
    
  2. System.exit() sollte nicht in catch aufgerufen werden.
    Ich gestehe zu, dass es von dieser Regel Ausnahmen geben kann, aber das Anliegen von Exceptionhandling ist, dass sich der Code um die Fehlerbehandlung kümmert, der weiß ein Fehler behandelt werden soll. Nur niemand eine Exception behandeln kann, soll das Programm beendet werden.

    <p>Wenn man System.exit() in catch aufruft, dann nehme ich Methoden weiter oben im Stack die Möglichkeit den Fehler zu behandeln. In der Regel ist dies nicht sinnvoll.</p>
    
    <p>System.exit() sollte in der Regel sowieso gemeiden werden, da z.B. alle Cleanup-Operationen nicht durchgeführt werden und der Code mit System.exit() mit einem Schlag quasi-untestbar wird.</p>
    
  3. Eine NullPointerException sollte nicht manuell geworfen werden.
    Eine NullPointerException ist eine wirklich meise Art von Exception, weil sie oft auf Fehler hinweisen, die an ganz anderen Stellen im Code verursacht wurden. Zum Beispiel sind NullPointerExceptions tief aus dem Code eines J2EE-Containers ist so das schlimmestem was passieren kann. Es ist nur schwer möglich den Grund für den Fehler zu suchen.

    <p>Wenn man den Gedanken hat durch "throw new NullPointerExcecption()" manuell eine NPE zu werfen, sollte man besser davon Abstand nehmen und eine Exceptionklasse wählen, die besser den wirklichen Fehler beschreibt z.B. IllegalArgumentException("xy is null").</p>
    

Studienfond OWL: Bewerben oder nicht?

Viele Studenten an der Universität Paderborn werden schon den Flyer vom "Studienfond OWL" in der Mensa gesehen haben. Aber was dahinter steckt, ob es für einen selbst relevant ist, bleibt unklar. Grundsätzlich ist es die Chance auf ein Stipendium von 1000 Euro pro Jahr (und andere Vorteile). Es ist nicht, wie einige Studenten glauben, ein Angebot für einen Studienkredit, der zurückgezahlt werden muss. Ein Stipendium ist ein Stipendium.

Der Studienfond OWL ist ein Verein, der von den fünf Hochschulen in OWL gegründet wurde und an Studenten an diesen Hochschulen Stipendien vergibt. Das besondere an dem Studienfond ist, dass er sich grundsätzlich aus Spenden von Privatpersonen und Firmen (besonders aus der Region) finanziert. Gegründet wurde der Studienfond (auch wenn er selbst diesen Zusammenhang gerne verneint, um nicht Teil der politischen Debatte zu werden) im Zuge der Einführung von Studienbeiträen. Nicht aus Zufall wurde die Förderung zunächst einmal auf 1.000 Euro für ein einjähriges Stipendium festgesetzt. Es sollten zumindest die Studienbeiträe ersetzt werden. Im Grunde ist es ein Kompromiss zwischen einer höheren Förderung und der Unterstützung von mehr Studenten.

Aber es soll dort nicht nur um Geld gehen. Zusätzlich will der Studienfond auch immateriell fördern. Dies geschieht durch ein Angebot von "Networking"-Veranstaltungen wie Firmenbesichtigungen, Vorträen und Unternehmergesprächen. Ebenso wurden zum Beispiel Freikarten für die Hannover Messe von Unternehmen zur Verfügung gestellt. Auch bei der Vermittlung von Praktika und "studienförderlichen Jobs" - scheinbar das neue Modewort der Universitätsleitung - soll geholfen werden.

Der Studienfond OWL will zwei Gruppen von Studenten fördern:
1) Akademisch erfolgreiche Studenten: Die Homepage spricht davon, dass die Studenten unter den besten 10% sein sollten. Zusätzlich ist auch ein Empfehlungsschreiben von einem Hochschulprofessor notwendig.
2) Studenten in finanzieller Notlage, die trotz Bedürftigkeit kein BaföG erhalten. Es sollen finanzielle Notlagen ausgeglichen werden, die die Weiterführung des Studiums gefährden würden.
Dabei sind die Bedingungen sollten eher als grobe Richtlinien zusehen. Es kommt auch immer darauf an, wie viele Studenten sich beworben haben und wie viele Spenden zu verteilen sind.

Womit wir zu der wichtigsten Frage kommen: Wie stehen die Chancen?
Ich glaube, dass alle Studenten, welche die Bedingungen mehr oder weniger erfüllen, ziemlich gute Chancen haben. Noch bewerben sich wenige Studenten. Gleichzeitig scheint die Sammlung von Spenden ganz gut zu klappen. Die Chancen sind heute so gut wie nie zuvor und sie werden vielleicht auch nie wieder so gut werden, wie sie jetzt sind.

Ist alles Gold, was glänzt: Nein, natürlich nicht. Noch sind die Stipendien verhältnismäßig gering (auf der Höhe von Büchergeld bei anderen Organisationen wie der Friedrich-Naumann-Stiftung). Der (auf der Homepage angekündige, aber wohl nicht 100% "durchgehaltene") Ausschluß von Bafög-Empfängern erscheint mir ziemlich unsinnig und es könnten auch insgesamt mehr Stipendien sein. Im Moment sind es 12 an der Uni Paderborn. Insgesamt ist das Ganze ist ein Prozess der sich gerade am Anfang befindet.

Ich bin der Überzeugung, dass eine Fundamental- und Schmähkritik, wie sie von der Asta Bielefeld vorgebracht wurde, nicht angebracht ist. Die Autoren scheinen den Studienfond als reines Täuschungsmanöver zu sehen und gehen dabei auch noch kreativ mit Fakten um. Ich glaube hingegen, man ist ehrlich bemüht, zu unterstützen. Auch die Qualität und Quantität der Förderung wird wohl (irgendwann) ausgebaut. Und man sieht und (oder vielleicht auch: man will nicht sehen) das nie alles von Beginn an perfekt klappt. Es ist wie oben schon gesagt ein Prozess.

Sollte man sich bewerben? Ja, wenn man glaubt die Bedingungen mehr oder weniger zu erfüllen, denn man hat wenig zu verlieren und ein Stipendium zu gewinnen. Weitere Infos gibt es auf der Webseite des Studienfonds OWL. Die Bewerbungsformulare sind auch nicht viel länger als die Formulare zur Anmeldung zu Prüfungen.

Dieser Artikel wurde (in geringfügig anderer Form) in der "Matik 59″, dem Magazin der Fachschaft für Informatik und Mathematik an der Universität Paderborn veröffentlicht. Veröffentlichung an dieser Stelle mit Genehmigung der Fachschaft.

Wednesday, July 18, 2007

Vector vs. Collections.synchronizedList

Every Java developer knows (or should know), that concurrent access to a list has to be synchronized.

In Java there are two build in ways to synchronize lists directly:

  1. java.util.Vector: The original implementation of an dynamic array from the old days of Java 1.0 - Java Stone Age.
  2. the factory method Collections.synchronizedList which produces a synchonized wrapper around a list (e.g. ArrayList or LinkedList).

There is also the list implementation CopyOnWriteArrayList from the package java.util.concurrent, which I will ignore here most of the time.

When I have to synchronize the access to a list in new code, which variant should be used

Depending from the concrete usage it could be an ultimate advance of the factory method, that the implementation of the underlying list can be chosen. If Vector is used, it is obviously a bad idea to delete elements from the middle of a list on a regular basis. The O calculus strikes back.

Furthermore the performance comparison shows surprising clear differences.

At the artificial task to insert 2^17 elements sequentially into the list, Vector needs 8 percent less time than the synchronized ArrayList. The advance is caused by the fact that Vector doubles the capacity of its internal data structure every time a threshold is reached. The ArrayList increases its internal array only about 50%. As a result the ArrayList copies its data more often into new arrays.

The iteration over 2^17 elements the vector needs six times longer then the synchronized variant of the ArrayList. This huge difference is caused by the locking behavior of the classes. Vector locks every single access to next(). The synchronizedList-Implementation doesn’t lock the access over an iterator as described in the javadoc. This breaks the rule that the client should never be responsible for thread safety of a class, but it allows coarse-grained locking around the whole loop. This avoids the possibility of ConcurrentModificationExceptions. The difference between one entry and release of an critical region against the 2^17 entrances and releases, causes the surprisingly high time difference.

Of course it is also possible to lock very single access to next, e.g. when the execution of the loop body takes a longer time. With this fine-grained locking the performance would be the same as of the Vector implementation.

Another reason against vector is the ballast the class carries from the Java 1.0 time. Vector implements the List interface and offers the methods add(), remove() and so, but it also has old methods like elementAt (old get), elements (old iterator which returns an Enumeration) and insertElementAt (old add). This makes the usage not very handy.

A more subtle reason for synchronizedList is that a lot of developers use Vector all the time, even if no synchronization is needed. It is often not clear, if Vector is used with purpose or since a lack of experience or knowledge. A lot of tutorials and books don’t mention the collections api. Furthermore there are universities haven’t discovery the collections api yet.

synchronizedList documents the purpose of the code in a better way: Yes, I want synchronization. Yes, I know what I do. In very case the intention should be documented. In the javadoc and (in the ideal case) also with the Annotations from "Java Concurrency in Practice".

In my opinion Vector should be declared obsolete at least after the introduction of generics. When no synchronization is needed, a "new" list implementation should be used. In the case of multi threading a synchronized wrapper or (when the reading accesses outnumbers the write accesses) the CopyOnWriteArrayList implementation should be used. Let Vector die, its time is over.

A bit more correct: Vector locks every single access to get(), which is called by next().
[Update May, 5th, 2008: In the Javaposse Googlegroup is currently an active and interessing discussion about ArrayList vs. Vector with further details, options and surprisingly different results]

Tuesday, July 17, 2007

Artikel über Swarm Bahavior

In National Geographic Juli 2007 steht ein interessanter Artikel zur Swarm Intelligenz:

Swarm Theory: A single ant or bee isn’t smart, but their colonies are. The study of swarm intelligence is providing insights that can help humans manage complex systems, from truck routing to military robots.

Obwohl der Artikel sich weitgehend mit der Biologie beschäftigt, geht er auch auf die Umsetzung von Swarm Intelligenz in der Informatik ein.

By demonstrating the power of self-organizing models to mimic swarm behavior, Reynolds [a Computer Science Researcher] was also blazing the trail for robotics engineers. A team of robots that could coordinate its actions like a flock of birds could offer significant advantages over a solitary robot. Spread out over a large area, a group could function as a powerful mobile sensor net, gathering information about what’s out there. If the group encountered something unexpected, it could adjust and respond quickly, even if the robots in the group weren’t very sophisticated, just as ants are able to come up with various options by trial and error. If one member of the group were to break down, others could take its place. And, most important, control of the group could be decentralized, not dependent on a leader.

"In biology, if you look at groups with large numbers, there are very few examples where you have a central agent," says Vijay Kumar, a professor of mechanical engineering at the University of Pennsylvania. "Everything is very distributed: They don’t all talk to each other. They act on local information. And they’re all anonymous. I don’t care who moves the chair, as long as somebody moves the chair. To go from one robot to multiple robots, you need all three of those ideas."

Interessant zu lesen!