PFGrid SWT Komponenten

PFGrid SWT (http://www.pfgrid.com/Index_Eclipse.aspx) ist ein TreeList- und Grid-SWT-Widget mit einem dynamischen Renderer-Ansatz, so dass das Control wahlweise in Windows-XP, Vista- oder Office2007-style dargestellt werden kann.

PFGrid.SWT EclipsePFNavigationBar.SWT EclipsePFPanel.SWT EclipsePFButton.SWT EclipsePFReflectionImage.SWT EclipsePFProgressBar.SWT: ProgressBar and state-control for JAVA SWTPFCheckBox.SWT: Custom Checkbox-widget for SWT JAVAPFHyperlink.SWT: Hyperlinks for JAVAPFRoundedToolbar.SWT: Toolbar-widget for JAVA

Eigene Renderer sind einfach zu implementieren. Beliebige SWT- aber auch Swing-controls können als Cell-Editoren verwendet werden. Das Grid verfügt über Features wie Excel-cell-copy oder Outlook-like grouping für Spalten, was für SWT-Grids einzigartig ist. JFace-Viewer für Table- und Tree-Darstellungen runden das widget ab. PFGrid kann als Eclipse-Plugin aber auch als standalone-jar in jeder Java-Applikation verwendet werden. Neben dem PFGrid-Widget wird auch ein Outlook-like NavigationBar-Widget mitgeliefert. Es handelt sich um eine kommerzielle Bibliothek.

Inselupdate: Lokale und innere anonyme Klasse für einen Timer nutzen

Lokale Klasse für einen Timer nutzen

Damit die Beispiele etwas praxisnäher werden, wollen wir uns anschauen, wie ein Timer wiederholende Aufgaben ausführen kann. Die Java-Bibliothek bringt hier schon alles mit: Es gilt ein Exemplar von java.util.Timer() zu bilden und der Objektmethode scheduleAtFixedRate(…) ein Exemplar vom Typ TimerTask zu übergeben. Die Klasse TimerTask schreibt eine abstrakte Methode run() vor, in die der parallel und regelmäßig abzuarbeitende Programmcode gesetzt wird.

Nutzen wir das für ein Programm, welches uns sofort und regelmäßig daran erinnert, wie wichtig doch Sport ist:

public class SportReminder {

public static void main( String[] args ) {

  class SportReminderTask extends TimerTask {

   @Override public void run() {

    System.out.println( "Los, beweg dich du faule Wurst!" );

   }

  }

  new Timer().scheduleAtFixedRate( new SportReminderTask(), 0 /* ms delay */, 1000 /* ms period */ );

}

}

Unser Klasse SportReminderTask, die TimerTask erweitert, ist direkt in main(…) deklariert. Das erzeugte Exemplar kommt später in scheduleAtFixedRate(…) und los rennt der Timer, um uns jede Sekunde an die Wichtigkeit von Bewegung zu erinnern.

Nutzung einer anonymen innerer Klassen für den Timer

Eben gerade haben wir für den Timer extra eine neue lokale Klasse deklariert, aber genau genommen haben wir diese nur einmal nutzen müssen, nämlich um ein Exemplar bilden, und scheduleAtFixedRate(…) übergeben zu können. Das ist ein perfektes Szenario für anonyme innere Klassen. Aus

class SportReminderTask extends TimerTask {

@Override public void run() { … }

}

new Timer().scheduleAtFixedRate( new SportReminderTask(), … );

wird

new Timer().scheduleAtFixedRate( new TimerTask() {

@Override public void run() {

  System.out.println( "Los, …" );

}

},

0 /* ms delay */,

1000 /* ms period */);

Im Kern ist es also eine Umwandlung von new SportReminderTask() in new TimerTask() { … }. Von dem Klassennamen SportReminderTask ist nichts mehr zu sehen, das Objekt ist anonym.

GunZip-Kommandozeilenprogramm in Java

package com.tutego.insel.io.zip;

import java.io.*;
import java.nio.file.*;
import java.util.zip.GZIPInputStream;

public class gunzip {

  public static void main( String[] args ) {
    if ( args.length != 1 ) {
      System.err.println( "Benutzung: gunzip <source>" );
      return;
    }

    String filename = args[ 0 ];
    Path srcPath, destPath;

    if ( filename.toLowerCase().endsWith( ".gz" ) ) {
      srcPath  = Paths.get( filename );
      destPath = Paths.get( filename.replaceAll( "\\\\.gz$", "" ) );
    }
    else {
      srcPath  = Paths.get( filename + ".gz" );
      destPath = Paths.get( filename );
    }

    try ( InputStream is  = new GZIPInputStream( Files.newInputStream( srcPath ) ) ) {
      Files.copy( is, destPath );
    }
    catch ( IOException e ) {
      System.err.println( "Fehler: Kann nicht entpacken " + filename );
    }
  }
}

Frage: Sollte man überall this. verwenden?

Ich verwende es nicht, aus einem guten Grunde: Ein this macht mir explizit deutlich, dass es eine lokale Variable gibt, die vom Namen hier die Objektvariable überdeckt, siehe typisches Beispiel vom Getter:

public void setAge( int age )
{
  this.age = age;
}

Wenn ich this. sehe, erwarte ich einfach, dass es eine Überschattung gibt und ich würde mich wundern, wenn this. einfach "nur so" verwendet wird. Ich finde es wichtig, dass man durch solche Idiome etwas aussagt.

Jobangebot Java-Entwickler

Für den Einsatz bei einem Kunden wird benötigt ein versierter Java-Entwickler (m/w) (bereits mit ausreichender Projekterfahrung, Erfahrungen in Anwendungsdesign und mit Architektur-Verständnis) mit folgenden techn. Kenntnissen:

  • Java (logisch)
  • Hibernate
  • Subversion (Erfahrungen wären gut, nicht zwingend)
  • Ant
  • Swing
  • Framework: Wings (Erfahrungen wären gut, nicht zwingend)
  • Framework: Vaadin (Erfahrungen wären gut, nicht zwingend)
  • Datenbank MySQL
  • Einsatz: süddeutscher Raum
  • ab sofort, ½ Jahr bis länger

Bewerbungen bitte direkt an elke.roetzer<ÄT>md-consulting<PUNKT>de schicken.

GMail-URLs generieren

private static String createGMailUrl( String to, String cc, String subject, String body )
{
  StringBuilder result = new StringBuilder( "https://mail.google.com/mail/?view=cm&tf=0" );
  
  if ( to != null && ! to.isEmpty() )
    result.append( "&to=" ).append( to );
  if ( cc != null && ! cc.isEmpty() )
    result.append( "&cc=" ).append( cc );
  if ( subject != null && ! subject.isEmpty() ) {
    try {
      result.append( "&su=" ).append( encode( subject ) );
    }
    catch ( UnsupportedEncodingException e ) {
      e.printStackTrace();
    }
  }
  if ( body != null && ! body.isEmpty() ) {
    try {
      result.append( "&body=" ).append( encode( body ) );
    }
    catch ( UnsupportedEncodingException e ) {
      e.printStackTrace();
    }
  }
  return result.toString();
}
private static String encode( String param ) throws UnsupportedEncodingException
{    
  byte[] utf8 = param.getBytes( "utf-8" );
  StringBuilder result = new StringBuilder( param.length() * 3 );
  for ( int i = 0; i < utf8.length; i++ )
  {
    String c = Integer.toString( utf8[ i ] & 0xFF, 16 );
    result.append( '%' ).append( c.length() == 1 ? "0" + c : c );
  }
  return result.toString();
}

JavaFX 2.1 ist fertig

Download unter http://www.oracle.com/technetwork/java/javafx/downloads/index.html. Aus den http://docs.oracle.com/javafx/release-documentation.html:

  • Media H.264 and AAC support

  • Mac OS X support

    Applications must be packaged for the desktop, Web and Web Start applications are not yet supported.

  • LCD text

  • UI enhancements, including controls for Combo Box, Stacked Chart, and application-wide menu bar

  • Webview to support JavaScript to Java method calls

Osterrätsel (C, nicht Java)

Linus Torwalds stellt in seinem G+ Stream zwei C-Ausdrücke vor:

/* Modified Carl Chatfield G+ version for 32-bit */
long a = (mask-256) >> 23;
long b = mask & 1;
return a + b + 1;

/* Jan Achrenius on G+ for 64-bit case */
return mask*0x0001020304050608 >> 56;

Die Frage für Rätselfreunde ist (ohne den G+-Beitrag gelesen zu haben): Was berechnen die Ausdrücke?

Eigene Linkseiten und Dokumentationen zu Java

Wie jedes System entwickelt sich Java weiter und über zentralen Neuerungen informiert der Blog. Speziell zu den neuen Java-Versionen geben dedizierte Unterseiten detaillierte Updates und eine Fülle von Links:

Nicht nur die Java SE entwickelt sich weiter, auch die Java Enterprise Edition. Einen großen Sprung gab es von J2EE 1.4 auf Java EE 5. Neues in den Enterprise JavaBeans (EJB) 3 listet die zentralen Neuerungen der Enterprise Java Beans 3 im Gegensatz zur EJB 2 auf.

In der professionellen Java-Entwicklung reicht die Java SE/Java EE nicht aus. Zu viele Lücken gibt es, und es wäre ein Fehler, wenn Entwickler-Teams Zeit aufwänden, diese Lücken selbst zu füllen. Die Seiten Open-Source Bibliotheken sowie freie und kommerzielle Swing-Komponenten geben einen Überblick, was quelloffen und kommerziell am Markt verfügbar ist.

Effektive Entwickler schreiben nicht nur wenig Code, sondern minimieren auch ihre Arbeit in Entwicklungsumgebungen, in dem sie zum Beispiel Schritte automatisieren oder Short-Cuts verwenden. Speziell für die IDE Eclipse listet die Seite über beliebte Eclipse-Plugins gute Erweiterungen auf.

Softwareentwicklung bedeutet nicht nur Software neu zu entwickeln, sondern auch bestehende Programme zu lesen und zu verändern. Aus einem misslungenen historisch gewachsenen System soll am Besten ein modernes, leicht zu pflegendes System werden. Die Refactorings von Martin Fowler auf Deutsch geben einen Eindruck, was schlecht riechender Code ist, und wie Transformationen von schlechtem Code in gutem Code aussehen.

Die Anzahl der Java-Bücher ist seit Beginn der Programmiersprache unübersichtlich geworden. Die Seite Java Bücher Hits und Flops gibt eine Übersicht über den Literaturmarkt und gibt eine Einschätzung, welche Werke für Softwareentwickler ein Gewinn darstellen.

Kritiker bemängeln, dass sich Java zu langsam entwickelt. Das ist nicht ganz falsch, doch gilt es zunächst zu unterscheiden, was damit gemeint ist. Java ist ein Dreigespann aus der Sprache, den Bibliotheken und der JVM. Änderungen an der JVM sind von der Kritik ausgenommen, es gibt kaum Eigenschaften, die bemängelt werden (Reified Generics/2 ist gewünscht). Probleme mit der Java API lassen sich durch API-Ergänzungen wie Google Guava oder Apache Commons beheben. Unter der Annahme, dass die die JVM eine solide Basis darstellt, und Interoperabilität mit den existierenden Bibliotheken gewünscht ist, lohnt sich ein Blick auf alternative Sprachen für die JVM.

JSR 357: Social Media API ist in der Entstehung

http://jcp.org/en/jsr/detail?id=357. Aufgabe:

This specification proposes to provide an API for accessing social information networks, both Public (Facebook, Twitter, Google+, LinkedIn, Xing, Yammer,…) and Corporate, e.g. within the Enterprise or Institution (University, Hospital, etc.) The primary API will build upon standards and formats specified by OpenSocial 2.0 or other relevant technologies defined by standard organizations and leading social networks.

Warum eine schlechte Webseite mich (fast) 160 € kostete und mich Air Namibia beinahe als Kunden verlor

Buchungsseiten im Internet sind kein neues Phänomen um so erstaunlicher ist es, dass es bei den Typ von Webseiten noch etwas zu optimieren gib. Als ich letztes Jahr eine weitere Reise nach Namibia plante, wählte ich Air Namibia aus, mit denen ich bisher noch nicht geflogen bin. Air Namibia fliegt von Frankfurt nach Windhoek, aber auch zu anderen Zielen. Um nach Frankfurt zu kommen kann man den Zug nehmen, denn Air Namibia bietet ein Rail & Fly Ticket an, tolle Sache!

What is Rail   Fly    Air Namibia-125410

Die HTML-Warning ist zwar peinlich, und auch, dass der Text englisch ist, obwohl “Deutsch” als Sprache voreingestellt ist, aber das ist nicht mein Problem.

Alle Flüge gehen in Deutschland von Frankfurt aus, daher ist in der Flugsuche bei “From” der Flughafen Frankfurt nur logisch:

FromAuswahl

Von dort geht es weiter, man gibt den Zielflughafen an, macht die Buchung, fertig. Einfache Sache.

Aber was ist mit dem Zugticket? Bei der Buchung wunderte mich schon, warum ich nicht auswählen konnte, dass ich Rail & Fly mit dazu buchen möchte. Wenn man bei Fluglinien wie Emirates einen Flug bucht, dann bietet diese eine schön Checkbox. Da mir das bei Air Nambia fehlt, schickte ich gleich nach der Buchung eine EMail mit der Frage ab, ob mein Ticket nun automatischer Bestandteil wäre, und wenn, wo meine IDs sind. Falls ich etwas falsch gemacht hätte, bat ich, mir das Ticket dazuzubuchen, da es für mich sehr wichtig wäre. Mehrfach frage ich nach, es ging hin und her, keine klare Antwort, immerhin eine EMail von Sylvia S.:

Dear Mr Ullenboom

As your request, rail ticket has been booked accordingly you have to pay at our office in advised.

Kind regards

“rail ticket has been booked accordingly“ Ok, gut. “Pay”? Hm, was soll das? Und “in advised”? Naja, und wo waren die Ticket-Nummern?  Ich rief in Deutschland an und man gab mir die beiden IDs für den Ticket-Automaten. Das war also mein Rail & Fly. Dachte ich.

Einen Tag vor Abflug ging ich zum Bahnhof, wollte mir dir Ticket ausdrucken, doch der Automat nahm die ID nicht an. Also rief ich wieder Air Namibia an, schilderte meiner Gesprächsperson die Situation, sie gab mir noch einmal die IDs durch. Die IDs waren die gleichen; es funktionierte nicht. Ich fragte am Telefon, was ich machen muss, aber sie sagte nur, die Daten kämen von der Bahn und sie könne mir nicht weiter helfen. Ich hatte also IDs bekommen, die warten jedoch ungültig.

Es kam, wie es kommen musste: ich musste zwei Zugtickets für insgesamt über 160 € selbst kaufen. Ich flog nach Namibia, nach ein paar Wochen wieder zurück und schickte eine EMails mit den Scan der Rechnungen, Bildschirmfotos vom Automaten mit der Zurückweisung. Ich bat um die Begleitung meiner Unkosten. Eine simple EMail reicht Air Namibia nicht, ich musste das ganze in einen Brief verpacken.

Ein paar Tage später kommt die Antwort, ich hätte Rail & Fly nicht mitgebucht. (Das hätte man auch direkt in der EMail sagen können…) Aber ich hatte doch die IDs bekommen?! Ich rief an und es stellte sich heraus, das ich tatsächlich nicht das Zugticket gekauft habe — mein Fehler. Und es stimmt, denn eine Checkbox zum Dazubuchen gibt es Air Nambia nicht. Stattdessen – und vielleicht ist es einigen Lesern schon aufgefallen – ist eben nicht der Flughafen auszuwählen, sondern ein “magischer” “Ort bei “From:”.

FromAuswahl2

Auf diese Idee bin ich nie gekommen! Also kostete mich dieser Fehler 160 €. Ist Air Nambia an dieser miesen Webseite Schuld? Im Prinzip nicht, denn das habe ich mir selbst zuzuschreiben, dass ich gewisse Annahmen über grafische Oberflächen und Buchungen als Standard voraussetzte.

Kann Air Nambia ihr Produkt verbessern? Aber klar! An vier Dingen könnte Air Nambia in meinen Augen arbeiten:

  • Auf der “Hilfe”-Seite sollte klar vermerkt werden, dass man diesen “magischen” ersten Punkt für das inkludierte Zugticket auswählen muss. Die Hilfe kannte ich, und hätte ich den Hinweis dort gelesen, wäre mir der Fehler nicht unterlaufen.
  • Diesen “magischen” Punkt absetzen und durch eine Checkbox im Buchungsverlauf ersetzen. Das würde es Kunden auch ermöglichen von London abzufliegen und nach Frankfurt zurückzukommen und dann ein Zugticket zu haben. Aber vielleicht ist diese Gabelung sowieso nicht vorgesehen …
  • Mir auch nach mehrfacher Nachfrage immer wieder die falschen IDs zu geben, anstatt klar zu formulieren, ich hätte Rail & Fly nicht gebucht. Auch: Die EMail-Kommunikation verbessern und mich nicht im Glauben lassen “rail ticket has been booked accordingly“.
  • Kunden die Option anzubieten, Rail & Fly einfach später dazuzubuchen. Das geht aber nur indirekt, in dem man den “Flug” umbucht. Die Umbuchungsbebühr betragen 165 € — die könnte Air Nambia reduzieren, da man bei dieser “Umbuchung” überhaupt nichts am Flug ändern muss. Später beim Telefonat kam es zu der Aussage, das ich mit dem eigenen Zugtickets ja noch günstiger gekommen bin. Ja super.

Schlussendlich hat Air Namibia nach meinen Telefonat noch einmal reagiert:

Wir haben Ihren Fall noch einmal intern geprüft und müssen leider mitteilen, dass sich aufgrund der Online-Buchung, die über das Air Namibia IT-Buchungssystem in Windhoek verarbeitet wurde, eine exakte Konstruktion des Buchungsvorgangs nicht mehr möglich ist. Da ein Fehler von Seiten der Air Namibia trotzdem nicht ausgeschlossen werden kann, wird Ihnen Air Namibia aus Kulanz die zusätzlich gekauften Bahntickets erstatten, denn laut Buchung ist R&F mit den zugehörigen Nummern, die Ihnen telefonisch mitgeteilt wurden, zwar hinterlegt, wurde aber eben nicht bestätigt und ausgestellt.

Dafür musste ich “nur” eine Einverständniserklärung abgeben:

Ich, C. U., erkläre mit meiner Unterschrift keine weiteren Regressansprüche gegenüber der Airline Air Namibia, deren Vertragspartnern und Handlingsagenten sowie weiteren Fluggesellschaften geltend zu machen. Mit dem Beitrag […] verzichte ich auf jegliche Schadensersatzansprüche gleich welcher Art.

Nach dem das ein paar Tage nach Valentinstag zu Air Namibia ging, erstattete mir die Airline über die AVIAREPS AG das Geld am 24.02 zurück. Schön. Ende gut.

Thema der Woche: Besondere Methoden der Renderer

Der “Bug” http://bugs.sun.com/view_bug.do?bug_id=4706356 führte zu einer Änderung, die http://docs.oracle.com/javase/7/docs/technotes/guides/swing/1.5/index.html so beschreibt:

Swing’s cell rendenders override a handful of methods to do nothing as they are not needed for cell renderers. They should override a couple of methods that are now being called to do nothing.

The following methods were added to DefaultTableCellRenderer, DefaultListCellRenderer and DefaultTreeCellRenderer

    /**
     * Overridden for performance reasons.
     * See the <a href="#override">Implementation Note</a>
     * for more information.
     *
     * @since 1.5
     */
    public void invalidate();
    /**
     * Overridden for performance reasons.
     * See the <a href="#override">Implementation Note</a>
     * for more information.
     *
     * @since 1.5
     */
    public void repaint();

Erkläre die Arbeitsweise und warum die Methoden überschrieben wurden. (Ist das Listing oben überhaupt korrekt?) Wie sieht das bei Komponenten bei SwingX aus?

Offtopic: Schöll AG und die Kopie der Seminarbeschreibungen, Teil 2

Nachdem ich 2009 im Beitrag http://www.tutego.de/blog/javainsel/2009/05/offtopic-content-klau-der-scholl-ag/ von dem “Entlehnen” meiner Semianarbeschreibungen berichtet habe, ist mir ganz entgangen, von dem Ausgang zu berichten.

Genau einen Tag vor dem Ablauf meiner gesetzten Zweiwochenfrist kommt ein Fax vom einer Anwalts-Sozietät in Darmstadt. (Über die Qualität der Web-Seite und der Rechtschreibung (“Angiffen”, “Umstrukturierunvon”) kann man streiten. Und “in englisch und französisch” schreibt man eigentlich “in Englisch und Französisch”, da als Substantive gebrauchte Adjektive und Partizipien großgeschrieben werden.)

Anstatt das ein Verantwortlicher der Schöll AG sagt; “Sory, dummer Fehler, kommt nicht wieder vor” gibt es kein Schuldeingeständnis. Schlimmer ist die Erklärung, mit der sich Schöll rauswinden will. Der Rechtsanwalt schreibt: “Unser Mandantin war aufgrund der zuvor geführten Gespräche zudem der Auffassung, Sie seien mit den Inhalten einverstanden. Wir werten Ihre E-Mail insoweit als Kündigung einer bestehenden Nutzungsberechtigung […]”. Ohne Frage gab es keine “zuvor geführten Gespräche” und von einer “bestehenden Nutzungsberechtigung” auszugehen ist falsch.

Daher habe ich nach dem Faxempfang am Freitag (29.05.2009) eine E-Mail an Schöll gesendet mit den Fragen

  1. wie viele Gespräche wir geführt haben,
  2. mit wem ich welches Gespräch geführt habe,
  3. zu welchem Zeitpunkt die Gespräche stattfanden und
  4. welchen Inhalt die Gespräche hatten.

Auf eine Antwort warte ich bis heute.

Rechtsanwalt Dr. Becker vertritt die Meinung, dass mein Inhaltsverzeichnis nicht “die für einen Urheberrechtsschutz erforderliche Schöpfungshöhe erreicht”. Die gängigen Urteile beziehen sich jedoch auf Inhaltsverzeichnisse von Büchern, nicht aber auf die Inhalte von Seminarbeschreibungen. Die Frage der Schöpfungshöhe und damit die des Urheberrechts müsste ein Gericht erst klären. Gibt es mangelnde Schöpfungshöhe, also das, was Dr. Becker hier durchscheinen lässt, gilt die Gemeinfreiheit. Das heißt, es gilt kein Urheberrecht und jeder könnte von jedem den Seminarinhalte übernehmen. Darüber wäre Schöll sicherlich auch nicht glücklich, wenn ich deren Seminareinhalte auf meine Webseite setze. Und das Problem der unerlaubten Leistungsübernahme ist hier noch nicht einmal angesprochen.

In der Summe halte ich die Öffentlichkeitsarbeit der Schöll AG für ein Desaster. Es zeigt sich immer, wie wenig Eier Unternehmen in der Hose habe um kurz und knapp “Sorry” zu sagen. Stattdessen ignorieren Unternehmen wie die Schöll AG Anfragen und schicken feige einen Anwalt vor. Naja, seit 3 Jahre ist die Sache abgeschlossen und Schöll hat fix eigene Seminarbeschreibungen aufgebaut. Die sind auch immer noch auf dem Stand von 2009 …

Es ist niemals schwieriger, das rechte Wort zu finden, als wenn man sich schämt.
– François de La Rochefoucauld (1613 – 1680)

Google Guava: Delete all files in a directory (now deprecated)

The java.io.File class can delete a file but not a collection of files or a whole directory including its containing files. com.google.common.io.Files declares two methods to do this job:

  • static void deleteDirectoryContents(File directory)
    Delete all the files within a directory but not the directory itself. If the contents of this or any subdirectory can’t be listed an IOException("Error listing files for " + directory) will be thrown.
  • static void deleteRecursively(File file) throws IOException
    Delete a file or directory and all contents recursively. This methods calls deleteDirectoryContents() first and then file.delete(). If this directory can’t be deleted an IOException("Failed to delete " + file) will be thrown.

Because a file can be a symbolic link it is important to understand the semantics of these methods. If a containing file or directory is a symbolic link will the symbolic link itself be deleted or will the method follow the link and delete the target? None of the methods follow symbolic links because it’s simply not possible with the JDK. If these methods find a symbolic link then just the link will be deleted. But what if the methods are called on a directory which is itself a symbolic link?

If deleteDirectoryContents() is called on a File object which is a symbolic link to a directory nothing will happen at all because as already mentioned symbolic links are not followed; so deleteDirectoryContents() will not delete the directory the method was called on. If on the other site deleteRecursively() is called on a symbolic link then just the symbolic link to this directory is deleted but not the target directory itself. That’s just how symbolic links works in Java and has nothing to do with the actual deleteXXX()-methods.

 

Alternative: Use NIO.2 from Java 7 or copy the old source code to your project.

Adventszeit, Zeit zum Nachdenken über Scala …

… und das macht Stephen Colebourne in einem Blog in einem kritischen Beitrag http://blog.joda.org/2011/11/scala-feels-like-ejb-2-and-other.html. Das produziert eine Menge an Antworten, durchaus lesenswert, auch die folgenden Blog-Einträge http://blog.joda.org/2011/11/scala-ejb-2-feedback.html und http://blog.joda.org/2011/11/real-life-scala-feedback-from-yammer.html. Und obwohl ich Programmiersprachen immer ganz reizend finde, macht mich Scala auch nicht so scharf, und ich war nie motiviert sie die lernen.