GWT Blog-Serie – GWT im Vergleich zu jQuery Mobile und Sencha Touch (3/4)

mgwt

Quelle: https://code.google.com/p/mgwt/

Wer gegenwärtig ein mobile App entwickelt, der sollte sich vor der Konzeption entscheiden, ob er die App nativ oder als Web-App implementieren will. Die Entscheidung hängt oft davon ab auf welchen Plattformen die App zugänglich sein soll.

Soll die App nur auf einer Plattform verfügbar sein, dann ist die beste Lösung fast immer, die App nativ zu Entwickeln. Soll sie auf mehreren Plattformen erscheinen, dann wird der Kostenfaktor meist zum treibenden Argument gegen eine plattformspezifische Entwicklung, auch wenn die Performance von Animationen und Benutzerinteraktionen nicht das Niveau von nativen Apps erreichen.

Kommen die Entscheidungsträger zu diesem Punkt, fällt die Entscheidung oft auf eine Web-App mit jQuery Mobile. Doch es gibt noch andere Frameworks auf dem Markt, welche mobile Optimierung anbieten. So zum Beispiel Sencha Touch oder MGWT.

Als Mobile-Entwickler bei Namics und während des Studiums habe ich meine Erfahrungen mit all den erwähnten Technologien gesammelt. Ich arbeitete an nativen Apps für iOS und Android sowie plattformunabhängigen Apps mit Sencha Touch, jQuery Mobile und GWT.

Im vorherigen Blogpost ging ich auf die Performance-Optimierung von GWT ein. In diesem Teil meiner Blog-Serie will ich diese drei Frameworks vergleichen und vertieft auf die Performance von MGWT eingehen.

(mehr …)

Mobile Crossplattform Entwicklung auf Basis von Phonegap – Ein Erfahrungsbericht

Ameisen sind fleissig, tatkräftig, rastlos und oft unterwegs, haben aber kein Internet.

Ähnlich geht es den Namics-Mitarbeitern auf so manchem Außendiensteinsatz, die trotzdem auf verschiedene Services angewiesen sind, wie der Zugriff auf sämtliche Mitarbeiter Kontaktdaten, der nicht immer online erfolgen kann. Die in die Jahre gekommene, mobile Weblösung sollte mit einem mobilen Telefonbuch abgelöst werden. Da bei Namics jeder sein eigenes Mobile Phone nutzen darf (BYOD-Philosophie) muss die erstellte Lösung auf möglichst vielen Plattformen laufen. Die Devices sind zu ca. 80% auf iOS und Android verteilt und diese Devices sollen primär auch unterstützt werden.
(mehr …)

jQuery Europe 2013, Tag 2

jquery-europe

Am 20 bis 22. Februar fand der europäische Ableger der jQuery Conference statt. Dieser Post besteht aus einer Zusammenfassung von Tag 2 der Konferenz. Die Zusammenfassung von Tag 1 wurde letzte Woche veröffentlicht. jQuery Mobile and Responsive Web Design – … Weiterlesen

jQuery Europe 2013, Tag 1

jqconfeu13

Am 20 bis 22. Februar fand der europäische Ableger der jQuery Conference statt. Als Austragungsort wurde das verschneite Wien gewählt; und mit dem Palais Liechtenstein ein würdiger Veranstaltungsort gefunden (siehe Bilder unten). Rund 400 Besucher trafen sich in Österreich um sich an einem … Weiterlesen

Terrific – a Frontend Development Framework goes Open Source

terrifically.org

Der Frontend Entwicklungsprozess wird durch die rasante Technologie- und Browserentwicklung immer komplexer. Die stetig steigende Vielzahl von Zielgeräten und Auflösungen, Animationen, CSS3, HTML5 etc. tun ihr Bestes, um die Aufwände und die Komplexität schon während der Konzeptionsphase zu erhöhen. Die unendlichen … Weiterlesen

Flexible & erweiterbare jQuery Plugins

jQuery ist ein mächtiges Framework welches das Arbeiten mit JavaScript stark erleichtert. Mittlerweile ist jQuery mit Abstand das verbreitetste JavaScript Framework der Welt. Ganze UI-Elemente wie Tabs, oder Funktionsblöcke wie etwa eine Bildergalerie sucht man jedoch – bei jQuery selber – vergeblich. jQuery stellt lediglich zahlreiche mehr oder minder kleine Helfer zur Verfügung, welche es ermöglichen, solche Dinge mit geringem Aufwand zu erstellen.

Nun ist es natürlich nicht praktisch komplexe Funktionen wieder und wieder – und für jedes Projekt neu – zu schreiben. Hier kommen die „jQuery Plugins“ ins Spiel. Ein jQuery Plugin ist in der Regel eine Erweiterung von jQuery und kann beliebig komplexe Funktionen – von History Handling über UI-Elemente bis zu Lightboxen – bereitstellen.

Aufbau eines Plugins

Die jQuery Plugin API dient dazu, jQuery um neue Funktionen zu erweitern:

// jQuery um Tab Funktion erweitern:
$.fn.tabsPlugin = function(userOptions) {
   // Plugin Code...
}

Plugins sind meist sehr ähnlich aufgebaut. Sie werden in der Regel auf ein Set von HTML Elementen angewendet und man kann das Verhalten des Plugins mit Optionen etwas beeinflussen. In etwa so:

var options = {
     activeTab: 2
};
$('div.tabs').tabsPlugin(options);

Damit würde man etwas HTML Code…
2307-html Code.png

…in ein Modul verwandeln das etwa wie folgt aussieht:
2306-Tabs-thumb-500x83-2305.png

Das Plugin hat dabei meist eigene Optionen, sogenannte Defaults. Diese werden durch die Optionen, welche der Benutzer dem Plugin beim Aufruf mitgegeben hat ergänzt:

var options = $.extend({}, $.fn.tabsPlugin.defaults, userOptions);

Innerhalb des Plugins, wird danach die entsprechende Plugin-Funktion auf jedem einzelnen der übergebenen Elemente ausgeführt. Dabei muss darauf geachtet werden, dass die Funktion nur auf das jeweilige Element Einfluss hat, damit mehrere Elemente auf der Seite die gleiche Funktionalität haben können.

var $tabSets = $(this);
$tabSets.each(function(){
     // Auf jedem Element die gewünschte Funktion ausführen
     var $tabSet = $(this); // Aktuelles Tab-Set
     ...
});

Nun soll’s ein bisschen anders sein…

Ein Problem vieler Plugins ist, dass sie zwar meist ihre Aufgabe gut erledigen, nicht selten auch viele Optionen mitbringen, aber nicht flexibel oder erweiterbar sind. Nehmen wir ein Plugin, das aus einem Set an HTML Elementen ein Tab-UI generieren soll. Dieses Plugin übernimmt das Sammeln der Tabs und zugehörigen Panels, sowie das Ein- und Ausblenden der Panels beim Klick auf ein Tab. Ausserdem bringt es noch einige Optionen mit, womit der Benutzer festlegen kann, welche Klassen die ausgewählten Tabs haben sollen und welches Tab zu Beginn aktiviert werden soll. Ist doch Perfekt, nicht?

Was nun, wenn der Inhalt des Panels beim Aufruf der Seite noch nicht vorhanden ist sondern erst nachgeladen werden soll, wenn man das entsprechende Tab aktiviert? Herkömmliche Plugins versagen hier oft und gewünschte Funktionalität muss direkt im Plugin eingefügt werden. Dabei geht die Update-Fähigkeit verloren und es leidet die Wiederverwendbarkeit und Sicherheit des Projekts. Im Wissen, dass der Benutzer vielleicht mit dem Plugin noch weiter Anwendungsfälle hat neigt der Autor des Plugins dazu, möglichst viele Funktionen in sein Plugin zu stecken, da er es ja flexibel halten möchte. Damit wird es gross, schwerfällig und unübersichtlich und verfügt über eine Menge Funktionen, welche viele unter Umständen gar nicht brauchen. Der Autor des besagten Tab-Plugins muss dabei an Tastatur-Bedienbarkeit, Ajax- und History-Fähigkeit sowie vieles mehr denken.

Evented jQuery Plugins = flexibel & erweiterbar

Eine Lösung für dieses Problem lautet Custom Events oder kürzer – Evented. Dabei muss sich der Plugin Autor überlegen, welche grundlegende Funktionen das Plugin benötigt und stellt diese in einer möglichst schlichten Form zur Verfügung.

Ein Tab-UI-Element hat im Grossen und Ganzen eine Funktion: Beim Klick auf ein Tab, soll das zugehörige Panel aktiviert und alle anderen deaktiviert werden. Wir brauchen also eine „activate“ Funktion. Ausserdem müssen zu Beginn alle Tabs gesucht, und die zugehörigen Panels gespeichert werden. Dazu benötigen wir eine „setupTabs“ Funktion. Des weiteren sollten die Panels wissen, zu welchem Tab sie gehören: „setupPanels„. Beim Aufruf der Seite sollen diese beiden Funktionen ausgeführt werden und das erste Tab aktiviert werden, dazu brauchen wir noch eine letzte Funktion, die „initialize“ Funktion.

Diese Funktionen sind „Events“. Jedes übergebene Set an HTML Elementen wird mit diesen Events versehen. Da der Event damit immer zu einem Tab-Element gehört, kann damit auch das Problem von allfälligen Konflikten mit anderen Tab-Elementen einfach gelöst werden. Wenn auf einer Seite zwei Tab-Elemente vorhanden sind, beeinfluss Tab-Verbund eins den zweiten Tab-Verbund nicht, wenn darauf der activate Event ausgeführt wird:

...
$tabSets.bind("activate",
        function(e, selected) {
            // selektiertes Tab aktivieren
        }
);
...

Events nach Aussen verfügbar machen

Der Trick besteht nun darin, dass diese Funktionen nicht einfach fest in das Plugin integriert sind, sondern das jede einzelne Funktion in ein Array gepackt wird, welches über ein Objekt customEvents von aussen Zugänglich ist. Die Funktions-Array können dadurch ergänzt, oder gar ganz überschrieben werden, bevor das Plugin auf ein Set von HTML Elementen angewendet wird.

var customEvents = {
    initialize: [function(options) {
        this.bind("initialize." + options.namespace,
        function(e) {
            // Tabs und Panels vorbereiten
            //und erstes Tab Aktivieren
        });
    }],

    setupPanels: [function(options) {
        this.bind("setupPanels." + options.namespace,
        function(e) {
            // Panels mit zugehörigem Tab verbinden
        });
    }],

    setupTabs: [function(options) {
        this.bind("setupTabs." + options.namespace,
        function(e) {
            // Tabs suchen und activate Funktion bei klick ausführen
        });
    }],

    activate: [function(options) {
        this.bind("activate." + options.namespace,
        function(e, selected) {
            // Alle Tabs deaktivieren und selektiertes
            // Tab und Panel aktivieren
        });
    }]
};

Events ergänzen

Im unserem Beispiel wollten wir, dass der Inhalt des Panels erst vom Server geladen wird, wenn das Tab aktiviert wird. Die Vorgehensweise ist nun denkbar einfach, man fügt einfach vor der Plugin-Standard-Funktion eine neue Funktion hinzu, welche den Inhalt des Panels via Ajax vom Server lädt. Dabei muss man zu keiner Zeit das Plugin selber verändern. Wenn der Plugin Autor ein Bug-Fix veröffentlich, kann das Plugin einfach aktualisiert werden – die Grundfunktionen werden die gleichen bleiben und die Erweiterung wird nicht tangiert da sie sich ausserhalb des Plugins befindet.

// Neue Funktion vor die bestehende
// activate Funktion schieben:
customEvents.activate.unshift( function(options) {
    // Die Erweiterung auf das Grund-Element
    // (nicht die einzelnen Tabs) binden:
    this.bind("activate." + options.namespace,
        function(e, selectedTab) {
            // Den Inhalt des Tabs hier
            // per Ajax in das Panel laden:
            var url= selectedTab.href;
            $(selected).data('$panel').load(url);
   });
});

Der Kern des Plugins ist dabei lediglich dafür verantwortlich, dass die Default Einstellungen mit den Benutzer-Optionen ergänzt werden und dass danach alle Tab-Elemente die Custom Events erhalten.

Hello World!

Nachdem man dieses erweiterbare und flexible Tabs-Plugin geschrieben hat, ist es natürlich schön, wenn sich der Rest der Welt auch daran erfreuen kann. In meinem nächsten Post werde ich zeigen, wo und wie man ein eigenes Plugin veröffentlichen kann und was dabei zu beachten ist.

The Terrific Way Of JavaScript

Wie im „letzten Post“:http://blog.namics.com/2010/07/terrific-oocss-part2.html veranschaulicht, setzt Terrific im HTML/CSS Part voll auf „OOCSS“:http://wiki.github.com/stubbornella/oocss. In Sachen JavaScript beschreitet Terrific jedoch völlig eigene Wege.

Was bringt’s?

Die Hauptvorteile des JavaScript Systems von Terrific sind:

Leichtgewichtige Architektur
Terrific strukturiert die JavaScript-Entwicklung ohne dabei die Entwickler einzuschränken. So können Entwickler weiterhin ihr gesamtes „jQuery“:http://www.jquery.com – Knowhow voll einsetzen und profitieren gleichzeitig von den zahlreichen Features und Möglichkeiten von Terrific.

Modulare Entwicklung
Die gesamte JavaScript-Entwicklung wird durch Terrific modularisiert. So können sämtliche „Module“:http://blog.namics.com/2010/06/terrific-part1.html einzeln entwickelt und getestet werden und – was noch viel wichtiger ist – ohne Seiteneffekte miteinander kombiniert werden.

Skalierbarkeit
Die Seite wird mit wachsender JavaScript-Grösse nicht durch unzählige DOM-Operationen und Events verlangsamt. Es wird wirklich nur der Code ausgeführt, welcher wirklich von den Terrific-Komponenten benötigt wird.

Einfache Integration
Mit Terrific entwickelte Frontends lassen sich mühelos in die verschiedensten Backendsysteme und CMS integrieren. So kann die Frontendentwicklung komplett vom entsprechenden Zielsystem entkoppelt werden.

Wie haben wir es gemacht?

Wie schon im „ersten Post dieser Serie“:http://blog.namics.com/2010/06/terrific-part1.html erwähnt, nutzt Terrific die „OOCSS-Namenskonventionen“:http://blog.namics.com/2010/07/terrific-oocss-part2.html technologieübergreifend sowohl für den HTML/CSS Part als auch für den JavaScript Part.
Dies erlaubt es Terrific, einen einheitlichen Bootstrapping-Mechanismus zu verwenden – egal ob es sich dabei um einfache Seiten mit wenig JavaScript-Funktionalität oder komplexe Applikationen handelt.

(function($) {
    var application = new Nx.Application($('.page'));
    application.registerModules();
    application.startAll();
})(Nx.$);

That’s it! Abgesehen von dem „Drumherum“ – ein klassischer 3-Zeiler ;-)

Die einzelnen Zeilen haben es jedoch ganz schön in sich.

var application = new Nx.Application($('.page'));

Diese Zeile instanziert eine neue Terrific-Application. Was auffällt ist, dass Terrific den „Namespace“:http://docs.jquery.com/Using_jQuery_with_Other_Libraries Nx (für Namics) verwendet. So kann Terrific auch parallel zu bestehenden oder durch das Backendsystem vorgegebenen JavaScript-Funktionalitäten verwendet werden.
Der Parameter $(‚.page‘) gibt den Context der Applikation an – .page ist nach OOCSS-Konvention der Seitencontainer.

application.registerModules();

registerModules übernimmt den Hauptteil des Bootstraps. Die Methode durchsucht den DOM-Tree nach Modulen – nach OOCSS-Konvention besitzen sämtliche Module die Klasse .mod – und instanziert per Namenskonvention die entsprechenden Module. Zum Beispiel wird für die Klasse .modNews das JavaScript Modul Nx.Module.News instanziert.

Als Pendant zu den OOCSS-Skins bietet Terrific JavaScript-Skins an – welche im Grunde nichts anderes als Module „Decorators“:http://en.wikipedia.org/wiki/Decorator_pattern#JavaScript sind.
Auch die Dekoration der Module geschieht – wie könnte es auch anders sein – per OOCSS-Namenskonvention. Besitzt ein DOM-Node die Skin-Klasse .skinNewsHighlighted so wird das Nx.Module.News Modul mit dem Nx.Module.News.Highlighted Skin dekoriert.

Um eine Kommunikation zwischen den Modulen zu ermöglichen – ohne mit dem „Loose Coupling“:http://en.wikipedia.org/wiki/Loose_coupling Gedanken zu brechen – werden in der registerModules-Methode auch noch per Namenskonvention definierte Kommunikationskanäle zwischen den Modulen aufgebaut.

Nachdem also alle Module inkl. Skins und Connectors in der Application registriert sind, kommt der Bootstrap in die letzte Phase.

application.startAll();

Mit startAll wird die Initialisierung der Module gestartet. Jedes Modul durchläuft dabei potentiell vier Phasen, welche nach Bedarf durch die entsprechende „Hook-Methode“:http://de.wikipedia.org/wiki/Schablonenmethode implementiert werden können.

  • dependencies – Nachladen von Libraries, Plugins etc. via Ajax
  • beforeBinding – Daten per Ajax holen, DOM Manipulationen etc.
  • onBinding – Events binden
  • afterBinding – Default State herstellen, Events triggern etc.

In den häufigsten Fällen werden jedoch nicht alle Phasen, sondern nur die onBinding-Phase benötigt. Terrific kümmert sich dabei um das Timing und die sequentielle Abarbeitung der vier Module-Phasen.

Beispiel gefällig?

Greifen wir das Modul-Beispiel aus dem „letzten Post“:“http://blog.namics.com/2010/07/terrific-oocss-part2.html wieder auf.

2131-Terrific-Module.png

Das Currency Converter Module hat folgende Funktionalitäten:

  • Ajax Live-Convertion
  • Non-JavaScript Variante mit Convert Button
  • Automatische Erstberechnung des aktuellen Werts

dependencies

Da nicht nach jedem Tastendruck eine Ajax-Berechnung ausgelöst werden soll, sondern nur sobald der Benutzer aufhört zu tippen, benötigen wir das „jQuery throttle / debounce Plugin“:http://benalman.com/code/projects/jquery-throttle-debounce/docs/files/jquery-ba-throttle-debounce-js.html von „Ben Alman“:http://benalman.com/.

/**
 * Hook function to load the module specific dependencies.
 *
 * @method dependencies
 * @return void
*/
dependencies: function() {
    this.require('jquery.throttle-debounce.min.js', 'plugin', 'onBinding');
}

Der dritte Parameter – in unserem Beispiel „onBinding“ – gibt an, in welcher Phase die dependency benötigt wird. Terrific kümmert sich um das Timing und die entsprechenden Callbacks. Zudem stellt Terrific sicher, dass von mehreren Modulen benötigte dependencies nicht doppelt nachgeladen werden.

beforeBinding

Alternativ zur Live-Convertion bietet die Non-JavaScript Variante einen zusätzlichen Convert Button. Dieser kann in der JavaScript Variante versteckt werden. DOM Manipulationen werden – um unnötiges Flackern zu vermeiden – in der beforeBinding-Phase durchgeführt.

/**
 * Hook function to do module specific stuff before binding the events (i.e. fetching some data).
 *
 * @method beforeBinding
 * @param {Function} callback the callback function which must be called at the end
 * @return void
 */
beforeBinding: function(callback) {
    $(':submit', this.$ctx).hide();
    callback();
}

Durch die Verwendung von this.$ctx (this.$ctx enthält den Module-DOM-Node) als zweiten Parameter im jQuery-Selector, werden die Events nur auf die aktuelle Modulinstanz gebunden. So können Module also auch problemlos mehrmals auf einer Seite verwendet werden.

onBinding

In der onBinding-Phase werden die Events gebunden.

/**
 * Hook function to bind the module specific events.
 *
 * @method onBinding
 * @return void
*/
onBinding: function() {
    var that = this;

    // disable the standard action on submit
    $('.converter', this.$ctx).bind('submit', function() {
       return false;
    });

    // bind the keyup event to start the convertion. To reduce the number
    // of ajax calls, the debounce plugin is used.
    $('.amount', this.$ctx).keyup($.debounce(250, function() {
        var $this = $(this).closest('form');
        var url = $this.attr('action') + '?' + $this.serialize();
        // ajax stuff etc.
        ...
        return false;
    }));
}

In unserem Beispiel wird durch return false – da die Live-Convertion nicht per Enter, sondern automatisch nach Beendigung der Eingabe ausgelöst werden soll – die Standard-Submitaktion unterbunden.

Im keyup-Eventhandler kommt das in der dependencies-Phase nachgeladene debounce-Plugin zum Einsatz. Dadurch kann die Anzahl Ajax-Requests stark reduziert werden, da die Berechnung erst nach 250ms Idle-Time ausgelöst wird.

afterBinding

Damit dem Benutzer gleich zu Beginn eine aktuelle Berechnung präsentiert werden kann – zum Beispiel der aktuelle Eurokurs – wird in der afterBinding-Phase die Initialberechnung ausgelöst.

/**
 * Hook function to do module specific stuff after binding the events (i.e. triggering some events).
 *
 * @method afterBinding
 * @return void
 */
afterBinding: function() {
    $('.amount', this.$ctx).trigger('keyup');
}

Was kann Terrific sonst noch?

Obwohl die Modul-Funktionalität den Hauptpart des Terrific JavaScript Systems darstellt, hat Terrific noch zahlreiche weitere JavaScript Features zu bieten, die das Programmiererleben erheblich erleichtern. Einige der Funktionen, die Terrific mit sich bringt:

  • Skins – Module Decorators
  • Layouts – seitenweite Funktionalitäten, z.B. Drag’n Drop von Modulen etc.
  • Connectors – ermöglichen die Kommunikation zwischen Modulen über konfigurierbare Kanäle
  • Sandbox – Bezug von Ressourcen, Zugriff auf andere Modulinstanzen etc.
  • Logging-Architektur
  • Zentrales Errorhandling

Die Terrific-Funktionalitäten sind also ziemlich umfassend ;-). Bis jetzt konnten wir alle Kundenwünsche mit den Bordmitteln von Terrific umsetzen. Neue, anspruchsvolle und herausfordernde Frontends sind also herzlich willkommen!

Real World Beispiele?

Das „Intranet von Repower“:http://www.namics.com/taten/neues-intranet-repower/ wurde komplett mit Terrific umgesetzt. Integriert wurde das Ganze in das Enterprise Wiki „Atlassian Confluence“:http://www.atlassian.com/software/confluence/. Wiki? Anspruchvolles Frontend? Wie man dies unter einen Hut bringen kann, zeigen wir im nächsten Terrific-Post!

h4. Weitere Terrific Informationen

Open Source Projekt: Terrific und TerrificJS

Terrific – Modulare Frontendentwicklung
Terrific und OOCSS
The Terrific Way Of JavaScript
Terrific im Projekprozess

Terrific und OOCSS

Wie im letzten Terrific-Post angetönt, geht es in dieser Episode ein bisschen ans Eingemachtere… also dann, auf gehts…

Wieso OOCSS?

Terrific basiert auf OOCSS. Um die Vorteile von OOCSS zu begreifen, muss man zuerst die Schwachstellen und Probleme von CSS verstehen.

Code ist sehr „fragil“
Eine falsche Änderung kann durch die Kaskadierung unvorhersehbare Effekte hervorrufen – zum Beispiel Layoutfehler auf Seite xx.

Parallele Entwicklung im Team ist extrem schwierig
Die CSS-Regeln beeinflussen sich gegenseitig. Ohne genaue Kenntnisse über die Arbeit der Teamkollegen, ist die parallele Entwicklung praktisch unmöglich.

Code-Reuse ist sehr selten
Wir „vertrauen“ nicht auf den Code von anderen. Dies nicht aufgrund egomanischen Zügen, sondern weil uns die Erfahrung gelehrt hat, dass wir oftmals eleganter und schneller zum Ziel kommen, wenn wir CSS-Code von Grund auf selber schreiben. Nicht selten bedient man sich dabei stark gekapselten CSS-Selektoren à la „#id .class“, die einen Reuse wegen ihrer hohen Spezifität und Individualität praktisch ausschliessen.

Konsequenzen

  • Code wird unübersichtlich und unstrukturiert
  • Der Code wächst linear zur Projektgrösse = Performanceprobleme

Beides hat zur Folge, dass die Fehleranfälligkeit stark ansteigt und der Code unwartbar wird.

Wie macht man es besser?

OOCSS wurde von Nicole Sullivan (Yahoo) entwickelt und stellt einen wiederverwendbaren Baukasten an CSS-Klassen zur Verfügung. Oberstes Ziel von OOCSS ist es, vorhersagbares Verhalten ohne Seiteneffekte sicherzustellen. Dies wird erreicht, indem das Markup und die dazugehörigen CSS-Klassen stark standardisiert werden.

Alle Terrific Komponenten werden entsprechend den OOCCS-Regeln umgesetzt:

Elements

Grundlegende Definition der HTML Elemente

/* Link */
a.base, a.base:link, a.base:visited {
    color: #434343;
    text-decoration: underline;
}

Als Namenskonvention wird.base verwendet. Dadurch kann man von Module zu Module selbst entscheiden, ob man den Basisstyle eines Elements verwenden will oder nicht.

Layout

Aufteilung in einzelne, voneinander getrennte Bereiche (z.B. Header, Footer, 3 Spalten)

2126-Terrific-Layout-thumb-500x241-2125.png

Das zugehörige Markup ist beinahe selbsterklärend:

<div class="page">
<div class="head">
<h2>Head</h2>
</div>
<div class="body">
<div class="leftCol">
<h2>Left Column</h2>
</div>
// more leftCols
<div class="rightCol">
<h2>Right Column</h2>
</div>
// more rightCols
<div class="main">
<h2>Main Content</h2>
</div>
</div>
<div class="foot">
<h2>Foot</h2>
</div>
</div>

Mit den OOCSS-Klassen page, head, foot, leftCol, rightCol und main lassen sich in kürzester Zeit Layouts erstellen, die bis und mit IE 5.5 abwärtskompatibel sind.

Grid

Seitenspezifische Unterteilung in Lines und Units

2129-Terrific-Grid-thumb-500x189-2128.png

Und das Markup? Et Voilà!

<div class="line">
<div class="unit size1of5">
<h3>1/5</h3>
</div>
// repeat 3 times
<div class="unit size1of5 lastUnit">
<h3>1/5</h3>
</div>
</div>
<div class="line">
<div class="unit size2of5">
<h3>1/5</h3>
</div>
<div class="unit size3of5 lastUnit">
<h3>1/5</h3>
</div>
</div>

Lines und Units können beliebig verschachtelt werden. So können auch komplexeste Grids mühelos erstellt werden. Lediglich bei den Units muss darauf geachtet werden, dass die Summe aller Breitenangaben nicht die umgebendende Line sprengt. Mit den von OOCSS mitgelieferten size-Klassen (size1of5, size3of5 etc.) wird dieses Problem durch prozentuale Breitenangaben umgangen. Bei eigenen Grids muss dieser Umstand jedoch berücksichtigt werden.

Modules

Module sind in Terrific das zentrale Thema. Praktisch sämtliche Inhalte und Funktionalitäten stammen aus den Inhaltsmodulen.

Beispiel: Currency Converter

2131-Terrific-Module.png

Um den Entwickler nicht einzuschränken, gibt OOCSS nur die Wrapper-Divs vor. Terrific erweitert das ganze noch durch eine modulspezifische Klasse (modCurrencyConverter), welche für die Kapselung des CSS und das Terrific JavaScript System benötigt wird.

<div class="mod modCurrencyConverter">
<div class="inner">
<div class="bd"><!-- 1-n times --> ...</div>
</div>
</div>

Sämtliche CSS-Regeln werden mit der spezifischen Modulklasse prefixed. Die Kaskade von CSS übernimmt also quasi die „Objektorientierungs“-Rolle.

.modCurrencyConverter .bd {
    background: #fff;
    padding: 10px 10px 18px 10px;
}
...

Skins

Skins bieten die Möglichkeit, das Aussehen von Modulen gezielt zu überschreiben. So können zum Beispiel mandantenfähige Systeme problemlos umgesetzt werden – ein Modulegrundstyle und ein Skin pro Mandant – ohne sämtlichen Code duplizieren zu müssen.

2137-Terrific-Skin-thumb-400x194-2134.png
<div class="mod modCurrencyConverter
       skinCurrencyConverterHighlighted">

<div class="inner">
<div class="bd"><!-- 1-n times --> ...</div>
</div>
</div>

Der Skin erbt sämtliche Regeln des Moduls. Um den Hintergrund zu verändern, muss im Skin-CSS also lediglich die entsprechende Regel überschrieben werden:

.skinCurrencyConverterHighlighted .bd {
    background: #aebbcb;
}

Skins sind auch nützlich, um „ähnliche“ Inhalte in einem einzigen Modul zusammenzufassen. Die voneinander abweichenden Definitionen werden dabei in die Skins ausgelagert.

Wie weiter?

Die HTML/CSS Problematik wird von OOCSS sauber gelöst. Das beschriebene 5-Komponenten-Prinzip von Terrific unterstützt dabei die modularisierte Frontendentwicklung optimal.

Aber wie sieht es mit dem JavaScript Part aus? Mehr dazu im nächsten Terrific-Post!

Weitere Terrific Informationen

Open Source Projekt: Terrific und TerrificJS

Terrific – Modulare Frontendentwicklung
Terrific und OOCSS
The Terrific Way Of JavaScript
Terrific im Projekprozess

Terrific – Modulare Frontendentwicklung

Hintergrund

Die Komplexität von Frontends wird immer grösser – und somit natürlich auch der Spass bei der Umsetzung. Dachte man bis vor Kurzem in „Seiten“, so spricht man jetzt vermehrt von Modulen und Single Page Applikationen. Dieser Schritt weg vom Seitendenken hin zu wiederverwendbaren Modulen, die beliebig miteinander kombiniert werden können, zieht auch ein Umdenken in der Frontendentwicklung nach sich.

Wiederverwendbarkeit, Skalierbarkeit, parallele Entwicklung und Reduzierung von Abhängigkeiten sind die zentralen Anliegen der modularen Frontendentwicklung.

Das Thema wird zurzeit heftigst an allen Frontendkonferenzen und in der Community diskutiert. Dabei werden die einzelnen Technologien meist isoliert betrachtet.

Ein spannender Ansatz für den HTML/CSS Part bietet OOCSS von Nicole Sullivan. OOCSS wird bereits auf zahlreichen Websites eingesetzt und hat sich auch schon in grossen Projekten (z.B Yahoo) erfolgreich bewährt.

Interessante Ideen zum JavaScript Part liefert Nicholas Zakas in seinem Vortrag Scalable JavaScript Application Architecture

Beide Ansätze gehen vom Modulgedanken aus, basieren jedoch aufgrund der isolierten Betrachtung auf unterschiedlichen Konventionen.

Genau hier setzt Terrific an!

Terrific

Terrific ist ein von Namics entwickeltes Frontend Development Framework, das auf Basis von OOCSS, jQuery und unzähligen anderen Ideen, Diskussionen und Best-Practices entstanden ist.

Im Gegensatz zu den technologiegebundenen Ansätzen nutzt Terrific die OOCSS-Namenskonventionen technologieübergreifend sowohl für den HTML/CSS Part als auch für den JavaScript Part. Dadurch entsteht eine lose gekoppelte, modulare, clientseitige Architektur, die den ganzen Frontendprozess standardisiert – wenn nicht sogar revolutioniert!

5-Komponenten-Prinzip

Jede Terrific-Applikation besteht aus fünf Basiskomponenten:

  • Elements -> grundlegende Elemente (h1, h2 etc.)
  • Layout -> einzelne, voneinander getrennte Bereiche, die den meisten Seiten innerhalb Applikation gemeinsam sind (z.B. Header, Footer, 3 Spalten)
  • Grid -> weitere, seitenspezifische Unterteilung in Lines und Units
  • Modules -> Inhaltsmodule
  • Skins -> Skins für Module

Beispiel Repower Intranet:

2027-Repower_Dashboard_Layout-thumb-500x325-2019-thumb-500x325-2020.jpg

* Grün: Layout

2025-Repower_Dashboard_Grid_Modules-thumb-500x325-2022-thumb-500x325-2023.jpg
  • Magenta: Grid
  • Blau: Modules

In den nächsten Terrific-Posts gehe ich detailliert auf die einzelnen Komponenten und deren Umsetzung ein. Es wird also technisch und sehr spannend!

Weitere Terrific Informationen

Open Source Projekt: Terrific und TerrificJS

Terrific – Modulare Frontendentwicklung
Terrific und OOCSS
The Terrific Way Of JavaScript
Terrific im Projekprozess

Railswaycon 2010 in Berlin

Letzte Woche durften Christian Felder und ich die Railswaycon in Berlin besuchen (danke Namics!). Auch wenn neben Yehuda Katz vielleicht die eine oder andere Grösse mehr hätte anwesend sein können, waren die Talkthemen sehr interessant. Hier eine kurze Zusammenfassung von ausgewählten Talks:

Push it to the limit – An intro to Websockets and Rails applications
Michael Johann zeigte, wie die Zukunft von real-time Applikationen aussehen kann. In HTML5 kann das bisher gängige Polling durch Websockets abgelöst werden. Dabei wird im Browser eine bidirektionale Verbindung zum Server aufgebaut, mit welcher der Server den Client per Push über Updates informieren kann. Ebenfalls erwähnenswert ist PubSubHubbub. Mit Hilfe von Websockets implementiert es ein Publish Subscriber System, basierend auf Atom und RSS.

Cross-Browser testing in the real World
Die Browservielfalt macht das Leben jedes Webentwicklers schwer. Martin Kleppmann stellte eine Landkarte der vielen vorhandenen Tools vor. Capybara steuert Selenium 2 via Webdriver und Watir, womit man auf Chrome, Firefox, Internet Explorer und Safari automatisiert testen kann. Mit Celerity kann zusätzlich noch Headless (hierbei wird kein Browser geöffnet) getestet werden. Anschliessend wurden 10 praktische Probleme und Lösungsansätze vorgestellt. Ziemlich komplex, wenn man alles abdecken will.

Small is Sexy – We need Components in Rails!
Nick Sutterer ist der Überzeugung, dass wir in Ruby on Rails Views Komponenten brauchen. Cells bietet gekapselte View-Objekte, welche sich kontextunabhängig selbst rendern können. Auf Wunsch können diese mit dem eventgetriebenen Aptomo auch stateful sein. So kann z.B. für eine Warenkorb-View einiges an Logik strukturiert werden. Laut Yehuda Katz werden einige Zeilen der Cells Codebase vielleicht in Rails 3 einfliessen.

Mongodb and Mongomapper 4 real!
Realational ist out, denn Document Storages sind da! Jan Krutisch zeigte wie der No-SQL Ansatz mit MongoDB verfolgt werden kann. Daten werden bei Document Storages wie der Name schon sagt in Form von Dokumenten geschrieben. Somit gibt es kein festes Schema der Datenbank mehr und es können nahezu beliebige Konstrukte gespeichert werden. Klarer Vorteil gegenüber relationalen Datenbanken ist die Performance. Statt einer Query Language wie SQL werden in Javascript so genannte Map- / Reduce-Funktionen geschrieben.

Rails 3: Dashing to the Finish
Die Merb Ikone Yehuda Katz zeigte an vielen Beispielen wie Rails 3 sich im Vergleich zu Rails 2 weiterentwickelt und verändert hat: Schneller, aufgeräumter, modularer und besser erweiterbar. Es gibt einige radikale Änderungen, womit eine Migration bestehender Applikationen etwas aufwändiger wird. Der grösste Teil ist jedoch bis Rails 3.2 rückwärtskompatibel. Ein wichtiger Bestandteil ist dabei die vollständige Implementierung des Rack Ansatzes. Zudem ermöglicht Bundler endlich gutes Dependency Management von gems.
Rails 3 kicks ass!

Ruby and Redis – Simple meets Awesome
Mathias Meyer berichtete von seinen Erfahrungen bei der Erweiterung einer Mysql-basierten Applikation mit Redis. Redis ist ein unglaublich schneller (mehrere 10000 Reads/Writes pro Sekunde), persistenter Key-Value-Store. Anhand diverser Beispiele wie Caching, Session storage, Statistiken, Who’s online, etc. wurde die Anwendung von Redis klarer und klarer. Umdenken ist angesagt!

Natürlich ist das nur ein kleiner Auszug der Themen. Wer mehr erfahren will, kann die Slides zu den meisten Tracks bei der schweizer Rails Usergroup finden.

Neben guten Vorträgen gab es in Berlin natürlich auch lecker Currywurst, heiter Sonnenschein und das ein oder andere gemeinsame Feierabendbier.