Sonntag, 25. Mai 2008

Enten und andere Typen

In Java-Kreisen wird gerne versucht, Ruby herunterzureden. Die Argumente dabei sind oft nicht sonderlich gut durchdacht und haben mehr mit diffusen Ängsten als mit wirklicher Kenntnis der Sachverhalte zu tun. Diese Art wertloser Diskussion ist oft anzutreffen, wenn es um zwei wirklich oder vermeintlich konkurrierende Technologien geht. Es geht hier nicht darum, die bessere zu finden, sondern darum den Wert der Investition zu erhalten, die jemand in das Erlernen einer der Alternativen gesteckt hat.

Ein Argument, daß von den Java-Befürwortern gegen Ruby of aufgebracht wird, ist, daß durch das Java-Typsystem viele Fehler schon vom Compiler gefunden werden, die in Ruby erst zur Laufzeit auftreten, was das Debuggen entsprechend teurer machen soll. Ich habe neulich ein paar hundert Zeilen lang ein etwas komplizierteres Ruby-Programm geschrieben und dabei darauf geachtet, welche Probleme auftraten und diese mit meinen Javaerfahrungen verglichen.

Duck-Typing

Häufig wird gesagt, Sprachen wie Ruby seien "untypisiert". Dies stimmt so nicht. Da Ruby objektorientiert ist, erlaubt es natürlich die Definition von Klassen und Klassen sind Typen. Was anders behandelt wird, ist die Deklaration von Variablen und Parametern. Diesen können erst einmal alle Objekte unabhängig von Typ zugewiesen werden, im Laufe der Programmausführung auch unterschiedliche Typen für dieselbe Variable. Der Typ wird erst überprüft, wenn eine Methode des Objekts aufgerufen wird. Und hier geschieht das ganz pragmatisch. Wenn die Methode vorhanden ist, so wird sie aufgerufen, ansonsten wird eine spezielle Methode aufgerufen, die alle anderen Fälle abhandelt. Diese Typisierung wird oft als Ducktyping bezeichnet: egal, was der Zoologe dazu sagen würde, wenn es nach Ente schmeckt und eine knusprige Entenhaut besitzt, dann wird es wohl Ente sein.

Jetzt gibt es die Behauptung, daß hierdurch sicheres Refactoring erschwert würde. Da ist etwas dran, doch ist die Lage nicht so hoffnungslos. Schließlich wurde das erste brauchbare Tool zum Code-Refactoring für Smalltalk entwickelt, das ein vergleichbares Typsystem besitzt.

Wie sieht es nun mit den Programmierfehlern aus? In der Tat kommen immer wieder lästige Fehler vor, die Java verhindert hätte. Allerdings handelt es sich fast nie darum, daß ein Objekt einen falschen Typ hätte. Vielmehr führen Tippfehler dazu, daß zwei Objekte da sind, wo nur eins sein sollte. Diese Art von Fehler wird in Sprachen wie Lisp und Smalltalk dadurch verhindert, daß Variablen zuerst deklariert werden müssen, ehe sie verwendet werden können. In Skriptsprachen, zu denen Ruby gehört, entsteht eine Variable in dem Augenblick, in dem sie zum ersten Mal verwendet wird. Gegenüber Python ist Ruby da sogar noch im Vorteil, da in Ruby der Gültigkeitsbereich der Variable im Namen angegeben wird (durch kein, ein oder zwei @).

Was in der Argumentation unterschieden werden sollte, ist Deklaration und Typisierung von Variablen. Wie immer erschwert es auch hier die Argumentation, wenn zwei Dinge, die nur lose etwas miteinander zu tun haben, immer wie eins behandelt werden.

Und wie war es sonst mit Ruby?

Mit Ruby schreibt man drastisch weniger Code als mit Java. Dadurch macht man natürlich auch weniger Fehler. Allerdings gibt es auch voll typisierte Sprachen, die wesentlich dichteren Code zu schreiben erlauben wie Java (z.B. Scala).

Ruby-Code ist vergleichsweise langsam. Das ist nichts Neues und macht häufig auch nichts aus. Allerdings dürfte sich die Lage demnächst auch verbessern, wenn nicht bei nativem Ruby, dann sicht durch jRuby. Letzteres scheint heute schon in vielen Bereichen schneller zu sein. Es benutzt die JVM, die ein ausgereiftes Memorymanagement Codeoptimierung mitbringt.


Sonntag, 18. Mai 2008

Ein Bild sagt mehr als tausend Worte ...

Dies ist ein beliebter Spruch, mit dem die Hersteller von graphischen Tools zur Programmentwicklung werben. Was aber bedeutet das für den Arbeitsalltag?

Lesen von Graphiken

Der zitierte Spruch bedeutet zwar, daß in einem Bild die Information von mehr als tausend Worten steckt. Dies bedeutet aber nicht notwendigerweise, daß diese Information schneller aufzunehmen wäre. Auch in ein Kunstwerk kann man sich verlieren und darin immer wieder neue Dinge entdecken. So ist das auch, wenn endlich die Tapete aufgehängt wird, nachdem der Architekt nach wochenlanger Arbeit vom DIN-A0-Plotter mit dem neuen Datenmodell zurückgekommen ist. Nach Tagen findet man dann in nur wenigen Minuten das Objekt, mit dem man gerade arbeitet und kann dann rasch feststellen, in welchem Zusammenhang es sich befindet. Vorausgesetzt die Verbindungslinien sind nicht zu lang und klar voneinander getrennt.

Meist wäre dem Betrachter wahrscheinlich eher mit einem gut verlinkten Dokument mit zusätzlichen Suchfunktionen gedient, mit denen der die Verbindungen zwischen zwei Objekten, die nächsten Nachbarn und ähnliches übersichtlich angezeigt bekäme.

Allerdings kann ein Übersichtsdiagramm, daß z.B. die wesentlichen Komponenten eines Systems und ihre Zusammenarbeit darstellt, ganz neue Einblicke ergeben.

Erzeugen von Graphiken

Der Umgang mit einem graphischen Werkzeug ist in der Regel wesentlich anstrengender wie das Schrieben von Texten. Täglich mehrstündiger Umgang mit der Maus führt bei den meisten Benutzern zu schmerzhaften Verspannungen. Außerdem ist die Informationseingabe meist deutlich langsamer. Besser sieht es aus, wenn eine textuelle Eingabe möglich ist, die dann von einer Software visualisiert wird. Dieser Ansatz ist aber eher selten.

Ebenen des Einsatzes von graphischen Werkzeugen

  • Skizzieren: Hier wird eine Idee graphisch dargestellt, wobei es nicht auf die Details ankommt, sondern nur das Prinzip dargestellt werden soll. Meist ist es hierbei schneller, die Skizze händisch zu erstellen. Ein Werkzeug, daß bei der Eingabe zuviel überprüft ist weniger hilfreich.

  • Modellieren: Hier ist es wichtig, daß der modellierte Aspekt vollständig und korrekt erfaßt wird. Es sollte aber nur auf einer bestimmten Abstraktionsebene gearbeitet werden. Eine Detaillierung bis zu den technischen Details gehört hier nicht hin. Da das Modell abstrakter sein sollte als das modellierte System, ist es zwar manchmal möglich, eine technische Implementierung automatisch zu erstellen (MDA-Ansatz), aber der umgekehrte Weg ist wenig sinnvoll.

  • Visualisieren: Die Graphik ist hier nur eine alternative Darstellung des Programms. Viele Werkzeuge erlauben Änderungen in beiden Darstellungen.

UML-Dilemma

Die oben beschriebenen Einsatzmöglichkeiten werden alle mehr oder weniger gut von den gängigen UML-Werkzeugen unterstützt. Dabei gibt es aber das Problem, daß die Validierung der Diagramme im einen Fall notwendig, im anderen aber eher weniger sinnvoll ist. Dies könnte dadurch geregelt werden, daß es konfigurierbare Sätze von Validierungsregeln gibt, die konfiguriert werden könnten. Dies ließe sich z.B. gut mit OCL durchführen. Die meisten UML-Werkzeuge sind aber nicht entsprechend flexibel.

Graphisches Programmieren

Immer wieder kommen Werkzeuge auf den Markt, die eine graphische Benutzeroberfläche zur Programmerstellung bieten. Derzeit ist das z.B. für BPEL sehr beliebt. Diese Tools haben gewisse Probleme:

  • Meist ist zusätzliche Information hinter den Symbolen verborgen. Was zuerst sehr einfach aussieht, entpuppt sich dann doch als komplex.

  • Sich wiederholende Aufgabe lassen sich auf der graphischen Ebene schlecht automatisieren. Hier muß die Textebene verwendet und auch verstanden werden.

  • Manchmal werden vom graphischen Editor Dinge nicht unterstützt, die in der Textdarstellung eigentlich möglich sein müßten. Ob das resultierende Programm dann lauffähig ist, ist zunächst unklar.

Versionierung und Vergleich

Für alle in der Entwicklung wichtigen Dokumente ist eine Versionierung notwendig. Je nach Tool ist es unklar, was in die Versionierung übernommen werden soll. Binäre Dateien sind wenig hilfreich.

Ein Vergleich zwischen den verschiedenen Versionen einer Graphik ist schwierig. Manche graphischen Werkzeuge bieten Unterstützung an. Diese arbeitet aber häufig auf eigenen Repositories und läßt sich schlecht mit der Versionierung sonstiger Dokumente verbinden. In anderen Fällen kann man die Dateien als Text vergleichen. Dann muß man aber die Struktur dieser Dateien verstehen (z.B. XMI für UML-Werkzeuge).

Zusammenfassung

Während Graphiken häufig sehr nützlich sind, um Ideen zu vermitteln, gibt es doch auch gravierende Probleme, wenn ausschließlich damit gearbeitet werden soll.