ROCA? Bedeutet das nicht einfach, nur RESTful Webseiten zusammenzuschrammeln? Nö, nicht nur. Mir geht es bei ROCA primär um den sinnvollen Einsatz der Frontend-Technologien (HTML, JavaScript, CSS) im Sinne des Progressive Enhancements [ROCA-PE]. In der Praxis kommen dann meist Javascript-Komponenten heraus, die sich Fachlogik-unabhängig jeweils um bestimmte Präsentations-Themen kümmern. Beispiele sind Treeviews, Asynchrone Formular-Validatoren, Date-Picker, Tabellen-Widgets und vieles mehr.
Allein die Vorstellung müsste vielen schon Tränen des Glücks in die Augen treiben: Wir laden uns einfach ein paar JavaScript-Komponenten aus dem Internet und brauchen uns mit dem Schmuddelkrams dann nicht mehr beschäftigen. Dieser Gedanke scheitert meist an mindestens zwei Punkten:
Das (kundenspezifische) Styling ist leider meist nicht dabei. Wir brauchen also mindestens einen Designer, was irgendwie hinzufummeln sein sollte.
Viel schwerwiegender aber ist, dass es in der Realität so gut wie keine ordentlichen JavaScript-Komponenten gibt. Jedes Mal, wenn man eine Komponente auswählt und denkt, „ah, die passt aber super auf meine Bedürfnisse“, verflucht man diese Entscheidung erfahrungsgemäß ein paar Tage später. Woran liegt das?
Vorausgesetzt, der Entwickler einer Komponente hatte überhaupt eine Vorstellung davon, wie seine Komponente später sein sollte (nennen wir es mal eine „Architektur“), sind diese Vorstellungen meistens nicht die selben, wie die der Entwickler der anderen Komponenten oder der einbettenden Anwendung. Oft werden solche Komponenten überhaupt nicht mit dem Ziel verfasst, irgendwo anders sauber eingebettet oder angepasst (beispielsweise umgestyled) zu werden.
Deswegen versuche ich mal im folgenden einige Punkte aufzuzeigen, anhand derer man die Eignung von Komponenten für ROCA-Architekturen überprüfen kann.
Reinitialisierungs-Fähigkeit
Die Wahrscheinlichkeit, dass die beim Seitenaufbau geladene DOM-Struktur gleich der Struktur zum Ende des Lebenszyklus der Seite ist, dürfte für die meisten Seiten recht nah bei 0% liegen. Heutzutage sind große Teile einer Seite einfach dynamisch und das ist auch gut so. Probleme gibt es meist, wenn der „unter einer Komponente liegende“ DOM manipuliert wird und die Komponente davon nichts mitbekommt bzw. mitbekommen will.
Denken wir an das einfache Beispiel eines Treeviews. Ist es so verwegen zu denken, dass man Teilbäume dieses Treeviews evtl. (an der Komponente vorbei) per Ajax nachladen oder anderweitig manipulieren will? Ich frage mich jedenfalls oft: Warum gibt es keine Treeview-Komponenten, die sauber reinitialisierbar sind?
Ein etwas einfacherer Fall ist, dass Markup per Ajax nachgeladen wird und eine Komponente innerhalb des entsprechenden neuen DOM-Teilbaums initialisiert werden muss. Dies ist letzten Endes aber natürlich kein Problem der jeweiligen Komponenten, sondern eher der Initialisierung selbst. Der einfache Ansatz der einmaligen Initialisierung via $(document).ready
dürfte für diesen (Standard-)Fall jedenfalls nicht völlig ausreichen.
Umstylebarkeit
Wie hoch ist wohl die Wahrscheinlichkeit, dass unsere Freunde vom Marketing sich mit einem jQuery-UI basierten Design/Theme zufrieden geben? Es kommen zwar erstaunlich viele Leute mit dem leicht angestaubten Charme des Designs der verwendeten Komponentenbibliothek durch [WTF] (selbst für öffentliche Webseiten), aber eigentlich sollte es heutzutage klar sein, dass jede Komponente zumindest ansatzweise an das Styling der Gesamt-Seite oder das Corporate Design angepasst werden muss.
Den Schlüssel dazu bietet meiner Meinung nach die strikte Trennung von funktionalem CSS (Layout) und Styling (bzw. Theming). Betrachtet man beispielsweise einen Date-Picker, so gibt es sicherlich einige Aspekte, die unabhängig vom letztendlichen Styling der einbettenden Webseite sind: Die Tage sollen entsprechend des jeweiligen Monats ordentlich tabellarisch dargestellt werden (dafür braucht man nicht mal CSS) oder der Picker soll magisch als Overlay erscheinen, wenn der Benutzer in das entsprechende Eingabefeld klickt. Welche Farbe aber der Rand des Overlays hat oder ob der aktuelle Tag grau oder blau hervorgehoben sein soll, muss letztendlich immer im jeweiligen Kontext unterschiedlich definiert werden.
Selbst wenn eine Komponente aber diese Trennung sauber vollzieht (Beispiele sind mir leider nicht bekannt), so sollte man aber immer noch in der Lage sein, auch funktionales CSS zu überschreiben. Soll beispielsweise der Datepicker nicht unter dem Eingabefeld erscheinen, sondern oberhalb eines Links (das Ausmaß menschlicher Unvernunft ist ja bekanntlich grenzenlos), so muss wohl oder übel auch in das funktionale Styling eingegriffen werden. Dies ist technisch eigentlich kein Problem. So steht das erste „C“ in „CSS“ bekanntlich für „Cascading“ und damit für die Möglichkeit, ein und die selbe Sache auch mehrfach beschreiben zu können. Treffen also mehrere widersprüchliche Aussagen für ein und das selbe Element zu, so kümmert sich dann CSS mit einem mehr oder weniger ausgefeilten Regelwerk darum, die Präzedenz der jeweiligen Aussage über die anderen zu bestimmen. Dies funktioniert eigentlich irgendwie immer, sodass im Prinzip jede durch eine Komponente gemachte CSS-Aussage überschreibbar ist. Die Frage ist nur: Wie schwer macht uns die Komponente dies? Ganz grundsätzlich lautet des Problem hier: „Überspefzifität von CSS Selektoren". Die Behandlung dieses Themas würde aber den Rahmen hier sicher sprengen.
Erweiterbarkeit
Ein weiterer Aspekt der Tatsache, dass solche Komponenten meistens nicht auf der grünen Wiese eingesetzt werden, ist die Vernetzung von Komponenten untereinander. So ist es durchaus wahrscheinlich, dass eine Komponente nicht bloß einmal initialisiert werden muss und dann vergessen werden kann. Stattdessen wird es oft die Notwendigkeit geben, bestimmte Ereignisse der Komponente (beispielsweise „Der Benutzer hat den DatePicker geöffnet“) mitzubekommen oder auch bestimmte Funktionalitäten von aussen zu steuern (beispielsweise „Mach den DatePicker wieder zu“). Der Schlüssel dazu ist natürlich die Verwendung von Events, die jede vernünftige Komponente feuern sollte, sowie die Referenz auf die Komponente nicht zu verlieren, um gegebenenfalls Methoden aufrufen zu können. Ersteres ist in der Regel kein Problem, zweiteres aber schon. Das liegt primär darin begründet, dass Frameworks wie jQuery die Komponenten-Referenz wegen des Fluent-Interface (.was().mache().ich().hier().eigentlich().gerade()
) nicht ordentlich nach aussen reichen. Man selbst kann (und will) sich diese Referenz also oft nicht selbst merken. Alternativ könnten Komponenten selbst dafür sorgen, dass ihre Referenz an der entsprechenden Initialisierungs-Stelle im DOM „aufbewahrt“ wird und nicht verloren geht. Leider gibt es dafür gerade im jQuery Universum keine Standard-Vorgehensweise, sodass die Wiedererlangung der Referenz eine höchst proprietäre Angelegenheit bleibt.
Framework-Unabhängigkeit
Auch wenn ich mir eben noch Mühe gegeben habe, so muss es jetzt doch raus: Ich mag jQuery nicht sonderlich. Die Gründe dafür wären sicherlich einen separaten Blog-Post wert. Was man aber, glaube ich, unabhängig von der Begründung behaupten kann ist: Ich bin damit nicht allein.
Versucht man jQuery zu vermeiden, so stellt man aber immer sehr schnell wieder fest, dass hunderte von gegebenenfalls sogar tollen und sinnvollen Komponenten einen immer wieder zu jQuery zwingen wollen. jQuery ist halt nicht nur ein Framework sondern ein ganzes Ökosystem, nennen wir es – an das höchst erfolgreiche „WS-*“ Universum angelehnt – einfach mal das „jQuery-*“ Universum.
Es gibt aber sicher viele Gründe für jQuery, die ich hier ebenfalls nicht aufzählen möchte. Was mir dabei aber wichtig wäre, ist eigentlich eine Selbstverständlichkeit: Wenn man sich schon dafür entscheidet, eine Komponente auf jQuery basieren zu lassen, so sollte man die Nutzer dieser Komponente, die man durch die Entscheidung natürlich ebenfalls zu jQuery zwingt, wenigstens nicht zu einer bestimmten Version von jQuery zwingen. Dazu beitragen könnte, z.B. möglichst wenig vom API-Umfang von jQuery einzusetzen oder auf bestimmte Funktionsbereiche komplett zu verzichten.
Barrierefreiheit / Semantik Markup
Vermutlich das erste, was man sich bei der Bewertung einer Komponente anschauen sollte, ist das Markup bzw. genauer die DOM-Struktur, die sie produziert. Handelt es sich hierbei um semantisches Kuddelmuddel oder ist es voll mit inline-Styles, so dürfte es einem eine Ahnung vom restlichen Zustand der Komponente geben.
Aus meiner Sicht gelten auch für Komponenten: Das erzeugte Markup muss semantisch sein, muss Style und Inhalt sauber trennen und muss Barrierefreiheit unterstützen.
Wat nu?
Wenn ich mir das hier noch einmal durchlese, so ist es eigentlich erschreckend, wie wenig überraschend das alles ist und wie wenig selbstverständlich es gleichzeitig aber zu sein scheint. Ich bin mir dabei aber nicht sicher, inwieweit sich meine subjektive pessimistische Wahrnehmung mit der echten Welt deckt. Daher hoffe ich, irgendwann dazu zu kommen, bestehende Komponenten auf diese Kriterien hin zu untersuchen. Anfangen würde ich vermutlich mit einigen bereits identifizierten Kandidaten [ROCA-Libs].