Kein kommerzieller Support mehr für Glassfish

Oracle stellt den kommerziellen Support für Glassfish ein und empfiehlt Kunden, die an solchem Support interessiert sind, auf WebLogic umzustellen:

Oracle stellt kommerziellen Support für GlassFish ein.

Die Frage ist natürlich, ob man dann nicht ein paar andere Umstellungen überdenkt:

  • Wenn es EJB sein muss, ist vielleicht auch der WildFly-Applikationsserver von JBoss eine Option
  • Wenn es Java sein muss, ist vielleicht auch Spring eine Alternative
  • Wenn es die JVM sein muss, sind Scala, Clojure oder JRuby einige weitere Möglichkeiten. Diese bringen in der Regel ihre eigenen Frameworks mit. Wer möchte noch EJB benutzen, wenn er schon bei JRuby, Scala oder Clojure angelangt ist? Ja, theoretisch ginge das wohl, EJBs in diesen Sprachen zu entwickeln.
  • Wenn nicht es nicht einmal die JVM sein muss, gibt es viele Möglichkeiten, die ich der Phantasie des Lesers überlasse.

Kurz gesagt, ich will hier nicht den Ruhm von EJB schmälern. Das tue ich vielleicht einmal in anderen Blog-Beiträgen. Aber niemand muss von Glassfish auf WebLogic umstellen. Und schon gar nicht muss man sich bei dem prall gefüllten Satz an Alternativen von Oracle bei den Verhandlungen über den Tisch ziehen lassen.

Nur benötigen diese Umstellungen immer viel Zeit und Geld und sie müssen gut geplant werden. Deshalb ist es sicher gut, längerfristig die Alternativen vorzubereiten und nicht erst wenn es schon zu spät ist. Sonst geht mit einem virtuellen Schild um den Hals in die Verhandlungen mit Oracle, auf dem steht, dass man gerne über den Tisch gezogen werden möchte.

Es sei dem Leser überlassen, seine Schlussfolgerungen für andere technisch interessante Softwareprodukte aus demselben Haus zu ziehen, z.B. mySQL oder Solaris. Und ja, man könnte theoretisch für diese Produkte ähnliche Listen anfertigen.

Share Button

Multidispatch (Multimethoden): verpassen wir etwas

Objektorientierte Programmiersprachen werden nach meiner Meinung eigentlich erst wirklich objektorientiert, wenn sie Polymorphie unterstützen. Das bedeutet, dass ein Stück Progammcode mit einem Objekt gewisse Manipulationen durchführt und dabei Methoden des Objekts aufruft. Diese tun etwas verschiedenes, je nach dem welches Objekt hier angesprochen wird, denn es ist eine Eigenschaft des Objekts, welche Methode wirklich aufgerufen wird. In vielen Objektorientierten Programmiersprachen, wie zum Beispiel Java oder C# oder C++ ist das so gelöst, dass das Objekt einer Klasse angehört und die Klasse die Methodenimplementierung enthält, aber es können natürlich auch Methoden direkt an einzelnen Objekten aufgehängt sein. Für die Freunde von C# und C++ sei daran erinnert, dass „virtual“ hier nicht fehlen darf.

Das ist alles wunderbar und man kann damit sehr viel anfangen. Nun wird die heile Welt gestört, wenn man sich irgendwelche Konzepte aus nie wirklich Mainstream gewordenen Programmiersprachen wie Common Lisp mit CLOS anschaut, wo es sogenanntes Multidispatch gibt. Die aufgerufene Methode hängt also nicht nur vom ersten speziellen Parameter, also dem Objekt, das oft vor dem „.“ steht, ab, sondern von allen Parametern. Das macht es unübersichtlich und niemand braucht so etwas, könnte man meinen. Das mag ja alles stimmen, aber wir werden doch mit Situationen konfrontiert, wo das Thema sehr relevant wird.

Nehmen wir an, man führt einen neuen numerischen Typ ein, z.B. Rational für rationale Zahlen \Bbb Q=\{ \frac{a}{b} : a, b \in \Bbb Z \wedge b > 0 \}. Nun braucht man Methoden für die Grundrechenarten, was sehr schön funktioniert, wenn man z.B. zwei rationale Zahlen addieren will. Nun soll es aber auch funktionieren, eine ganze Zahl zu einer rationalen Zahl zu addieren. Dafür kann man die „+“-Methode oder weniger schön die „add“-Methode noch einmal mehr überladen und einen ganzzahligen Parameter verstehen oder innerhalb der Methode diesen Fall zur Laufzeit erkennen. Der erste Ansatz greift leider zu kurz, weil wegen Vererbungshierarchie und gerade wegen der Polymorphie der genaue Type zur Compilezeit nicht bekannt ist und daher auf die allgemeine Methode, etwa so etwas wie

+(x : Numeric) ,

zurückgefallen wird, die wiederum abhängig vom realen Typ von x auf die richtige Methode oder den richtigen Methodenteil führen sollte.
Das ist alles noch gut machbar, man darf es nur nicht vergessen.

Aber was passiert nun, wenn q rational und n ganzzahlig ist und wir nicht q+n, sondern n+q schreiben? Nun müsste man Integer (oder BigInteger) oder was auch immer der Typ ist, hoffentlich ohne diesen absurden Überlauf bei 2^{31}-1 wie die java-ints, nachträglich beibrigen, rational zu verstehen. In Ruby kann man zumindest noch nachträglich die Methode + von Integer ändern und durch eine eigene ersetzen, die auch Rational versteht, aber der Ansatz stößt irgendwann an Grenzen. In Ruby behilft man sich oft damit, dass die +-Methode der linken Seite eine „coerce“-Methode der rechten Seite mit der linken Seite als Parameter aufruft, um Konvertierungen zu machen. Damit kommt man recht weit, aber man muss sehr genau hinschauen, was man tut.

Nun kommt sicher der Einwand, dass Operatorüberladen sowieso „böse“ ist. Das hilft aber hier nichts, die Probleme treten in identischer Form auf, wenn man es „add“ statt „+“ nennt.

Der zweite Einwand ist vielleicht, dass man nicht jeden Tag neue numerische Typen schreibt. Aber man schreibt doch hoffentlich ab und zu neue Klassen und nutzt Vererbung. Da muss man dann eine equals-Methode oder so etwas ähnliches implementieren. Und schon ist das Problem sehr relevant. In der Regel habe ich das dadurch gelöst, dass equals zuerst die Klassen von linker Seite (self oder this) und rechter Seite vergleicht und nur wenn die gleich sind, überhaupt weiter vergleicht. Das ist meistens ein guter Ansatz. Aber manchmal muss man wirklich Gleichheit zwischen Objekten zulassen, die nicht derselben Klasse angehören. Dann ist es schon eine Herausforderung, das korrekt und halbwegs solide zu lösen. Man sieht also, dass wir hier wirklich etwas verpassen… Aber solange man die Konzepte kennt, kann man sie grundsätzlich in jeder Programmiersprache anwenden, der Aufwand ist nur etwas größer.

Java ist hier tatsächlich etwas schlechter gestellt als z.B. Scala oder Ruby, weil man sehr schlechte Möglichkeiten hat, die eingebaute equals-Methode zu ersetzen. Während es bei SortedSet die Wahlmöglichkeit gibt, Comparable oder einen Comparator zu verwenden, setzen HashSet und HashMap fast immer auf die interne hashCode() und equals()-Methode und man muss sich mit Wrappern oder geeigneten inneren Klassen behelfen, um eine zweites Interface für dasselbe Objekt mit anderen equals()- und hashCode()-Methoden zu liefern.

Share Button

Scala Exchange 2013

Deutsch

I have visited the conference ScalaX 2013 in London on the beginning of December.

It was really fun. The talks were quite challenging, maybe even a little bit more than on other conferences I have visited, but that was really fun to listen to. About 400 participants were there and three tracks were available. So it was possible to learn a lot about advanced concepts in functional programming and software architecture with a focus on Scala, but also some Haskell and Clojure.

Some interesting talks were:

Share Button

Besuch bei Scala Exchange 2013

English

Gleich ein paar Wochen nach der Devoxx habe ich noch so eine Konferenz besucht, diesmal nur zwei Tage und unter dem Namen „Scala Exchange“ oder kurz #scalaX.
Es ging hauptsächlich um funktionale Programmierung und Architektur und das wiederum meistens recht „Scala-lastig“.
Die Vorträge waren um einiges anspruchsvoller als bei der Devoxx, aber das machte vielleicht auch den speziellen Reiz aus.

Interessante Vorträge waren unter anderem:

Share Button

Devoxx 2013 Part 2

During the time from 2013-11-13 to 2013-11-15 I have been attending the Devoxx-conference in Antwerp in Belgium.
Most of the speeches I have been listening too were just great, like for example:

Share Button

Devoxx 2013 Teil 2

In der Zeit vom 13. bis zum 15. November habe ich die Devoxx-Konferenz in Antwerpen besucht.
Die meisten Vorträge waren wieder sehr gut, z.B.:

Hier ist noch ein guter Blogbeitrag zur Devoxx 2013.

Share Button

UTF-16 bei Zeichenketten in Java

English

Zeichenketten in Java und in vielen JVM-Sprachen enthalten Unicode-Zeichen und sind mit utf-16 codiert. Es war sehr weitsichtig, schon in den 90er-Jahren an Unicode zu denken und das als alleinige Möglichkeit vorzusehen. Man hat sich so erspart, das Durcheinander zu haben, welche Zeichenkette jetzt in welcher Codierung vorliegt, weil alle gleich sind, und auch zumindest für gängige europäische und westasiatische Sprachen die Handhabung vereinfacht, weil da ein Zeichen zwei Bytes sind. Der Nachteil mit dem etwas größeren Speicherverbrauch spielt fast keine Rolle, weil man mit ein paar Zeichenketten sehr selten an die Grenzen stößt. Mit 64-Bit-CPUs (und 64-Bit-JVM) kann man ja fast beliebig viel Hauptspeicher einsetzen.

Aber es gibt auch Applikationen, die trotzdem mit ihrem Speicherverbrauch an Grenzen stoßen. So könnte man auf die Idee kommen, eigene Zeichenketten zu verwenden, die utf-8 statt utf-16 verwenden. Die entsprechende Konvertierung ist nicht schwierig und sicher im Netz zu finden, sogar in der eigenen Java-Libary. Leider sind die Zeichenketten aber an so vielen Stellen vorgesehen und man kann sie nicht einfach durch eine andere Klasse ersetzen. Was bleibt sind also lästige explizite Konvertierungen. Aber allein mit diesem Ansatz kann man natürlich eine Menge Speicher sparen.

Eine andere Idee wäre es, Zeichenketten zu komprimieren. Wenn sie lang genug sind, funktionieren Algorithmen wie gzip auf einer einzelnen Zeichenkette. Das erschwert natürlich den selektiven Zugriff auf einzelne Teile der Zeichenkette, aber das Problem hat man schon mit utf-8, wo man nicht genau weiß, ab welchem Byte nun das n-te Zeichen beginnt, ohne sie von Anfang an durchzugehen. Aber wir müssen auch damit rechnen, dass es nicht einzelne lange Zeichenketten gibt, sondern sehr viele, die jeweils zu kurz sind, um für sich genommen mit einer Kompression kleiner zu werden. Wenn man nun aber die Gesamtheit der Zeichenketten ungefähr kennt, kann man eine Komprimierung generieren, die für diesen Satz von Zeichenketten gute Ergebnisse bringt. Das bedeutet, dass man ähnlich wie bei der Umstellung von utf-16 auf utf-8 einzelne Byte-Sequenzen der unkomprimierten Zeichenkette durch anderen Byte-Sequenzen für die komprimierte Zeichenkette ersetzt. Die häufig vorkommenden Sequenzen werden durch kürzere ersetzt, die selteneren durch längere. So kann man mit weniger Bytes auskommen. Die Regel, wie das Komprimieren und Dekomprimieren funktioniert, muss man nur einmal für das ganze Programm speichern und nicht wie bei der ersten Idee für den Einsatz von gzip in jeder Zeichenkette einzeln.

Es empfiehlt sich unbedingt, die folgenden Punkte zu beachten:

  1. Sind wirklich die Zeichenketten ein Problem mit ihrem Speicherverbrauch?
  2. Lässt sich dieses durch andere, einfachere Optimierungen der Software lösen?
  3. Lasst es sich durch Hardware lösen?
  4. Gibt es schon geeignete oder adaptierbare Lösungen im Netz? Oder in der eigenen Organisation?
  5. Eine neue String-Klasse ist so grundlegend, dass man sie unbedingt gut testen muss. Unit-Tests sollten wirklich ausführlich sein.
Share Button

Devoxx 2013 Teil 1

Ich besuche in dieser Woche die Devoxx-Konferenz in Antwerpen. Es gibt wieder viele interessante und auch unterhaltsame Vorträge über Software-Architektur, Entwicklungsprozesse, Security, Team-Organisation und neue Technologien. Dart 1.0 als möglicher Ersatz für Javascript ist zum Beispiel vorgestellt worden. Es ist immer gut, wenn man noch etwas dazu lernen kann, denn Leute, die schon alles wissen, bremsen früher oder später ihre Teams oder ihre Projekte aus, weil alles Neue abgelehnt wird…

Ich hoffe, dass ich nächstes Jahr wieder dort sein kann.

Mehr Details dazu kommen später.

Voriges Jahr war ich auch dort.

Share Button

Devoxx 2013 part 1

2013 I am visiting Devoxx in Antwerp again. It is quite interesting, because they have invited good speakers who know their stuff and are fun to listen to.

So I am learning a lot about software architecture, software development, team organization, security and new technologies. It is always good not to know everything and to be able to learn new stuff, because people who know everything already usually slow down their projects sooner or later. So I hope to be there again next year. 😉

I will write more in another post …

Btw. last year was great as well. 😉

Share Button

Scala, Ruby, Perl,… – wann nimmt man was?

Wer einen goldenen Hammer hat, für den sieht jede Schraube wie in Nagel aus. Aber wir haben einen riesigen Werkzeugkasten und wie man sieht, überschneiden sich tatsächlich manche Werkzeuge in ihren Einsatzbereichen, aber das Universalwerkzeug ist nicht wirklich in Sicht oder doch nicht wirklich in allen Bereichen mit den Spezialwerkzeugen konkurrenzfähig.

Oft hat man ja Altlasten, also vorhandene Applikationen, die man erweitern oder ergänzen soll oder es sollen sogar neue, „in die Landschaft passende“ Applikationen hinzugefügt werden. Dann landet man bei Cobol, Railo, Fortran, C, Java, C#, C++, PL/SQL, PL/1, (Visual)Basic u.s.w. Wobei diese zum Teil sogar ihre sehr große „Nische“ haben, in der sie noch aktuell sind. Dass C für Systemprogrammierung noch sehr aktuell und fast konkurrenzlos ist, sei unbenommen.

Wenn keine Vorgaben durch Bibliotheken, Altlasten, IT-Landschaft u.s.w. bestehen, ist es natürlich interessant, in der zur Verfügung stehenden Zeit möglichst viel machen zu können. Eine Technologie, die einen zwingt, viel Zeit mit trivialen Aufgaben zu verbringen und die eigentlich interessanten Dinge in einem Wust von trivialem Code zu verstecken, den man nun einmal schreiben muss, darf man dann auch schon einmal hinterfragen. Letztlich sind zwei Wege vielversprechend, um mit wenig Code viel auszudrücken und letzlich in wenig Zeit viel zu entwickeln: Die funktionalen Sprachen wie z.B. F#, Clojure, Erlang, Elixir und Haskell. Oder die Skriptsprachen wie Ruby, Perl, Perl6 (wenn es mal fertig wird), Python und PHP. Natürlich überschneidet sich das ein Stück weit, weil einige funktionale Sprachen auch ein bißchen wie Skriptsprachen einsetzbar sind und einige Skriptsprachen auch gewisse funktionale Konstruktionen unterstützen.

Letztlich erweisen sich die funktionalen Sprachen als vielversprechend, wenn es darum geht, sehr leistungsstarke Applikationen zu entwickeln, die einen hohen Durchsatz und eine hohe Parallelisierung der Verarbeitung verwirklichen. Twitter soll mit Scala diesen Weg gegangen sein. Grundsätzlich bieten alle ernsthaften funktionalen Sprachen hier einige Möglichkeiten. F# lässt sich übrigens auch mit Mono kombiniert unter Linux verwenden. Vielleicht hat Erlang noch einen kleinen Vorteil, weil es schon auf VM-Ebene für diesen Einsatzbereich optimiert ist. Diese VM lässt sich aber auch mit Elixir verwenden. Aber man hat die Wahl zwischen mehreren Wegen.

Für viele Web-Applikationen hat sich Ruby als gut geeignet erwiesen, man sieht aber, dass es einige sehr gute PHP-Applikationen gibt. z.B. MediaWiki, die Software, mit der Wikipedia läuft. Allerdings zeichnet sich im Moment ein Trend ab, mehr von der Logik in Javascript auf der Client-Seite zu implementieren und serverseitig (fast) nur noch Webservices mit REST anzubieten, die die eigentliche Businesslogik und die Zugriffe auf die Daten zur Verfügung stellen. Diese REST-Services kann man natürlich in Ruby entwickeln; aber da gibt es viele Wege…

Ruby und vor allem Perl sind aber auch sehr stark, wenn es darum geht, Textdateien zu verarbeiten. Man kann diese nach Mustern durchsuchen, umgruppieren und umbauen und damit schöne Auswertungen machen. Für sehr große Datenmengen sollte man sich natürlich noch etwas eingehendere Gedanken machen, weil dann der Durchsatz und die Parallelisierung plötzlich mehr Bedeutung bekommen als das eigentlich Parsen des Texts. Aber man kann noch viel mehr…

Eine große Applikation kann diese Dinge auch kombinieren. GNU-Emacs ist eine sehr altes Beispiel, dass hier einen noch heute sehr aktuellen Ansatz verfolgt. Die Grundfunktionalität ist in C entwickelt und die weitergehenden Funktionen und Erweiterungen alle in Emacs-Lisp. So läßt sich ohne viel Aufwand einen Erweiterung einbinden, was nicht so leicht geht, wenn man erst einmal neu kompliieren muss. Die Idee lässt sich auch heute noch aufgreifen, wenn man eine Applikation z.B. in Scala entwickelt und dann die Möglichkeit anbietet, diese über Ruby- oder Groovy-Scripte anzusprechen, zu erweitern und zu konfigurieren.

Wenn man einmal an Häuser denkt, ist die Idee nicht so abwegig. Das eigentliche Haus ist relativ stabil aus Beton, Stein und Holz gebaut und bleibt in der Regel jahrzehntelang unverändert. Die Möbel sind selten aus Beton gegossen und eher flexibler (auch wenn sie vielerorts jahrzehntelang gleich stehen).

Share Button