Ausweg aus dem GUI-Dilemma

SWTSwing und Eclipse on Swing

Dieter Krachtus und Christopher Deckers

Kein Graben in der Welt von Java ist tiefer als der zwischen SWT und Swing oder Eclipse und Sun. Einigkeit herrscht nur im Wissen, dass dieser Zwist wirklich allen schadet. Doch wie beendet man diesen mitunter religiös geführten Streit über die Wahl des rechtmäßigen GUI-Toolkits? Wie soll man fanatische Streithähne vereinen, die nur zwei Sichtweisen kennen: für sie oder gegen sie! Die beiden Projekte SWTSwing und Eclipse on Swing (EoS) versuchen genau diesen Kunstgriff und wollen den beiden verfeindeten Lagern eine versöhnende Alternative (Hubert Schleichert: Wie man mit Fundamentalisten diskutiert, ohne den Verstand zu verlieren. Anleitung zum subversiven Denken, C.H. Beck, 1997) offerieren.

Die einzig schlechte Wahl ist die Wahllosigkeit. Es scheint also eher ein Segen, mit SWT und Swing eben diese Wahl zu haben? Zeit und Muße, beide Toolkits ausgiebig zu erlernen, fehlen jedoch meist und somit ist es nicht verwunderlich, dass die Wahl des Toolkits sich nicht am aktuell zu lösenden Problem, sondern am Gusto des Entwicklers orientiert. Faktisch besteht also Wahllosigkeit.

Wäre es nicht schön, man hätte die Wahl zwischen SWT und Swing, und zwar nicht nur zu Beginn eines Projekts sondern zu jedem Zeitpunkt während der Entwicklung? Mit bekannten APIs Eclipse-Plugins, RCP-Applikationen oder ein JFace/SWT-GUI entwickeln und dann ohne Code-Änderungen im Handumdrehen zwischen SWT und Swing hin und her wechseln?

SWTSwing hat sich genau dieses Ziel zur Pflicht gesetzt. Die Kür erhält man mit Eclipse on Swing (EoS), dass den Versuch antritt, dieses Kunststück für eine der komplexesten SWT-Applikationen, nämlich Eclipse selbst, zu ermöglichen.

SWTSwing

Spätestens im März 2003, mit der Veröffentlichung des Eclipse Java SDK 2.1 erhielt das UI-Toolkit SWT viel Aufmerksamkeit. Es hatte einen Grad der Reife erreicht, der immer mehr Entwickler davon überzeugte SWT direkt in eigenständigen Anwendungen zu nutzen.

Im August 2005 wurde die Implementierung des SWTSwing-Projekts begonnen, jedoch dauerte es fast ein Jahr bis zum ersten offiziellen Release. Als Entwickler-Tests und um den Fortschritt des Projekts zu dokumentieren dienen die SWT-Snippets. Wie der Name andeutet, handelt es sich um Code-Schnipsel, minimale Beispiele also, die man SWT-Anfängern ans Herz legt, um die Funktionsweise der SWT-Widgets zu erlernen. SWTSwing kann den Großteil dieser Snippets fehlerfrei ausführen, wobei keine nativen SWT-Widgets, sondern Swing-Widgets Verwendung finden.

Schnell wurde leider klar, dass komplexere Applikationen und deren GUIs nicht nur mehr sind als die Summe ihrer Einzelteile, sondern ironischerweise auch mehr Bugs aufweisen, als ihre Einzelteile (Snippets unter SWTSwing) erhoffen lassen.

Als so genannter Gold-Standard einer extrem komplexen SWT-Applikation sollte direkt Eclipse dienen. Deshalb wurde Eclipse on Swing (EoS – benannt nach der griechischen Göttin Eos initiiert, welches lange Zeit auf einer stark veränderten Codebasis von SWTSwing basierte, um Eclipse mit Swing überhaupt zu einem erfolgreichen Start zu bewegen.

Die Strategie, SWTSwing über sehr simple (Snippets) und gleichzeitig sehr komplexe Tests (EoS) zu verbessern, hatte den Erfolg. Unzulängliche Implementierungen und Probleme wurden durch EoS enttarnt und lieferten direktes Feedback für die Verbesserung von SWTSwing.

Diese Verbesserungen in SWTSwing durch EoS erlauben es mittlerweile, dass auch andere komplexe SWT-Applikationen bald schon produktiv eingesetzt werden können. Im Moment trüben nur noch einige kleinere Bugs den Spaß, die jedoch bereits zum Zeitpunkt der Veröffentlichung dieses Artikels behoben sein dürften. Möchte man einen Eindruck vom momentanen Status von SWTSwing gewinnen, sprechen die aktuellen Screenshots der beliebten SWT-Applikationen Azureus und RSSOwl (Abb. 1, 2) für sich selbst.

Abb. 1: Azureus

Abb. 2: RSSOwl
SWT(Swing) – Details

Wir wollen nun kurz das generelle Design von SWT betrachten, um zu verstehen, wie SWTSwing dessen Implementierung mittels Swing umsetzt. SWT stellt ein Public API zur Verfügung und besitzt über eine dünne native Schicht ein privates Interface zum System (Abb. 3).

Abb. 3: Wie sich SWTSwing einfügt

Die tatsächliche Implementierung von SWT folgt einem generellen Muster. Die grundlegende Idee ist, dass alle nativen Aufrufe in einer einzigen Klasse, nämlich org.eclipse.swt.internal..OS zugänglich sind, welche ein Eins-zu-eins-Mapping auf die entsprechenden C-Funktionen abbilden. Die Funktionen dieses recht dünnen Layers werden direkt von den Klassen des SWT Public API (Listing 1) aufgerufen. Das AWT benutzt ebenfalls einen über JNI (Java Native Interface) realisierten nativen Layer, jedoch enthält dieser eine Menge weiterer Logik und ist somit „fetter“ im Vergleich zu SWT.

Listing 1: Widget-Erzeugung in SWT für Windows
-------------------------------------------------------
class org.eclipse.swt.widgets.Button extends Control {
  public void setText (String string) {
    // ...
    TCHAR buffer = new TCHAR (getCodePage (), text, true);
    OS.SetWindowText (handle, buffer);
    // ...
  }
}

class org.eclipse.swt.widgets.Control {
  void createHandle () {
    // ...
    // Erzeugung des handle erfolgt durch die Super-Klasse
    handle = OS.CreateWindowEx (...);
    // ...
  }
}

class org.eclipse.swt.internal.win32.OS {
  // Native Methoden
}

Im nächsten Schritt wollen wir anhand eines kleinen Beispiels verdeutlichen, wie SWTSwing es bewerkstelligt, das Swing- anstatt SWT-Widgets verwendet werden. In Listing 1 und Listing 2 wird dazu die Erzeugung eines Buttons mit SWT und SWTSwing gegenübergestellt. Der deutlichste Unterschied bei der SWTSwing-Implementierung in Listing 2 ist das Fehlen der Klasse org.eclipse.swt.internal..OS und somit aller nativen Abhängigkeiten. Wie Listing 2 zeigt, werden stattdessen über das Interface org.eclipse.swt.internal.swing.CButton, abhängig von einem Style-Parameter, Instanzen der Klassen CButtonPush, CButtonToggle bzw. CButtonCheck erzeugt. Diese Klassen sind Spezialisierungen der Swing-Klassen JButton, JToggleButton bzw. JCheckBox.

Für alle SWT-Widgets gibt es also ein Interface ähnlich CButton und Klassen wie CButtonPush, die dieses Interface implementieren und sich gleichzeitig von einer Swing-Widget-Klasse ableiten.

Listing 2: Widget-Erzeugung in SWTSwing
------------------------------------------------
class org.eclipse.swt.widgets.Button extends Control {
  Container createHandle () {
    // Erzeugung des handle erfolgt innerhalb des Widgets
    return (Container)CButton.Instanciator.createInstance(this, style);
  }
  public void setText (String string) {
    // ...
    ((CButton)handle).setText(string);
    // ...
  }
}

interface org.eclipse.swt.internal.swing.CButton {
  public static class Instanciator {
    public static CButton createInstance(Button button, int style) {
      if((style & SWT.PUSH) != 0) {
        return new CButtonPush(button, style);
      }
      if((style & (SWT.CHECK)) != 0) {
        return new CButtonCheck(button, style);
      }
      if((style & (SWT.TOGGLE)) != 0) {
        return new CButtonToggle(button, style);
      }
      // ...
    }
  }
  public void setText(String text);
}

class CButtonPush extends JButton implements CButton {...}
class CButtonToggle extends JToggleButton implements CButton {...}
class CButtonCheck extends JCheckBox implements CButton {...}

Ein konzeptioneller Unterschied zwischen SWT und Swing und gleichzeitig die Hauptkomplikation bei der Implementierung von SWTSwing soll hier erwähnt werden. Gemeint ist der unterschiedliche Event-Pump-Mechanismus. In SWT muss man diesen explizit managen, wohingegen Swing den Mechanismus automatisch intern verwaltet. Um diese Diskrepanz zu lösen, definiert SWTSwing zwei unterschiedliche Funktions-Modi: real-dispatching und best-effort dispatching.

Der real-dispatching-Modus erzeugt das erwartete SWT-Verhalten, bei dem der SWT UI Thread identisch mit dem OS Thread ist. Im Fall von Swing bedeutet dies, dass der automatisch verwaltete UI Thread von SWT kontrolliert wird. Um diesen Modus zu nutzen, muss man die Applikation oder den UI Thread auf eine bestimmte Art und Weise starten. Obwohl also nicht standardmäßig aktiv, wird dieser Modus dennoch empfohlen, um die Performance zu erhöhen und strikte Kompatibilität zum SWT-Design zu wahren.

Der „best-effort dispatching“-Modus ist standardmäßig aktiv und kontrolliert den Swing UI Thread nicht. Dieser Modus besitzt zwei UI Threads, den SWT- und den Swing UI Thread, die beide als valide Threads für SWT-Aufrufe angesehen werden. Es wird hierbei angenommen, dass der Hauptteil des Codes der vom SWT Thread ausgeführt wird Initialisierungen sind, die ablaufen, bevor ein Swing-Fenster überhaupt sichtbar wird, und dass der Rest der Arbeit als Antwort auf Swing-Events ausgeführt wird. Unter dieser Annahme, kann SWT direkt mit Swing interagieren, ohne dem Risiko eines Events ausgesetzt zu sein, das von Swing ausgeht.

Vorteile

Ein offensichtlicher Vorteil einer Implementierung von SWT mit Swing ist Portabilität. Separate native Bibliotheken sind nun nicht mehr nötig, was von einigen Nutzern als sehr wichtig angesehen wird. Weiterhin steigt auch die Anzahl der unterstützen Plattformen: Diese ist nicht identisch für SWT und Swing.

Die Look & Feel-Unterstützung von Swing könnte ebenfalls eine große Rolle spielen. Mit SWT ist man auf das native Verhalten der Zielplattform beschränkt, was in einigen Fällen nicht das ist, aber Entwickler und Arbeitgeber wollen. In diesem Zusammenhang sei nur der Begriff des Company Branding erwähnt.

Ein weiterer wichtiger Punkt kann für einige Anwendungen ein einfacheres und schlankeres Deployment sein. Eine eigenständige Applikation könnte sowohl als native SWT-Applikation samt plattformspezifischem Installer als auch gleichzeitig ohne Codeänderungen als schlankere plattformunabhängige Applikation via WebStart ausgeliefert werden.

Dies sind nur einige wenige Beispiele, die zeigen, wie man real existierende Probleme lösen kann, solange man sich die Wahl vorbehält, gleichzeitig sowohl SWT als auch Swing ohne Mehraufwand zu nutzen.

Eclipse on Swing

Eclipse on Swing hatte bei seiner Gründung hauptsächlich drei Gründe. Seine Rolle als sog. Gold-Standard für die Reifung von SWTSwing wurde bereits genannt. Die Trennung der eigenständigen Codebasen von SWTSwing und EoS konnte nach einem langwierigen Prozess der Fehlersuche wieder aufgehoben werden – als Basis von EoS dient also ab sofort das jeweils aktuellste SWTSwing.

Es ist erfreulich zu bemerken, dass alle Views von EoS schon gut benutzbar sind und nur noch wenige Bugs das Gesamtbild bei der produktiven Arbeit trüben. In Abbildung 4 läuft Eclipse mit dem Swing Windows Look & Feel, wodurch kaum visuelle Unterschiede zu SWT erkennbar sind.

Abb. 4: Eclipse on Swing

Positiv ist auch die Möglichkeit, nicht nur Eclipse selbst mit Swing zu betreiben, sondern im Prinzip jede auf der Eclipse Rich Client Platform (RCP) basierende Applikation. Abbildung 5 zeigt diese Möglichkeit des EoS-Plug-in für den JAX 2006 Innovation Award Gewinner Bioclipse.

Die Gründer von EoS und SWTSwing fokussieren im Moment alle Anstrengungen auf eine Verbesserung von SWTSwing. Das EoS-Plug-in selbst wird deswegen absichtlich im Moment nur in einer manuell zu installierenden Form angeboten, bis eine zufrieden stellende Reife von SWTSwing und EoS erreicht ist. Interessierte können das Plug-in hier herunterladen.

Mit dem EoS-Plug-in soll das zweite Ziel von EoS vorangetrieben werden: Dem interessierten Eclipse-Nutzer wird ein nicht invasives Plug-in an die Hand gegeben, das er von Zeit zu Zeit updaten und sich somit vom Stand der Qualität von EoS und SWTSwing überzeugen kann. Es könnte sich hierbei also um einen sprichwörtlichen Brückenbauer in der Java-Community handeln, der zwischen SWT und Swing vermittelt, Einigkeit schafft und Vorurteile abbaut.

In einem Interview mit dem Eclipse Magazin bemerkte Mike Milinkovich, der Executive Director der Eclipse Foundation: „Eine der schönen Sachen bei Eclipse ist, dass wir nicht religiös, sondern sehr pragmatisch sind. Nach dem Motto: Die Leute können ihre technischen Probleme mit dieser Technologie lösen. Es passt, sie arbeitet, sie skaliert. Es klappt gut.“

Mit dem EoS-Plug-in wird es für Eclipse getreu seinem Motto möglich, auch die Technologie von Swing „zu umarmen“ (Abb. 4, 5).

Abb. 5: EoS-Plug-in & Bioclipse (RCP)

Das dritte und auf lange Sicht wichtigste Ziel des EoS-Projekts wird vielleicht nicht sofort ersichtlich, wenn man es mit den Worten – mehr Sicherheit und Flexibilität für die Zukunft von Eclipse – umschreibt. Ähnlich einer Aktie hängt der Erfolg von Eclipse damit zusammen, dass viele an die Zukunft von Eclipse glauben und sich darauf verlassen, dass Eclipse auch noch in zehn Jahren der entscheidende Technologieführer ist.

EoS: Eclipse on Spare(tyre)

Sehr interessant ist demnach die weiterführende Überlegung, welches denn die fragilsten Elemente von Eclipse im Falle einer Weiterentwicklung durch Dritte sind. Erstens gibt es für viele Plug-ins von Eclipse Redundanzen, d.h. freie oder kommerzielle Plug-ins, die etwas Ähnliches tun und notfalls bei einem Totalausfall als Ersatz dienen könnten. Zweitens ist Eclipse praktisch vollständig in Java entwickelt, gut dokumentiert, besitzt Unit-Tests usw. – viele Entwickler sollten also mehr als qualifiziert sein, im Ernstfall die Idee Eclipse weiterzuführen.

Als Einziges von allen Bestandteilen von Eclipse erfüllt ein Element an dessen Basis diese beiden Kriterien nicht. Gemeint ist SWT. Bei einem Worst-case-Szenario gibt es nicht nur keinen unmittelbaren Ersatz für SWT, vielmehr ist auch dessen Weiterentwicklung aufgrund der nativen Abhängigkeiten alles andere als trivial.

Aber auch in Real-case-Szenarien könnte SWTSwing/EoS viele Vorteile bieten: Zum Beispiel wenn es darum geht, SWT auf eine neue Version eines Betriebssystems anzupassen. Swing könnte hier eine bequeme Übergangslösung schaffen, bis die native SWT-Implementierung einen gewissen Reifegrad erreicht hat.

Auch ist es wohl alles andere als gesichert, dass die Entscheidung, einen plattformabhängigen nativen Weg zu gehen, für alle Zeit die beste Wahl für Eclipse ist. Im Moment ist Swing zumindest keine bessere Wahl für Eclipse im Vergleich mit SWT. Als Anwärter auf die GUI-Krone hat sich das in seiner grünen Jugend zu Recht als Prinz Valium gescholtene Swing jedoch mittlerweile sehr zum Besseren gewandelt. Und wer will voraussagen, was eine JRE 10.0 alles an Verbesserungen zu bieten hat?

Fazit

Akzeptierter Usus, nämlich die Technologie zu wählen, die ein gegebenes Problem am elegantesten löst, wird in der Java-GUI-Entwicklung nur scheinbar befolgt. Vielmehr steht die Wahl des GUI-Toolkits meist schon fest, und Argumente, warum dies die pragmatischere Wahl ist, werden dann auch schnell gefunden.

Die Gründer von SWTSwing/EoS und Autoren dieses Artikels halten es eher mit Orwell, der uns daran erinnert, dass man gewöhnlich nicht zwischen Gut und Böse, sondern zwischen zwei Übeln zu wählen hat.

Dies bedeutet zwei Dinge. Erstens, es gibt nicht das ultimativ bessere Toolkit – SWT und Swing haben beide ihre ihnen eigenen Schwächen -, und zweitens, dass man sich ab sofort glücklich schätzen darf, auch noch im Nachhinein das jeweils andere Übel zu wählen.

Dieter Krachtus ist der Gründer von Eclipse on Swing und Co-Developer von SWTSwing. Er arbeitet als Entwickler und Consultant mit dem Schwerpunkt Rich Clients auf Basis von Swing und dem Eclipse RCP. Zurzeit macht er seine Doktorarbeit am Interdisziplinären Zentrum für Wissenschaftliches Rechnen (IWR) in Heidelberg. Kontakt: dkrachtu at ix.urz.uni-heidelberg.de.

Christopher Deckers ist der Gründer von SWTSwing und Co-Developer von EoS. Er lebt in Frankreich und arbeitet als Senior Java Developer. Christopher hatte schon immer Interesse an Rich User Interfaces, Tools und APIs, und leistet einen Beitrag zu mehren Open Source Projekten. Kontakt: chrriis at gmail.com.

Geschrieben von
Dieter Krachtus und Christopher Deckers
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.