Donnerstag, Dezember 28, 2006

Ruby goes Lisp

Mit ParseTree kann man zur Laufzeit die Struktur eines Ruby-Programms analysieren. Das was da rauskommt sieht sehr nach Lisp-S-Expressions aus, was Grahams These stützt, die Programmiersprachen würden sich mit der Zeit immer mehr Lisp annähern. Dass mit ParseTree bei weitem nicht die Flexibilität von Lisp erreicht ist, kann man auf der ParseTree-Homepage lesen: Es funktioniert nicht für die Ruby-Core-Klassen und verändern bzw. generieren kann man so einen ParseTree wohl auch nicht. Dennoch wahrscheinlich eine sehr nützliche Geschichte.

Post bewerten

Toyota

Hier gibt es einen ganz interessanten Artikel darüber, dass die Ideen des Toyota-Production-System noch heute funktionieren und Wettbewerbsvorteile bringen - insbesondere wenn man es so radikal durchzieht wie Toyota.
Während die meisten Autohersteller Autos herstellen, macht Toyota vier Dinge:

  1. Autos herstellen

  2. Autos besser herstellen

  3. Jedem Mitarbeiter beibringen, wie man Autos besser herstellt

  4. Immer nach Möglichkeiten suchen, den Prozess zur Prozessverbesserung zu verbessern


Dazu gehört, dass man nie zufrieden ist mit dem, was man erreicht hat. Stattdessen sucht man immer noch Möglichkeiten, in kleinen Schritten Verbesserungen zu schaffen.

Post bewerten

Marktorientierte Innovation

Es ist jetzt schon ein wenig her, dass ich das Buch "Marktorientierte Innovation" gelesen habe. Seitdem habe ich immer mal wieder versucht, die beschriebenen Konzepte in der Praxis anzuwenden und bin mit den Ergebnissen sehr zufrieden.
Das Buch befasst sich mit der Frage, warum sich bestimmte Innovationen durchsetzen und andere nicht. Welche Innovationen haben überhaupt eine Chance auf dem Markt? Was müssen Unternehmen tun, um mit Innovationen neue Marktpotenziale zu erschließen? Sollten sie sich gegen Konkurrenz wehren, die neue Innovationen auf den Markt bringt und wenn ja, wie? Und warum ist das alles so?
Für all diese Fragen bietet das Buch ein nützliches Denkmodell an, mit dem man sich z.B. auch die Frage beantworten kann, ob sich neue Programmiersprachen durchsetzen können oder nicht.

Post bewerten

Freitag, Dezember 08, 2006

eXtreme Programmer gesucht

Wir (www.it-agile.de, www.akquinet.de) suchen gerade wieder neue Mitarbeiter. Dabei interessieren wir uns explizit für Entwickler, die Ihr Studium mind. 1,5 Jahre hinter sich haben, mind. 2 Jahre Java-Projekterfahrung haben und mind. privat TDD und inkrementellen Entwurf praktiziert haben.

Aufgabenbereich ist die Entwicklung in XP-Teams, inkrementelle Architektur und bei entsprechender Erfahrung das Coaching unserer Beratungskunden.

Wer Interesse hat, sieht sich das mal an: http://it-agile.de/jobs.html

Post bewerten

XP auf japanisch

Wahrscheinlich bin ich wieder der letzte im Internet, der das entdeckt hat: XP-Song-Video auf japanisch. Auf deutsch gibt es das bisher nicht. Da sind uns die Japaner mal wieder eine um eine Naselänge voraus.

Post bewerten

Sonntag, Dezember 03, 2006

Nutzen von Dokumentation

Auf der ix-Konferenz "Bessere Software" war ich auch noch im Vortrag "Toleranz gegenüber Inkonsistenzen in der Konzeptdokumentation - eine unbedingte Notwendigkeit" (was für ein Titel :-) von Prof. Dr.-Ing. Siegfried Wendt. Dabei ging es um die Frage, wieviel Dokumentation von welcher Art man braucht. Sehr nützlich fand ich die Feststellung, dass die Nützlichkeit von Dokumentation mit ihrer Detaillierung abnimmt. So kann z.B. eine Architekturübersicht mind. für alle Entwickler des Systems nützlich sein. Die Dokumentation einer einzelnen Klasse ist höchstens für den Entwickler der Klasse relevant. Und selbst für den ist sie selten nützlich. Er hat die Klasse ja geschrieben und kann sich i.d.R. auch ohne Dokumentation ausreichend orientieren. Zitat Wendt (sinngemäß): "Wer Dokumentation auf dieser Detailierungsebene schreibt, verbrennt Geld."

Post bewerten

Martin Fowler: Introduction to Domain Specific Languages

Bei InfoQ gibt es die Präsentation "Introduction to Domain Specific Languages" von Martin Fowler. Hier erläutert Martin Fowler nicht nur, was eine Domain Specific Language (DSL) ist, sondern auch, wie man schrittweise zu seiner eigenen DSL kommt.
Er beginnt dabei mit XML zur Darstellung der DSL, kommt dann aber zu dem Schluss, dass XML häufig nicht die beste Darstellungsart ist. Es i.d.R. gibt deutlich kompaktere Schreibweisen, die den Umgang mit der DSL erheblich vereinfachen können. Ähnliche Gedanken scheinen auch die Spring-Macher umzutreiben.

Post bewerten

Freitag, Dezember 01, 2006

Unser Hibernate-Buch...

...ist das vierte von oben :-)

Post bewerten

Dienstag, November 28, 2006

Die Fehler von Microsoft

Auf der ix-Konferenz war ich heute morgen in der Session "Die Fehler von Microsoft" von Andreas Zeller (Universität des Saarlandes). Dabei ging es um die Frage, ob und wie man Fehlerhäufigkeit bestimmter Module vorhersagen kann, um diese besonders intensiv zu testen. Andreas Zeller hat dazu Untersuchungen an Microsoft- und Eclipse-Modeulen durchgeführt. Der Vortrag war nicht nur gut vorgetragen, sondern transportierte auch ein paar interessante Erkenntnisse:

  1. Wenn ein Modul in der Vergangenheit sehr fehlerträchtig war, wird es auch in Zukunft fehlerträchtig sein.

  2. Mit Metriken kann man nicht universell vorhersagen, welche Module besonders fehlerträchtig sein werden. Zitat Zeller: "Das ist ein herber Schlag für die Metrik-Community. Ein Glück, dass ich nicht dazu gehöre."

  3. Man kann je Produkt (z.B. Microsoft Internet Explorer) Metriken definieren, die ganz gut funktionieren. Dazu braucht man aber Zahlen aus der Vergangenheit. Damit ist das Verfahren nur sinnvoll für neue Module in einem bestehenden Produkt. Für die existierenden Module in einem bestehenden Produkt haben wir ja Erkenntnis Nummer 1.

  4. Die erfahrensten Entwickler machen die meisten Fehler. So hat angeblich Erich Gamma eine der höchsten Fehlerraten im Eclipse-Projekt. Und Module, die sehr viele Unittests haben, sind sehr fehleranfällig. Das liegt daran, dass die erfahrenen Entwickler immer nach vorne geschickt werden, wenn es brenzlig wird. Und die Entwickler schreiben dort viele Unittests, wo sie viele Probleme vermuten. Das bedeutet, dass die Entwickler unabhängig von Metriken eigentlich ganz gut wissen, wo die fehlerträchtigen Module rumlungern. Dann kann man sich doch auch einfach an deren Einschätzung orientieren.

Weitere Informationen zu dem Thema finden sich unter www.softevo.org.

Post bewerten

Sonntag, November 26, 2006

Gute Entwickler

Bei den XP-Days war es bei der Fishbowl-Session zu Agile 2.0 explizit ein Thema, bei anderen Vorträgen stand die Frage implizit im Raum: Wie wird man eigentlich ein guter Entwickler?
Es rief keinen Widerspruch hervor, als ich behauptet habe, die Unis würden keine nennenswerten Programmierfähigkeiten vermitteln. Ich finde das absurd: Wenn etwas im Kern aller Einzeldisziplinen der Informatik steht, dann doch wohl Programme und die muss doch auch jemand programmieren. Aber im Moment sind die Unis wohl nicht der Ort, um ein guter Programmierer zu werden. Also muss man das Programmieren wohl außerhalb der Uni lernen. Da gibt es zwei Möglichkeiten: Neben dem Studium oder nach dem Studium. Im Autismus-Mode wird das nur begrenzt gehen: Man braucht Partner, von und mit denen man lernen kann.
Da finde ich es sehr schön, dass vermehrt Lernformen auftreten, die genau das ermöglichen: Programmieren lernen.

  • Im Coding-Dojo lernt man durch Beobachten anderer Entwickler das Programmieren. Das kann mit oder ohne Pair-Programming und mit oder ohne testgetriebener Entwicklung (TDD-Dojo) geschehen.

  • Im Coding-Tournament treten Programmierpaare gegeneinander an, um Bots zu programmieren, die dann gegeneinander spielen - im Fall der XP-Days Indian Poker.


Ich habe jetzt ein paar solcher Veranstaltungen selbst mitgemacht/veranstaltet und habe erlebt, wieviel man dort in sehr kurzer Zeit lernen kann - und das mit jeder Menge Spaß. Ich halte Coding-Dojos und Coding Tournaments auch für eine Klasse Idee, um sie innerhalb von Firmen zur internen "Weiterbildung" durchzuführen.
Ein TDD-Dojo bieten übrigens Henning Wolf und ich gemeinsam auf der ix-Konferenz in Frankfurt am 30.11.06 an.

Post bewerten

NEZIAK als neue Methode der Softwareentwicklung?

Gestern haben wir bei Hennings Geburtstagsparty in ausgelassener Stimmung unsere Gedanken schweifen lassen und sind dabei auf NEZIAK gestoßen. Zu NEZIAK kommt man, wenn man KAIZEN (kontinuierliche Verbesserung in kleinen Schritten) umgedreht aufschreibt. Inhaltlich bedeutet NEZIAK entsprechend die kontinuierliche Verschlechterung in kleinen Schritten :-)
Ist natürlich offensichtlicher Blödsinn... Allerdings habe ich den Eindruck, dass viele Projekte konsequent NEZIAK einsetzen. Nanu? Wer macht denn etwas offensichtlich Blödsinniges und warum?

Post bewerten

XP-Days 2006 in Hamburg sind vorbei

Die XP-Days 2006 in Hamburg sind vorbei. Sie haben mir gut gefallen. Die Vorträge waren im wesentlichen gut bis sehr gut und ich habe alte Bekannte wieder getroffen. Schon während der Konferenz konnten die Teilnehmer bloggen. Inzwischen trudeln auf dem Konferenzblog auch die Folien zu den Vorträgen ein.

Post bewerten

Dienstag, November 21, 2006

Wie schwer kann es sein, ein PDF mit Java zu drucken?

Eigentlich ist es ganz einfach, haben wir uns gedacht. Aber nichts da. Man kann zwar mit allen möglichen Programmen PDFs erzeugen, aber die PDFs dann automatisch an einen Windows-Drucker zu schicken, scheint noch ein offenes Forschungsthema zu sein.
Unser erster Anlauf ging über die Java Printing Services. Laut API-Doku ist es ganz einfach. Man sagt mit dem PDF-Flavor, dass man ein PDF drucken will und fertig. Dummerweise hat Sun den PDF-Flavor nicht implementiert. Man hofft wohl, dass das jemand anderes tut. Wir konnten aber niemanden finden, der es auch getan hat.
Zwischenzeitlich hatten wir dann ein BAT-Programm gefunden, dass schwindelerregende Dinge mit der Registry tut. Das haben wir aber nicht zum Laufen bekommen, außerdem braucht es Admin-Zugang auf dem PC der Anwender und das ist bei Unternehmenssoftware eher nicht angesagt.
Schließlich hat uns das kommerzielle JNIWrapper aus der Klemme geholfen.
Aus dem gleichen Stall stammt übrigens auch JExplorer, mit dem man den MS-Internet-Explorer nahtlos in Swing-Anwendungen einbetten kann.

Post bewerten

Samstag, November 18, 2006

Java-Script auf dem Server

Bei aktuelllen Web-Anwendungen hat man immer Java-Script auf dem Client. Die AJAX-Frameworks versuchen, diese Tatsache zu verstecken, so dass man nur mit der einen serverseitigen Programmiersprachen arbeiten muss.
Wenn es anspruchsvoll wird, reichen die Frameworks aber nicht mehr aus und man muss doch wieder Java-Script für den Browser programmieren. Wäre es da nicht viel eleganter Java-Script auch auf dem Server einzusetzen und damit nur eine Programmiersprache benutzen zu müssen? Schließlich braucht sich Java-Script bzgl. der Sprachkonstrukte eigentlich nicht verstecken hinter anderen Script-Sprachen.
Siehe dazu Phobos.

Post bewerten

Dienstag, November 14, 2006

Unit-Testing in Multi-Projekt-Settings mit JUnit 4

Die von mir zitierte Lösung für Unit-Testing in Multi-Projekt-Settings funktioniert nur für JUnit 3.8, aber nicht für JUnit 4. Johannes Link hat die Lösung für JUnit 4 adaptiert.

Post bewerten

Dienstag, November 07, 2006

Newsfeed zieht um

Der Newsfeed zu diesem Blog wird umziehen nach: http://stefanroock.blogspot.com/rss.xml

Post bewerten

Mittwoch, November 01, 2006

Unit-Testing in Multi-Projekt-Settings

Die Eclipse-IDE bietet sich an, um ein Gesamtprojekt in mehrere Subprojekte/Komponenten zu unterteilen. Die Abhängigkeitsverwaltung in Eclipse sichert dabei, dass man keine ungewollten Abhängigkeiten in sein System einbaut.
Unverständlicherweise kann man in Eclipse aber nicht Unit-Tests über mehrere Projekte auf einmal ausführen. Wenn man sehr viele Projekte in Eclipse hat, wird das Ausführen der Unit-Tests zur echten Qual.

Aber es gibt eine ganz einfache Lösung über eine generische Test-Suite, die einfach alle Tests im Classpath ausführt. Den Code (< 100 Zeilen) dazu findet man bei Björn Martensson.

Post bewerten

Mittwoch, Oktober 11, 2006

DROP COLUMN

Wenn man agil Software entwickelt, gehören häufige Produktivreleases zum Handwerkszeug. Daraus resultieren zwangsläufig Datenmigrationen, die mehr oder weniger umfangreich bei jedem Release anfallen.

Refactorings am Code verursachen entsprechende Refactorings an den Datenbankstrukturen. Besonders häufig findet man Umbenennungen von Spalten, Typänderungen von Spalten sowie das Löschen von Spalten.

Viele Datenbanken unterstützen das Umbenennen von Spalten direkt. Dort wo es nicht geht, fügt man eine neue Spalte mit dem Zielnamen ein, kopiert die Daten von der Quell- in die Zielspalte und löscht schließlich die Quellspalte. Mit ALTER TABLE und UPDATE ist das alles auch kein Problem. Bei Typänderungen von Spalten geht man genauso vor, nur dass man zwischendurch eine temporäre Spalte einführt (sonst bekommt man einen Namenskonflikt zwischen Quell- und Zielspalte).

Das Schreiben dieser Migrationsskripte scheint erstmal sehr aufwändig und unangenehm. In unseren Projekten haben wir allerdings festgestellt, dass es dann doch nicht so schlimm ist. Auf jeden Fall ziehen wir das Schreiben der Migrationsskripte dem Hinauszögern oder Weglassen von Releases vor.

Es gibt nur ein wiederkehrendes Problem und das heißt DB2: DB2 ist anscheinend die einzige Datenbank, die Tabellenspalten nicht löschen kann.

Wir behelfen uns in diesem Fall mit temporären Tabellen: Wir legen zuerst eine Kopie der Quelltabelle an und kopieren die Daten von der Quelltabelle in die temporäre Tabelle. Dann löschen wir die Quelltabelle und legen sie mit der Zielstruktur neu an. Dann migrieren wir die Daten von der temporären Tabelle in die neue Zieltabelle (mit INSERT) und löschen schließlich die Temporärtabelle. Das ist leider aufwändig und auch fehleranfällig, weil schnell mal Indices und Fremdschlüssel-Constraints verloren gehen.

Es gibt sicher gute Gründe dafür, warum DB2 DROP COLUMN nicht unterstützt - entsprechende Argumentationen findet man beim Googlen relativ schnell. Trotzdem erschwert DB2 leider agile Softwareentwicklung deutlich mehr als die anderen relationalen Datenbanksysteme.

Post bewerten

Samstag, September 23, 2006

Video: Closures in Java

Es gibt ein ganz lustiges und informatives Video, wie Closures in Java aussehen könnten und wie sie intern auf Inner Classes abgebildet werden können.

Post bewerten

Freitag, September 22, 2006

Terminplaner in Lisp

Ich habe das Terminplaner-Beispiel zuerst in Java programmiert und dann nach Groovy (Skriptsprache für die Java-Plattform) programmiert. Das Beispiel ist in Groovy als eine der jüngsten Programmiersprachen doch erheblich kürzer und einfacher als in Java. Da hat es mich dann doch gereizt, das Beispiel auch einmal in einer der ältesten Programmiersprachen zu programmieren: Lisp. Dabei habe ich Common Lisp verwendet mit CLOS (Common Lisp Object System) und Lisp-Unit von Chris Riesbeck.

Die quantitativen Ergebnisse aller drei Implementationen zuerst einmal im Vergleich:

Java

  • 5 Fachklassen, 1 Exception-Klasse, 1 Testklasse

  • 37 Methoden inkl. Konstruktoren + 10 Methoden in Testklasse

  • 246 LOC operativ + 144 LOC für Testklasse (inkl. Leerzeilen)

  • 4 For-Schleifen, 4 If-Abfragen


Groovy

  • 4 Fachklassen, 1 Exception-Klasse, 1 Testklasse

  • 30 Methoden inkl. Konstruktoren + 9 Methoden in Testklasse

  • 203 LOC operativ + 123 LOC für Testklasse (inkl. Leerzeilen)

  • Alle 4 For-Schleifen der Java-Lösung wurden durch Closures ersetzt, die 4 If-Abfragen blieben bestehen.


Common Lisp

  • 4 Fachklassen, 1 Testklasse - Exceptions werden mit Hilfe von Conditions modelliert (nur eine Zeile notwendig)

  • 17 Methoden, 1 Condition-Funktion, 10 Testmethoden

  • 76 LoC operativ, 100 LoC Test (inkl. Leerzeilen)

  • Alle 4 Schleifen der Java-Lösung wurden durch Closures ersetzt, die 4 If-Abfragen blieben bestehen, allerdings in den spezialisierten Varianten when und unless.


Wow! Die Common-Lisp-Variante hat erheblich weniger Code als die Java- oder die Groovy-Variante. Woran liegt das?
Naheliegend wäre es, die Ursache bei dem Lisp-Feature zu suchen, dass keine andere Programmiersprache anbietet: Macros (Vorsicht: Lisp-Makros sind ganz anders als die berüchtigten C-Makros). Dem ist aber nicht so. Tatsächlich habe ich in dem Lisp-Code kein eigenes Makro selbst definiert und nur an einer Stelle von der Mächtigkeit der
Lisp-Makros profitiert. Mit assert-error aus Lisp-Unit kann man sehr einfach prüfen, ob eine Exception (im Lisp-Jargon Condition) geworfen wird:


(define-test benutzer-nicht-eingeladen-exception
(setup)
(let ((termin (make-termin stefans-kalender ein-datum 180 "TDD-Dojo")))
(assert-error 'benutzer-nicht-eingeladen (lehne-termin-ab termin "Henning"))))


Zum Vergleich der entsprechende Java-Code:


public void testBenutzerNichtEingeladenException() {
Termin termin = _stefansKalender.newTermin(_jetzt, 180, "TDD-Dojo");
try {
termin.lehneTerminAb(HENNING);
fail("BenutzerNichtVorhandenException erwartet");
} catch (BenutzerNichtEingeladenException e) {
assertTrue("Exception erwartet", true);
}
}


Das erklärt aber nicht, warum der operative Code in Lisp so viel kürzer ist als in Java oder Groovy. Eine nähere Analyse fördert folgende Gründe zu Tage:
  • In Java und Groovy werden eigene Zeilen spendiert, für schließende geschweifte Klammern. Für das Lisp-Äquivalent (schließende runde Klammern) werden keine eigenen Zeilen spendiert. Dierk König schlägt in seinem kommenden Groovy-Buch diese Art der Formatierung für Groovy für bestimmte Situationen auch vor (bei den Buildern).

    • In Java und Groovy ist es üblich, Leerzeilen in Methoden einzufügen, teilweise auch zwischen Attributen. Beides macht man in Lisp eher nicht.

    • Das aufschreiben von Attributen einer Klasse ist in Common-Lisp schlanker als in Groovy oder Java. Insbesondere gibt es prägnante Abkürzungen, um Setter und Getter und Defaultwerte zu definieren.

    • Einige Implementierungen lassen sich nicht sinnvoll 1:1 nach Common-Lisp transferieren. Daher vergleicht man ein Stück weit dann doch Apfelsinen mit Orangen (so groß wie zwischen Äpfel und Birnen sind die Unterschiede dann doch nicht :-)


    Der gewaltige Unterschied in den LoC findet sich bei der Menge der Syntaxelemente in deutlich reduzierter Form. So spart man sich in Common-Lisp zwar Einiges an Zeilen für die Attributdefinitionen in Klassen, es gibt aber die gleiche Anzahl von Attributdeklarationen. In diesem Sinne ist die Lisp-Lösung zwar kürzer als die Lösungen in Java und Groovy. Sie ist bzgl. der Komplexität aber äquivalent zur Groovy-Lösung und diese beiden Lösungen sind weniger komplex als die Java-Lösung.

    Wieviel wirkt der große Unterschied in den LoC? Quelltext wird viel häufiger gelesen als geschrieben. Daher ist die Einsparung der Tastenanschläge bei der Code-Erstellung nicht wirklich von Interesse. Wenn man allerdings beim Lesen von Quelltext weder vertikal noch horizontal scrollen muss, erleichtert dies das Lesen: Im Lisp-Terminplaner passt jede operative Klasse problemlos auf eine Bildschirmseite, so dass man jede Klasse auf einen Blick erfassen kann. Das kann man als (leichten) Vorteil von Lisp werten. Allerdings muss ich zugeben, dass man den Groovy-Code an der einen oder anderen Stelle noch etwas eleganter Formulieren kann und dann auch noch etwas an LoC einsparen kann.

    Quelltext des Terminplaners in Common-Lisp.

    Post bewerten

  • Dienstag, September 19, 2006

    Refactoring und Closures

    Refactoring-schwaches Java
    Vor wenigen Tagen schrieb ich zusammen mit Henning Wolf Beispielcode für einen Sudoku-Solver. Wir wollten damit bestimmte Aspekte testgetriebener Entwicklung (TDD) sowie von Refactoring zeigen. Dabei haben wir unter anderem folgenden Code geschrieben:


    public class Sudoku {

    final static int groesse = 9;
    private Zelle[][] _sudokuArray = new Zelle[groesse][groesse];

    public Sudoku(int[][] array) {
    for (int i = 0; i < array.length; i++) {
    for (int j = 0; j < array[i].length; j++) {
    _sudokuArray[i][j] = new Zelle(array[i][j]);
    }
    }
    }

    public String[][] gibAusgefuellt() {
    String[][] result = new String[groesse][groesse];
    for (int i = 0; i < result.length; i++) {
    for (int j = 0; j < result[i].length; j++) {
    result[i][j] = _sudokuArray[i][j].toString();
    }
    }
    return result;
    }

    ...
    }



    Hier hat man offensichtlich das DRY-Prinzip verletzt (DRY = Don't Repeat Yourself): Die zwei ineinander geschachtelten FOR-Schleifen existieren zweimal (wenn man sich den kompletten Quellcode des Sudoku-Solvers ansieht, kommt das Konstrukt sogar noch häufiger vor). Ähnliche Duplizierungen in Zusammenhang mit If-Abfragen, For- und While-Schleifen finden sich in jedem größeren Java-Programm, dass ich bisher gesehen habe.

    Prinzipiell kann man diese Code-Duplizierungen auf verschiedene Arten beseitigen. Die naheliegendste Lösung besteht im Einführen eines Interfaces MatrixBesucher:


    interfaces MatrixBesucher {
    void besucheZelle (Object[][] matrix, int i, int j)
    }



    Ein Objekt dieses Interfaces reicht man als Parameter in eine Hilfemethode iteriereMatrix:


    private static void iteriereMatrix (ZellenBesucher besucher) {
    for (int i = 0; i < groesse; i++) {
    for (int j = 0; j < groesse; j++) {
    besucher.besucheZelle(i, j);
    }
    }
    }



    Dann wird aus dem Anfangs gezeigten Code:


    public class Sudoku {

    final static int groesse = 9;
    private Zelle[][] _sudokuArray = new Zelle[groesse][groesse];

    public Sudoku(final int[][] array) {
    iteriereMatrix(new ZellenBesucher() {
    public void besucheZelle (int i, int j) {
    _sudokuArray[i][j] = new Zelle(array[i][j]);
    }
    }
    }

    public String[][] gibAusgefuellt() {
    String[][] result = new String[groesse][groesse];
    iteriereMatrix(new ZellenBesucher() {
    public void besucheZelle (int i, int j) {
    result[i][j] = _sudokuArray[i][j].toString();
    }
    }
    return result;
    }

    ...
    }



    Damit ist DRY wieder hergestellt. Das Problem daran ist nur, dass sowas kein Mensch macht. Schließlich ist die Lösung länger (mit Hilfsmethode und Interface 26 statt 16 Codezeilen) und besser lesbar ist sie leider auch nicht wirklich.

    Möglicherweise schwerer wiegt, dass man für das Refactoring in Richtung DRY die Ebene wechseln musste. Das DRY-Prinzip war innerhalb einer Klasse auf Algorithmus-Ebene verletzt und wir mussten ein neues Interface einführen, also auf die Entwurfsebene wechseln. Das bedeutet, dass der Refactoringprozess an dieser Stelle nicht-linear verlaufen ist (linear: kleines Problem, kleine Lösung; nicht-linear: kleines Problem, umständliche Lösung).

    Anmerkung: Man kann sich andere Lösungen des Problems vorstellen, die ohne die umständlichen und schwer lesbaren anonymen Inner-Classes auskommen. Solche Lösungen erfordern aber deutlich mehr Entwurfsarbeit, mitunter sogar Vererbung oder den Einsatz von Entwurfsmustern. Damit würde der Refactoring-Prozess sogar noch nicht-linearer.

    Refactoring mit Closures
    Mit Closures hingegen ließe sich das DRY-Prinzip mit wenig Aufwand umsetzen und man kann beim Refactoring auf der Algorithmus-Ebene bleiben. Zu allem Überfluss ist die Lösung auch noch leicht lesbar. Hätte Java Closures, könnte die Lösung in etwa so aussehen (die Syntax für Closures ist hier an Groovy angelehnt):


    public class Sudoku {

    final static int groesse = 9;
    private Zelle[][] _sudokuArray = new Zelle[groesse][groesse];

    public Sudoku(final int[][] array) {
    iteriereMatrix({i, j -> _sudokuArray[i][j] = new Zelle(array[i][j])};
    }

    public String[][] gibAusgefuellt() {
    String[][] result = new String[groesse][groesse];
    iteriereMatrix({i, j -> result[i][j] = _sudokuArray[i][j].toString()};
    return result;
    }

    private static void iteriereMatrix (Closure closure) {
    for (int i = 0; i < groesse; i++) {
    for (int j = 0; j < groesse; j++) {
    closure.execute(i, j);
    }
    }
    }

    ...
    }



    Und schon ist die Lösung nur noch 15 Codezeilen lang (im Gegensatz zu 16 Codezeilen beim Original-Quelltext).

    Nun kann man natürlich einwenden, dass die Closures prinzipiell auch nicht mächtiger sind als anonyme Inner-Classes, es sich hier also lediglich um Syntactic-Sugar handelt. Das ist richtig und zeigt, wie wichtig eine prägnante Syntax ist. Denn die Inner-Class-Lösung wird in der Praxis so gut wie nicht eingesetzt, während die Closure-Lösung überaus üblich ist in Programmiersprachen, die Closures unterstützen wie z.B. Lisp, Python der Groovy.

    Closures in Java
    Wenn Closures so nützlich sind und konzeptionell eigentlich nur Syntactic-Sugar für anonyme Inner-Classes darstellen, dann sollte es ja eigentlich auch kein Problem sein, Closures auch in Java zu unterstützen. Und tatsächlich gibt es Anzeichen dafür, dass wir irgendwann Closures auch in Java haben werden:

    http://article.gmane.org/gmane.comp.lang.lightweight/2274

    Interessant ist hier die Argumentation: Es ist ein grundlegendes Design-Prinzip von Java, dass nur dann Objekte auf dem Heap allokiert werden, wenn der Programmierer dies explizit anfordert (typischerweise durch new). Bei Closures muss man aber implizit Speicher auf dem Heap allokieren und daher passen Closures nicht zum Design von Java.
    Nun bricht aber seit Java 5 das Auto-Boxing dieses Prinzip und daher sei es jetzt sowieso egal und man könnte dann auch noch Closures einführen :-)

    Prinzipiell bin ich persönlich der Meinung, dass Closures mir das Leben als Java-Entwickler erleichtern würden. Gleichzeitig müsste man aber große Teile des JDKs komplett umbauen. Sonst startet der ganze Ansatz als Tiger und landet als Bettvorleger. Wenn man schon Closures hat, wird man auch erwarten, dass mind. die Collections massiv davon Gebrauch machen (z.B. für das Iterieren über die Elemente). Wo man sich sonst noch die Verwendung von Closures wünschen würde, kann man gut am GDK (Groovy Development Kit) sehen.

    Und wenn man soweit geht, dann sollte man vielleicht lieber Java als Sprache auf Deprecated setzen und die Migration nach Groovy pushen. Denn da werden Closures von Beginn an unterstützt und auch entsprechende Libraries im GDK sind verfügbar.

    Post bewerten

    Montag, September 18, 2006

    Groovy und Grails auf Konferenzen

    Eindrücke aus erster Hand zu Groovy und Grails kann man sich auf verschiedenen Konferenzen in den nächsten Monaten besorgen:

    Post bewerten

    Grails: Schnell mal eine Web-Anwendung mit Groovy für die Java-Plattform

    An anderer Stelle habe ich bereits Groovy kurz beleuchtet, die standardisierte Skriptsprache für die Java-Plattform.

    Jetzt, wo man eine so mächtige und flexible Skriptsprache hat, lag es natürlich nahe, den Rails-Ansatz auch für Groovy nutzbar zu machen. Herausgekommen ist Grails.

    Grails existiert erst in der Version 0.2.2, hat aber bereits einen erstaunlichen Entwicklungsstand. Mit wenigen Clicks ist eine erste Version der Webanwendung zusammengebaut, die man dann explorativ weiterentwickeln kann.

    Die existierende Dokumentation reicht für erste Schritte aus, vieles kann man sich durch nachdenken erschließen.

    Grails ist sicherlich eine sehr interessante Technologie für die Web-Projekte, die für die Java-Plattform entwickeln müssen/wollen. Die Java-ähnliche Syntax von Groovy erleichtert Java-Entwicklern den schnellen Einstieg.

    Post bewerten

    Sonntag, September 03, 2006

    Kommentarfunktion in diesem Blog jetzt für alle

    jedenfalls für alle mit einem Blogger-Account. Bisher musste man zusätzlich Geheimwissen mitbringen: Man musste auf das # am Ende eines Eintrages klicken, um den Eintrag einzeln zu öffnen und dort konnte man dann einen Kommentar hinterlassen. Ich habe jetzt das Template für diesen Blog so geändert, dann man die Kommentarfunktion jetzt direkt am Eintrag aufrufen kann. Außerdem habe ich das kryptische # durch "Permanent Link" ersetzt.

    Dass man zum Kommentar hinterlassen einen Blogger-Account haben muss, ist ärgerlich, aber wg. der Spam-Problematik zur leider wohl unvermeidlich.

    Post bewerten

    Donnerstag, August 24, 2006

    IDEs und der K(r)ampf zwischen Statik und Dynamik

    Für Java existieren heute mit Eclipse, IntelliJ IDEA und Konsorten sehr mächtige Entwicklungsumgebungen. Cross-Referencing, Refactoring und Auto-Completion sind Features, die man nicht mehr missen möchte.
    Dass diese Features für die aktuellen Skriptsprachen a la Python, Ruby oder Groovy nicht oder nur eingeschränkt existieren, wird häufig als Argument gegen diese Skriptsprachen verwendet.

    Aber wird über diese Features wirklich reflektiert?

    Cross-Referencing
    Mit den Cross-Referencing-Möglichkeiten der IDE kann man auf Tastendruck oder Mausclick von einer Codestelle zum referenzierten Element gelangen (z.B. von einer Variablendeklaration zur Klasse, von deren Typ die Variable ist).

    Natürlich sind die Cross-Referencing-Möglichkeiten in den IDEs deutlich mächtiger als eine Textsuche über Dateien. Aber ist der Unterschied wirklich so groß? Und ist die Textsuche häufig nicht sogar schneller?

    Refactoring
    Refactoring ist eine der großen Errungenschaften in der Neuzeit der Softwareentwicklung und ihr Automatisierungsgrad ist wirklich erstaunlich hoch. Aber welche automatisierten Refactorings nutzen wir überhaupt bei der täglichen Arbeit und wie häufig? Viele Entwickler verzichten sogar absichtlich auf bestimmte einfache Automatisierungen (z.B. "Introduce Variable"), weil sie von Hand schneller sind - die Mächtigkeit der IDEs führt bei großen Projekten leider dazu, dass die Arbeit mit ihnen mitunter doch etwas zäh wird.
    Viele Refactorings kann man in der Tat mit vertretbarem Aufwand und Risiko auch von Hand durchführen. Einige andere (z.B. "Rename Class") lassen sich auch auf anderem Wege automatisieren (Find&Replace über Dateien). Natürlich kann man sich dann oft nicht 100%ig sicher sein, dass alles korrekt geändert wurde. Man muss anschließend die Tests ausführen. Dass muss man in Java aber auch, weil es immer mehr untypisierte Referenzen in XML-Dateien (Struts, Spring, EJB etc.) gibt, die den IDEs auch mal durch die Lappen gehen.

    Auto-Completion
    Bei der automatischen Vervollständigung tippt man nur den Beginn eines Wortes ein und die IDE ergänzt die fehlenden Zeichen. Dadurch spart man Tippzeit, reduziert die Wahrscheinlichkeit von Tippfehlern und muss sich nur an den Anfang von Methodennamen erinnern.
    Interessanterweise gibt es auch in programmiersprachen-unabhängigen Editoren wie Emacs oder JEdit Auto-Completion. Dabei werden viel einfachere Verfahren eingesetzt als in den Java-IDEs, die aber erstaunlich gute Ergebnisse liefern. Ein ganz einfacher Ansatz besteht z.B. darin, bei der Auto-Completion nur die Wörter zu berücksichtigen, die in der aktuellen Datei schon mal verwendet wurden. Etwas umfangreicher ist der Ansatz, die Wörter aller Dateien eines Projektes zu verwenden.
    Ähnlich wie beim Cross-Referencing sind diese Auto-Completion-Features der Editoren qualitativ denen der IDEs unterlegen. Aber wie beim Refactoring sie sind schneller.

    Und das ist ein Faktor, den man nicht unterschätzen sollte. Ich ertappe mich beim Java-Programmieren jedenfalls immer wieder dabei, dass ich Namen komplett manuell eintippe, weil ich damit schneller bin als die zäh reagierende Entwicklungsumgebung. Und wenn ich in einem einfachen Editor eine Skriptsprache programmiere, genieße ich es, dass der Editor immer sofort reagiert. Die IDEs sind nur Bruchteile von Sekunden langsamer, aber das reicht schon aus, um den Flow beim Programmieren zu beeinträchtigen.

    Post bewerten

    Samstag, August 19, 2006

    Closures in Common Lisp

    Martin Fowler published an online article about closures. He used the Ruby programming language for the examples. There are translations of the examples to Python and a language called Boo.

    As a programming task for myself I did the examples in Common Lisp, which supported Closured already decades ago. A real lisper might be able to write the code in a more elegant way but I think the principle should become clear.

    I didn't use the Common Lisp Object System (CLOS) since for this simple example an ad-hoc modeling with hashes is simpler.


    ;; Ruby
    ; def managers(emps)
    ; return emps.select {|e| e.isManager}
    ; end

    ;; Common Lisp
    (defun is-manager (emp) (getf emp :is-manager))

    (defun managers (emps)
    (remove-if-not (lambda (emp)
    (when (is-manager emp) emp))
    emps))


    ;; Ruby
    ; def highPaid(emps)
    ; threshold = 150
    ; return emps.select {|e| e.salary > threshold}
    ; end

    ;; Common Lisp
    (defun high-paid (emps)
    (let ((threshold 150))
    (remove-if-not (lambda (emp)
    (when (> (getf emp :salary) threshold) emp))
    emps)))


    ;; Ruby
    ; def paidMore(amount)
    ; return Proc.new {|e| e.salary > amount}
    ; end

    ;; Common Lisp
    (defun paid-more (amount)
    (lambda (emp) (when (> (getf emp :salary) amount) emp)))

    ;; Ruby
    ; highPaid = paidMore(150)
    ; john = Employee.new
    ; john.salary = 200
    ; print highPaid.call(john)

    ;; Common Lisp
    (let ((high-paid (paid-more 150))
    (john '(:name John :is-manager nil :salary 200)))
    (princ (funcall high-paid john)))


    ;; Tests
    (defparameter manager-list
    '((:name Stefan :is-manager nil :salary 150)
    (:name Henning :is-manager t :salary 151)
    (:name Martin :is-manager nil :salary 120)
    (:name Christian :is-manager t :salary 200)))

    (princ #\newline)
    (princ "Test function managers")
    (princ #\newline)
    (princ (managers manager-list))
    (princ #\newline)

    (princ #\newline)
    (princ "Test function high-paid")
    (princ #\newline)
    (princ (high-paid manager-list))
    (princ #\newline)

    Post bewerten

    Freitag, August 04, 2006

    Sensing Variables for Refactorings

    Michael Feathers hat ein Konzept namens Sensing Variables beschrieben, mit dem sich Refactorings an Methoden sicherer durchführen lassen. Ein häufiges Problem mit dem Refactoring "Extract Method" besteht darin, dass der selektierte Code-Block sich nicht automatisch in eine Methode verschieben lässt (z.B. weil die neue Methode dann mehrere Rückgabewerte haben müsste). Also muss man erstmal manuell die Methode manipulieren, bevor man "Extract Method" ausführen kann. Dazu muss man häufig die Reihenfolge von Anweisungen in der Methode ändern, kann aber nur schwer feststellen, ob sich durch das Verschieben die Semantik der Methode ändert. Sensing Variables helfen, an dieser Stelle mehr Sicherheit zu bekommen.

    Post bewerten

    DSL: Domain Specific Languages

    Martin Fowler hat einen kurzen Artikel über DSLs in seinem Blog veröffentlicht. In dem Artikel erklärt er den Unterschied zwischen General Purpose Languages (GPL) und DSLs. Außerdem argumentiert Fowler, dass der Übergang zwischen APIs und DSLs fließend ist. Das API einer Bibiothek könne durchaus vergleichbar sein mit einer DSL.

    Das finde ich sehr überzeugend, vor allem wenn man sich die dynamischen Skriptsprachen a la Ruby, Groovy oder Lisp ansieht. Dort wo in Java eigene DSLs für Build-Skripte (ANT), Datenbankabfragen (Hibernate Query Language, HQL) oder Oberflächenbeschreibung (HTML, JSP) verwendet werden, haben Ruby und Konsorten einfach nur Bibiotheken, die innerhalb der Programmiersprache verwendet werden.

    Interessant finde ich, dass alle Artikel zum Thema DSL, die ich kenne (ich gebe zu, dass das nicht allzu viele sind), sich ausschließlich um Technologie-Domänen kümmern. Es kommen immer wieder dieselben technischen Beispiele für DSLs: SQL, ANT, etc. Das finde ich schade. Schließlich sind die technischen Aspekte in einem Softwareprojekt eher uninteressant im Gegensatz zu den fachlichen. DSLs nur für technische Aufgaben zu verwenden, riecht nach einer Optimierung an der falschen Stelle (wenn ich in einem Bereich 50% Aufwände spare, der nur wenige Prozent meiner Gesamtaufwände ausmacht, ist der Gesamtgewinn marginal).

    Eigentlich müssten wir nach fachlichen DSLs suchen. Interessiert das Niemanden, ist das so schwer oder lese ich einfach nur die falschen Quellen?

    Post bewerten

    Freitag, Juli 28, 2006

    Flow - Softwareentwicklung im Fluss

    Wenn ich heutige Java-Projekte sehe, dann ertappe ich mich immer wieder bei derselben Frage: "Muss das alles so schwerfällig sein?" Um dieser Frage nachzugehen, habe ich mich selbst gefragt, wie ich mir Softwareentwicklung vorstelle. Dazu fällt mir zuerst ein Wort ein: Flow

    Meine Gedanken dazu habe ich in einem Online-Artikel niedergeschrieben.

    Post bewerten

    Sonntag, Juli 23, 2006

    YouOS: Bye, bye Betriebssystem?

    YouOS ist ein webbasiertes Betriebssystem mit allerhand Anwendungen. Das ganze Ding ist noch im Alpha-Stadium, aber die Richtung ist schon mal interessant:

    • Keine Installation von Software auf dem eigenen Rechner.
    • Zugang zu den eigenen Programmen und Daten von jedem Rechner der Welt aus.
    • Automatische Datensicherung
    • Zentrale Sicherheitsmechanismen gegen Viren und andere Angriffe

    Eigentlich ist das Ganze eine naheliegende Idee. Mit Writeboards, Writely, GMail, NumSum, Flickr und anderen sind längst mehr Funktionen im Internet verfügbar, als der durchschnittliche Anwender benötigt. Was bisher fehlte, war die Integration. Man musste mehrere Accounts verwalten, sich URLs merken und konnte schlecht übergreifend über die Systeme arbeiten.

    YouOS leistet das noch nicht vollständig, aber das Potenzial ist da.

    Post bewerten

    Dienstag, Juli 18, 2006

    Buch: Hackers and Painters

    Ich habe gerade das Buch "Hackers and Painters" von Paul Graham durchgelesen. In dem Buch ist eine Reihe von Essays veröffentlicht, die (fast?) alle auch online auf auf der Web-Site von Paul Graham verfügbar sind. Trotzdem lohnt sich das Buch, um es in der Bahn oder im Urlaub zu lesen.

    Die Essays decken verschiedene Themenbereiche ab begonnen vom typischen Hacker-Charakter über Innovationen und Startups in der IT bis hin zum Programmiersprachenentwurf. Dabei vertritt Paul Graham häufig ungewöhnliche Ansichten und Ideen und regt damit zum Denken außerhalb der gängigen Bahnen an (warum die nächste Webanwendung nicht in Lisp schreiben?).

    Mir hat das Buch jedenfalls sehr gut gefallen.

    Post bewerten

    Dienstag, Juli 11, 2006

    Verantwortung in der Softwareentwicklung

    Ich habe zusammen mit Henning Wolf einen Artikel über Berufsethos und Verantwortung in der Softwareentwicklung im Java-Magazin veröffentlicht. Der Artikel ist online verfügbar.

    Der Artikel ist kontroverser als der Titel vielleicht vermuten lässt. Die drei Hauptthesen des Artikels sind:
    1. Jeder ist verantwortlich für alles, was er tut.
    2. Jeder ist verantwortlich für alles, was er denkt.
    3. Jeder ist verantwortlich für alles, was mit ihm geschieht.

    Wer würde das schon einfach so unterschreiben? Wer nicht, sollte den Artikel lesen.

    Post bewerten

    Mittwoch, Juli 05, 2006

    Regeln vs. Eigenverantwortlichkeit in agilen Projekten

    Bei den agilen Methoden gibt es deutliche Unterschiede in den Vorgaben und Regeln, die sie definieren. So ist z.B. Feature-Driven-Development sehr strikt bzgl. Rollen und Verantwortlichkeiten und eXtreme Programming definiert den Entwicklungsprozess sehr detailliert. Auf der anderen Seiten steht Scrum, dass nur grob regelt, wie die Anforderungen in das Projekt eingebracht werden. Die restliche Ausgestaltung des Projektes obliegt den Entwicklern.

    Was ist das bessere Modell? Wieviel Freiheit brauchen die Entwickler, um höchste Produktivität zu erreichen und wieviel Regeln muss man definieren, damit das Projekt nicht im Chaos versinkt?

    Vielleicht hilft bei der Beantwortung dieser Frage das Dreifus-Modell der Qualifikationsaneignung (Skill Acquisition). Demnach brauchen Anfänger Regeln und Vorgaben. Bei der Arbeit in dem so vorgegebenen Rahmen entwickelt sich Erfahrung und Intuition, so dass die Regeln und Vorgaben immer weniger wichtig werden und sogar behindern können. Also wären Feature-Driven-Development und eXtreme Programming eher für Neulinge geeignet und Scrum für erfahrene Entwickler?

    Post bewerten

    Dienstag, Juni 20, 2006

    XP-Days 2006 in Hamburg


    In diesem Jahr finden die XP-Days in Hamburg statt. Sie werden dieses Jahr zusammen von Andrena und it-agile ausgerichtet. Nähere Infos zum Einreichen von Beiträgen gibt es unter http://www.xpdays.de.

    Post bewerten

    Samstag, Juni 17, 2006

    Korrektur zu GroUnit: JUnit ohne Bytecode

    Dierk König wies mich darauf hin, dass mein erstes Argument für GroUnit im Gegensatz zu JUnit so nicht stimmt . Mit groovy.util.AllTestSuite kann man sehr wohl in JUnit auch direkt Groovy-Quellcode testen, ohne diesen vorher nach Bytecode zu compilieren.
    Vielen Dank an Dierk für die Klarstellung.

    Post bewerten

    Sonntag, Juni 11, 2006

    GroUnit: Unittests mit Groovy


    Ursprünglich als reine Fingerübung gedacht, habe ich ein Unittest-Tool für Groovy geschrieben: GroUnit. Das ist nicht weiter schwer, weil Groovy bereits Unterstützung für Unit-Tests mitbringt, allerdings ohne UI. Man kann wg. der nahtlosen Groovy-Java-Integration JUnit auch für Groovy verwenden (siehe z.B. Groovy-Web). Das hat aber ein paar Nachteile:

    • Man muss die Groovy-Klassen nach Bytecode compilieren. Für Produktionscode ist das OK, aber während der Entwicklung verlängert es unnötig die Turn-Around-Zeiten.

    • Wenn ein Test fehlschlägt, bekommt man im Stack-Trace auch die ganzen Core-Reflection-Geschichten angezeigt, die Groovy im Hintergrund durchführt. Dadurch muss man immer erst mal eine Weile im Stacktrace suchen, bis man das eigentliche Problem überhaupt gefunden hat.

    • Seit JUnit 4.0 bringt JUnit keine eigene Benutzungsoberfläche mehr mit. Diese wird von den Entwicklungsumgebungen gestellt. Das ist für Jave wunderbar. Es erzwingt für Groovy aber, dass man eine schwergewichtige Java-Entwicklungsumgebung verwendet. Häufig wäre man mit einem mächtigen Editor besser bedient.


    Ich habe versucht, in GroUnit diese Probleme zu adressieren. Sehr weit bin ich in der ersten Version 0.1 sicher noch nicht gekommen. Aber vielleicht engagieren sich noch weitere Leute für GroUnit und es wird noch was richtig Gutes.
    Zur GroUnit-Homepage mit Download-Möglichkeit.

    Post bewerten

    Freitag, Juni 09, 2006

    Groovy im Vergleich zu Java am Terminplaner-Beispiel

    Ich habe den Terminplaner, den ich als Beispiel für testgetriebene Entwicklung programmiert hatte, von Java auf Groovy migriert. Für den Terminplaner in Java hatte ich testgetrieben ca. 180 Minuten benötigt. Für die Migration nach Groovy habe ich dann ca. 60 Minuten investiert.

    Der erste Unterschied der Groovy-Lösung zur Java-Lösung ist der Wegfall der Klasse TeilnahmeStatus (war Enum bei Java). Die Teilnahme-Status-Informationen landen bei Groovy einfach in der Klasse Teilnahme.

    Die equals- und compareTo-Methoden sind in Groovy einfacher zu implementieren, weil es für beides eigene Operatoren (== und <=>) gibt, die mit Null-Werten umgehen können.

    Bei einer der compareTo-Methoden habe ich bei der Migrationen einen Fehler gefunden, der im Groovy-Code sofort offensichtlich wird. Im Java-Code kann man den Fehler durch die Klammerung beim flüchtigen Lesen übersehen (ist mir beim Schreiben der Java-Lösung ja offensichtlich auch passiert).

    Die betroffene Java-Zeile sieht so aus:

    int startZeitCompare = startZeit.compareTo(startZeit);

    In Groovy wird der Problem sofort offensichtlich:

    int startZeitCompare = startZeit <=> startZeit

    Es muss natürlich heißen:

    int startZeitCompare = startZeit <=> o.startZeit

    Die Zahlen nach der Umstellung lesen sich so:

    Java-Zahlen
    • 5 Fachklassen, 1 Exception-Klasse, 1 Testklasse
    • 37 Methoden inkl. Konstruktoren + 10 Methoden in Testklasse
    • 246 LOC operativ + 144 LOC für Testklasse (inkl. Leerzeilen)
    • 4 For-Schleifen, 4-If-Abfragen


    Groovy-Zahlen
    • 4 Fachklassen, 1 Exception-Klasse, 1 Testklasse
    • 30 Methoden inkl. Konstruktoren + 9 Methoden in Testklasse
    • 203 LOC operativ + 123 LOC für Testklasse (inkl. Leerzeilen)
    • Alle 4 For-Schleifen wurden durch Closures ersetzt, die 4-If-Abfragen blieben bestehen.


    Die Code-Ersparnis lässt sich im Wesentlichen auf folgende Groovy-Konzepte zurückführen:
    • Closures machen For-Schleifen überflüssig und sind kürzer aufzuschreiben.
    • Durch Properties werden Getter und Setter überflüssig.
    • Typecasts entfallen.
    • In den Tests spart die Uniformität von Arrays und Collections Konvertierungen.


    In Groovy habe ich also ca. 80% der LOC (Lines of Code) benötigt, die ich für die Java-Lösung benötigte. Das hört sich erstmal nicht nach einem Quantensprung an. Allerdings muss man bedenken, dass ich „lediglich“ Java durch das doch sehr ähnliche Groovy ersetzt habe. Also hat eine Einzelmaßnahme 20% Code-Ersparnis gebracht. Setzt man das einfach mal naiv mit 20% Kostenersparnis gleich, ist man sehr schnell in Regionen, die interessant erscheinen (die meisten Offshoring-Untersuchungen sprechen von geringeren Einsparungspotenzialen).

    Außerdem ist zu bedenken, dass mein Terminplaner-Beispiel die Strukturen in den Vordergrund stellt und die Daten ignoriert (so hat der Benutzer nur seinen Namen und der Termin nur 4 Datenfelder). In einer vollständigen Terminplaner-Anwendung sind viel mehr Datenfelder zu verwalten (MS-Outlook hat für Kontakte so um die 30 Datenfelder). Und gerade wenn es nur um das Halten von Datenfeldern geht, spielt Groovy seinen LoC-Vorteil aus. Die 30 Datenfelder würden in Groovy ca. 10 LoC bedeuten und in Java ca. 130 LoC (beide Zahlen inkl. Leerzeilen).

    Nicht zuletzt habe ich die Terminplaner-Anwendung relativ stumpf auf Groovy umgestellt. Ich muss prüfen, ob sich der Code durch fortgeschrittene Groovy-Konzepte noch weiter vereinfachen lässt.

    Der Groovy-Code findet sich hier zum Download.

    Post bewerten

    Samstag, Mai 20, 2006

    TDD-2: Testabdeckung bei TDD-Code

    Ich habe mal die Testabdeckung bei meinem Terminplaner-Beispiel analysiert, das ich testgetrieben entwickelt habe. Dabei hat sich herausgestellt, dass die Testabdeckung nicht bei 100% lag, wie ich zunächst vermutet hätte, sondern bei gut 80%. Nach einigem Nachdenken und Rumprobieren habe ich entschieden, die Testabdeckung nicht auf 100% zu bringen (was problemlos möglich gewesen wäre).
    Die Reports der Testabdeckung sowie die Diskussion der Analyseergebnisse finden sich hier zum Download.

    Post bewerten

    Freitag, Mai 19, 2006

    Software-Architektur: Die vergessene Dimension?

    Wenn über Software-Architektur gesprochen wird, werden ihr die solche Funktionen zugeschrieben - sowohl bei klassischer Betrachtung wie auch aus dem Blickwinkel agiler Methoden:
    • Rahmen für die Realisierung der funktionalen Anforderungen setzen
    • Nicht-funktionale Anforderungen wie Wartbarkeit, Robustheit, Sicherheit etc. sichern

    Dabei wird aus meiner Sicht ein ganz wichtiger Faktor übersehen oder ignoriert. Die Software-Architektur beeinflusst ganz wesentlich die weitere Ausgestaltung des Entwicklungsprozesses und der Projektorganisation. Wie aufwändig die Koordination verschiedenen Entwicklungsteams in einem großen Projekt wird, ist ganz wesentlich von der gewählten Architektur bestimmt.

    Ich habe inzwischen eine ganze Reihe von Projekten erlebt, in denen die Architektur gewählt wurde, ohne auf den Entwicklungsprozess und die Projektorganisation zu achten. Die Konsequenz war immer eine sehr unangenehme Beschränkung der Möglichkeiten im Projektverlauf. In einem Fall hätte man ein schlecht laufendes Projekt retten können, wenn man die Entwicklermannschaft von 8 auf 20 Entwickler hätte erhöhen können. Die Architektur hat das aber verhindert. In einem anderen Fall hat die gewählte Architektur erzwungen, dass man ganz genau vorher planen musste, wer was tun muss. Als der Umstieg auf eine agilere, reaktivere Vorgehensweise mit kurzen Releasezyklen anstand, war das faktisch nicht möglich.

    Aus meiner Sicht muss bei der Definition und Weiterentwicklung der Architektur jeweils auch berücksichtigt werden, welche Beschränkungen und Möglichkeiten die Architektur für den Entwicklungsprozess und die Projektorganisation mit sich bringt. Und das bedeutet für viele Software-Architekten eine ganz neue zusätzliche Dimension in ihrer Tätigkeit.

    Post bewerten

    Dienstag, Mai 02, 2006

    TDD-1: Testgetriebene Entwicklung am Beispiel

    Ich habe zum Spaß mal zwei Sessions zu je 90 Minuten am Beispiel "Terminplaner" testgetrieben programmiert (Java und JUnit). Protokoll und Code gibt es hier zum Download. Vielleicht hilft es ja bereits in der jetzigen Form dem einen oder anderen beim Verständnis von TDD?

    Richtig interessant wird es aber erst später. Dann will ich verschiedene Aspekte des Beispiel-Codes und des Vorgehens beleuchten.

    Zwei interessante Beobachtungen kann man aber bereits jetzt machen:
    1. Ich war beim Programmieren wg. der fortgeschrittenen Zeit immer wieder mal abgelenkt. Das testgetriebene Vorgehen hat mich immer wieder schnell auf den richtigen Weg gebracht.
    2. Es gibt nur eine Testklasse für 5 Klassen. Man hätte auch Tests für die einzelnen Klassen schreiben können. Das schien mir aber immer doppelte Tests zu implizieren.

    Post bewerten

    Sonntag, März 26, 2006

    Revenge of the Nerds

    Durch Dierk König bin ich auf einen Artikel von Paul Graham aus dem Jahr 2002 gestoßen: Revenge of the Nerds. Dort argumentiert Paul Graham, dass die Programmiersprachen sich mit der Zeit immer weiter an LISP angenähert haben, allerdings immer noch nicht die Ausdruckskraft von LISP erreicht haben (das ist schon erstaunlich, wenn man bedenkt, dass LISP bereits 1958 erfunden wurde). Außerdem behauptet er, dass die Programmiersprache eine große Rolle bei der Produktivität spielt. Die zweite These erscheint mir sofort plausibel und passt auch mit den gängigen Untersuchungen zur Produktivität in Softwareprojekten zusammen.
    Die erste These war mir neu, scheint mir aber ebenso plausibel. Sie hat mich dazu animiert, nochmal an meine Studienzeit zurückzudenken, in der LISP-Programmierung zur Grundausbildung gehörte. Und tatsächlich: Die Programmiersprachen sind immer LISP-ähnlicher geworden und haben LISP immer noch nicht erreicht. Und ich trauere irgendwie doch immer mal wieder der Art und Weise nach, wie man LISP programmieren konnte. Es ist doch schon erstaunlich, dass man mit LISP bereits die Möglichkeit hatte, sich für sein Problem eine adäquate Sprache zu definieren und dann das Problem in dieser Sprache zu lösen. Modern ausgedrückt ist in LISP von Anfang an die Möglichkeit enthalten gewesen, DSLs (Domain Specific Languages) zu definieren. Smalltalk, Ruby, Python und Groovy sind trotz ihrer Dynamik nicht so ausdrucksstark geworden. Aber viel fehlt nicht mehr. Warten wir noch ein oder zwei Programmiersprachengenerationen ab und wir programmieren alle in LISP. Das heißt dann vielleicht etwas anders und hat vielleicht ein leicht andere Syntax, aber konzeptuell wird es LISP sein - wenn Paul Graham Recht hat. Irgendwie freue ich mich darauf und hoffe, dass ich selbst dann noch zum programmierenden Volk gehöre.

    Post bewerten

    Skype-Diskussion Java-Magazin: Technology First

    Im Java-Magazin 04/2006 wurde ein Artikel mit einer Skype-Diskussion veröffentlicht, an der ich auch beteiligt war. In der Diskussion ging es um die Frage, warum wir als Softwareentwickler die vielen tollen Techniken so selten einsetzen, obwohl wir sie lange kennen (Bsp.: Test-First, Entwurfsmuster etc.).
    Vor kurzem wurde ich von einem Leser des Artikels gefragt, ob die Diskussion tatsächlich so stattgefunden hat oder ob sie erfunden wurde. Die Diskussion hat tatsächlich stattgefunden und das Protokoll wurde lediglich etwas gekürzt und um Rechtschreib- und Grammatikfehler bereinigt.
    Der Artikel als PDF findet sich hier.

    Post bewerten

    Sonntag, März 05, 2006

    Ruby on Rails vs. ???

    Zur Zeit ist Ruby on Rails in aller Munde. Von vielen wird es für die Technologie der Zukunft gehalten. Aber gegen wen ist Ruby on Rails eigentlich positioniert?

    Ich bin kein Experte für Skriptsprachen a la PHP oder Perl, habe aber das Gefühl, dass Ruby on Rails gegenüber diesen Sprachen keinen wahnsinnig großen Fortschritt darstellt - klar ist die Sprache Ruby cooler, aber kann man dadurch seine Webanwendungen soviel schneller schreiben?

    Bliebe als Konkurrent also Java. Dort dürfte Ruby on Rails nur für einen kleinen Teil der existierenden Java-Kunden interessant sein. Wer sich strategisch für Websphere als Application-Server entscheidet, kann dann schlecht wichtige Anwendungen in Ruby in einer anderen Ablaufumgebung entwickeln. Bleiben also die Kunden übrig, die heute Java-Projekte starten und die sich keine strategischen Gedanken über Transaktionsmonitore oder Application-Server machen.

    Wenn sich allerdings Groovy und Grails als Java-Technologien verbreiten, ist das dann für die existierenden Java-Kunden nicht viel attraktiver als Ruby on Rails? Immerhin lassen sich ihre existierenden Projekte leicht mit Groovy integrieren.

    Ich finde Ruby als Sprache cool und Ruby on Rails für eine bestimmte Art von Anwendungen auch. Allerdings befürchte ich, dass der Coolness-Faktor nicht ausreicht, um eine nennenswerte Verbreitung zu finden. Die allermeisten Entwickler suchen sich ihre Programmiersprache schließlich nicht selbst aus. Und Manager sind bekanntermaßen relativ immun gegen Coolness...

    Post bewerten

    Donnerstag, Februar 16, 2006

    Hibernate-Buch erschienen

    Hibernate 3Ich habe soeben ein Belegexemplar des Buches "Hibernate - Persistenz in Java-Systemen mit Hibernate 3" vom dpunkt-Verlag erhalten, dass ich zusammen mit Robert Beeger, Arno Haase und Sebastian Sanitz geschrieben habe.

    Das Buch ist bei Amazon noch im Status "noch nicht erschienen", aber das wird sich in den nächsten Tagen ändern.

    Am 8. Mai 2006 halten wir auf der JAX in Wiesbaden einen ganztägigen Power-Workshop zu Hibernate 3.

    Post bewerten

    Samstag, Februar 04, 2006

    Defect Driven Design

    Darauf hat mich Jürgen Ahting in seinem Blog aufmerksam gemacht: Defect Driven Design.
    Demnach erklärt man einfach direkt nach Vertragsunterzeichnung, die Softare sei fertig für den Akzeptenztest. Der Kunde wird dann sagen, dass er das Icon auf dem Bildschirm nicht finden kann. Und damit hat man den ersten Fehler, der zu korrigieren ist. Also baut man ein Icon und erklärt erneut die Bereitstellung der Software. Der Kunde clickt auf das Icons und es passiert nichts. Und damit hat man den nächsten Fehler. Und so weiter und so fort.

    Das hört sich natürlich absurd an, aber ein paar sinnvolle Denkanstöße kann man da trotzdem draus gewinnen, glaube ich.

    Post bewerten

    Sonntag, Januar 29, 2006

    Agile Methoden unter Beschuss oder: Die Rache des Wasserfalls

    siehe http://www.waterfall2006.com

    Post bewerten

    Dienstag, Januar 24, 2006

    Blog zur Kundenrolle in Softwareprojekten

    Jürgen Ahting hat jetzt auch einen Blog. Hier geht es um die Kundenrolle in Softwareprojekten sowie die Wirtschaftlichkeit von Softwareprojekten.

    Post bewerten

    Sonntag, Januar 22, 2006

    Groovy kann Typen

    Ich hatte mir in einem früheren Blog-Eintrag für dynamische Sprachen wie Ruby gewünscht, dass man optional einen Typ nennen kann, der dann dynamisch zur Laufzeit geprüft wird. So kann man meiner Meinung nach die Lesbarkeit von Quellcode erhöhen. Nehmen wir als Beispiel folgende Methode (Syntax ist informell):

    def loescheKunden(kunde)

    Dann muss man die Doku oder die Methodenimplementation lesen, um herauszufinden, was hier übergeben werden muss. Das Kundenobjekt, die Kundennummer oder der Kundenname?

    Eine Deklaration mit Typ würde diese Frage sofort beantworten:

    def loescheKunden(Kunde kunde)

    Jetzt habe ich mich näher mit Groovy beschäftigt und festgestellt, dass das genau so in Groovy funktioniert. Man kann optional Typen angeben, die dann dynamisch geprüft werden. Wenn man keinen Typ angibt, verhält sich Groovy wie die anderen dynamischen Sprachen und prüft den Typ auch nicht.

    Post bewerten

    Donnerstag, Januar 12, 2006

    XP und Software-Engineering

    Vor ein paar Tagen hat mich Tammo Freese mit folgendem Argument infiziert:

    Wikipedia definiert: Die Softwaretechnik (software engineering) als Teilgebiet der Informatik beschäftigt sich mit der standardisierten ingenieursmäßigen Herstellung von Software und den damit verbundenen Prozessen.

    Die einzige Methode zur Softwareentwicklung, die sich wirklich Software Engineering auf die Fahnen schreiben darf, ist demnach eXtreme Programming. Schließlich definieren alle anderen Methoden nur grobe Blöcke für die weitere Arbeit. Wie diese Blöcke konkret mit Arbeit zu füllen sind, lassen sie offen. Nur eXtreme Programming definiert hinunter bis auf die Ebene von Minuten, wie vorzugehen ist: Test erweitern, bis er fehlschlägt. Code so ändern, dass der Test wieder durchläuft. Und dann geht es wieder von vorne los.

    Das ist ein weiteres Indiz dafür, dass die Industrialisierung der Softwareentwicklung erst jetzt mit den agilen Methoden stattfindet.

    Post bewerten

    Seminar: Kundenrolle in agilen Projekten

    Agile Projekte versprechen früh einsetzbare Software mit einem besonders günstigen Kosten-Nutzen-Verhältnis. Damit die Erfolge mit agilen Projekten auch realisiert werden können, muss der Kunde seiner geänderten Rolle auch gerecht werden. Am 20.02.2006 findet zum zweiten Mal das Seminar Aufgaben und Chancen des Kunden bei agiler Softwareentwicklung der Deutschen Informatik Akademie (DIA) in Köln statt.

    Ich führe das Seminar zusammen mit Jürgen Ahting durch.

    Auszug aus der Seminarankündigung: Agile Softwareentwicklung (z.B. mit dem Extreme Programming, XP) ist mehr als ein neues Schlagwort. In vielen Praxisprojekten wurde bereits die Leistungsfähigkeit agiler Ansätze nachgewiesen. Die konsequente Zusammenstellung erfolgreicher und bewährter Planungs-, Arbeits- und Programmiertechniken sowie die aufmerksame Beachtung und Nutzung ihrer gegenseitigen Einflüsse bietet neue Chancen zur erfolgreicheren und effektiveren Entwicklung von Software. Insbesondere ergeben sich zusätzliche Möglichkeiten, die Risiken und Kosten von Projekten zu steuern und zukünftige Kosten zu verringern.

    Agile Softwareentwicklung zielt darauf ab, mit vorgegebenen Ressourcen so schnell wie möglich den maximalen Nutzen für den Kunden zu realisieren, ohne dabei die Qualität zu kompromittieren. Ein wesentlicher Erfolgsfaktor für diese Nutzenoptimierung ist die enge und flexible Zusammenarbeit zwischen Kunden und Entwicklungsteam. Kurze Releasezyklen führen zu frühem Return-On-Investment und geben schnelles Feedback über Angemessenheit und Qualität der Software.

    Die Vorteile des agilen Vorgehens sind leichter zu verstehen als umzusetzen, weshalb auch agile Projekte scheitern können. Da der Kunde beim agilen Vorgehen eine zentrale Rolle einnimmt, kann er die Vorteile nur dann voll ausschöpfen, wenn er seine Rolle auch genau versteht und optimal ausfüllt. Deshalb ist es nicht nur für die Ausführenden sondern auch für die auf Kundenseite maßgeblich an agilen Softwareentwicklungsprojekten Beteiligten extrem wichtig, aus der praktischen Erfahrung in Projekten verschiedenster Größenordnungen zu lernen. So können sie die wirtschaftlichen Hintergründe der agilen Praktiken verstehen und ihre Rolle als Auftraggeber sinnvoll wahrnehmen und geschickt agieren. Nur dann wird es möglich sein, agile Entwicklungsprojekte optimal zu gestalten und zum Erfolg zu führen.

    Nähere Informationen zu dem Seminar gibt es auf der Website der DIA oder über den Flyer zum Seminar.
    Anmeldungen für das Seminar nimmt die DIA direkt entgegen.

    Post bewerten

    Sonntag, Januar 08, 2006

    Codelängen

    Bei meinen Recherchen zu Groovy bin ich über ein interessantes Beispiel gestoßen. Dasselbe kleine Programm einmal in C#, in Java und in Groovy sowie Ruby (Achtung: Der Ruby-Quellcode findet sich in den Kommentaren zu der Groovy-Seite. Man muss dort also nach unten scrollen. Leerzeilen habe ich nicht mitgezählt und ich habe bei Java und C# ein paar Zeilen abgezogen, die der Formatierung im Web geschuldet waren):

    • C#: 45 Zeilen Code

    • Java: 56 Zeilen Code

    • Groovy: 14 Zeilen Code

    • Ruby: 17 Zeilen Code



    Von der unterschiedlichen Zeilenanzahl zwischen Groovy und Ruby sollte man sich nicht verwirren lassen. Im Groovy-Beispiel wurde eine Methode einfach in eine Zeile geschrieben, für die im Ruby-Beispiel drei Zeilen verwendet wurden. Man kann sagen, dass die Implementation in Groovy und Ruby identisch ist - abgesehen von syntaktischen Kleinigkeiten.

    Bedeutet das jetzt einen relevanten Unterschied für die Praxis? Moderne IDEs helfen, auch den umfangreicheren Java- und C#-Code schnell zu erstellen. Der Autor der Java-Version hat mit IntellJ IDEA nur 10% des Codes wirklich eingetippt.

    Ich meine, da ist sehr wohl ein Unterschied. Schließlich wird Quellcode viel häufig gelesen als geschrieben. Für die Produktivität der Entwicklung ist daher ausschlaggebed, wie aufwändig das Lesen und Verstehen existierenden Codes ist und nicht wie schnell man den Code tippen kann. Und die einschlägigen Statistiken sagen, dass die Anzahl der Zeilen Code, pro Personentag entstehen ebenso konstant ist, wie die Anzahl der Fehler, die man durchschnittlich je 1.000 Codezeilen macht. Ob man also 1.000 Zeilen Code mit Java oder Groovy schreibt: Man braucht gleich lang und programmiert die gleiche Anzahl Fehler in den Code. Nur, dass man in 1.000 Zeilen Groovy viel mehr Funktionalität programmieren kann als in 1.000 Zeilen Java.

    Post bewerten

    Groovy

    Dynamische Programmiersprachen a la Python und Ruby haben in den letzten Jahren viel Aufmerksamkeit erhalten. Ein wenig untergegangen ist da bisher Groovy. Groovy ist Bestandteil der Java-Platform und mit dem JSR-241 spezifiziert.

    Groovy lehnt sich bei der Syntax an Java (Groovy-Syntax ist Java-Syntax mit weniger Regeln) an und ist von den Sprachkonstrukten ähnlich zu Python oder Ruby. Besonders interessant ist Groovy für Java-Programmierer, weil es insbesondere eine gute Integration mit Java gibt. Man kann Groovy-Code ganz einfach aus Java heraus aufrufen und umgekehrt auch Java-Code einfach aus Groovy. Damit hat man insbesondere gleich das ganze JDK in Groovy zur Verfügung.

    Dadurch kann man z.B. Swing-Code mit Groovy schreiben und die Kernfunktionalität der Anwendung mit Java. Vorteil: Der Groovy-Swing-Code ist kürzer und verständlicher als derselbe Code in Java.

    Und es gibt das Groovy-Äquivalent zu Ruby on Rails: Grails.

    Weitere - gut strukturierte - Informationen zu Groovy gibt es hier.

    Post bewerten

    Donnerstag, Januar 05, 2006

    Industrialisierung der Software

    Seit Jahrzehnten wird immer wieder gefordert, die Softwareentwicklung müsste endlich aus der Produktion lernen. Insbesondere die Planbarkeit der Softwareentwicklung wurde als Ziel formuliert. Automatisierte Code-Generierung mit CASE-Tools, Software-Fabriken, vollständige Spezifikationen etc. haben versucht, diesen Anspruch einzulösen - mit allenfalls bescheidenem Erfolg.
    Als Kontrapunkt dazu sind um die Jahrtausendwende (das hört sich doch mal monumental an :-) die agilen Methoden wie eXtreme Programming, SCRUM, Crystal etc. entstanden. Dabei hat sich immer deutlicher herausgestellt, dass sich in den agilen Methoden viele Ideen wiederfinden, die bereits das Produktiongewerbe revolutioniert hatten: Lean Production, Lean Manufacturing, Just In Time, Kaizen. Auf den Punkt gebracht haben das die Poppendiecks in ihrem empfehlenswerten Buch Lean Software Development.
    Also kann man sagen, dass mit den agilen Methoden die Industrialisierung doch noch Einzug in die Softwareentwicklung gehalten hat - nur eben auf eine ganz andere Art als ursprünglich gefordert.

    Post bewerten

    Mittwoch, Januar 04, 2006

    eXtreme Programming in der Financial Times Deutschland

    In der Financial Times Deutschland ist gerade ein Artikel über eXtreme Programming erschienen. Interessanterweise wird die Sinnharftigkeit nicht mehr in Frage gestellt. Jetzt machen es die Firmen nicht, weil die die Entwickler nicht wollen oder können. Und gleichzeitig sagen die Entwickler überall, sie können XP nicht einführen, weil ihr Management nicht mitspielt...

    Post bewerten

    Kritik zu unserem XP-Buch

    Hier gibt es eine Kritik zu Buch über eXtreme Programming, dass ich zusammen mit Henning Wolf und Martin Lippert geschrieben habe.

    Post bewerten

    Sonntag, Januar 01, 2006

    Hibernate 3-Buch: Beispielcode und XDoclet-Kapitel online

    Buch: Fit for Developing SoftwareIch habe an einem Buch über Hibernate 3 mitgeschrieben (zusammen mit Robert Beeger, Arno Haase und Sebastian Sanitz). Das Buch wird im Februar 2006 im dpunkt-Verlag erscheinen. Bereits jetzt gibt es Beispielcode aus dem Buch sowie ein Kapitel über XDoclet zur Generierung der Mapping-Dateien online zum Download.

    Post bewerten