Die Adobe Consultants Eric Garza, Peter Matin und Alistair McLeod hielten auf der MAX in San Francisco und Mailand hervorragende Vorträge zu Cairngorm. Ihre Themen lauteten „FIA Development with Cairngorm – Tips from the Experts“ und „Flex Development with Cairngorm„.
Es lohnt sich die Folien dieser Vorträge (Vortrag 1, Vortrag 2) sehr genau zu studieren. Denn auch wenn Cairngorm als Architektur-Framework schon einige Jahre eingesetzt wird und viele Flex Entwickler mit Cairngorm gut vertraut sind, herrschen noch sehr unterschiedliche Meinungen und Strategien beim Einsatz des Frameworks, nicht zuletzt wegen der mangelhaften Dokumentation.
Auch wenn sich Cairngorm in der Grundstruktur über die Jahre kaum weiterentwickelt hat, haben sich die aktuellen „Best Practices“ bei Adobe Consultings wesentlich geändert. Ein Grund mehr, auch seinen eigenen Einsatz von Cairngorm zu überdenken.
Hier ein Überblick über die Experten-Tips:
- ModelLocator
- ModelLocator ist im wahrsten Sinne des Wortes ein „Ort für Models“ D.h. der Model Locator hält typisierte Model Objekte. Dazu gehören u.a. Presentation Models, globale Informationen (z.B. UserVO), globaler Applikation-State. Dazu gehören aber keine Eigenschaften wie z.B. „address“, „country“ usw.
- Schluss mit den unzähligen „ModelLocator. getInstance()“! Der ModelLocator wird nur einmal im (Haupt-)View über getInstance() aufgerufen. Alle weiteren Views werden ihre notwendigen Models injiziert (Stichwort: Dependencies Injection ). D.h. ein View wird nur mit seinen notwendigen Daten per Referenz „befüllt“, z.b. mit seinem Presentation Model (siehe Punkt 2) oder einem Top-Model-Object. Aber auch mit dem ModelLocator selbst, falls es notwendig ist.
- Presentation Model (PM)
- Vorab: Wer mehr über den Einsatz von Presentation Models erfahren möchte, hier zwei sehr empfehlenswerte Artikel:
– Martin Fowler: Presentation Model
– Paul Williams: Presentation Patterns – Presentation Model - PM präsentiert das Verhalten und die State eines oder mehrerer Views, d.h. soviel Code wie möglich wird von dem View in sein PM ausgelagert. Dazu zählen: View-Daten (z.B. gefilterte Listen von Produkten), View-States (z.B. selectIndex eines ViewStackes), View-Logik (z.B. State eines Absende-Buttons innerhalb eines Formulars)
- Ein View beobachtet über Bindings Änderungen von Model-Daten.
- Ein View kennt sein PM, aber ein PM nicht die Views.
- Über das PM wird die View und Business-Logik getrennt. Sollte ein PM zu viele Verantwortlichkeiten erhalten, empfiehlt es sich, Teile der Business-Logik in weitere externe Klassen auszulagern
- PM verarbeitet auch Fehler, z.B. bei serverseitgen Abfragen von Daten (siehe auch Punkt 3)
- Updaten von Model-Daten
- User-Gesten vom View werden direkt an sein PM weitergegeben, um von dort Cairngorm-Events abzufeuern. Das Event landet wie gehabt im entsprechenden Command.
- Commands sollten keine direkte Referenze zu Models haben und somit die Model-Daten selbst nicht updaten. Stattdessen schicken die Cairngorm-Events Model-Callback-Funktionen als Referenzen mit, welche dort (z.B. im PM) direkt geupdated werden
- Serverseitige Daten werden über Delegates abgearbeitet, welche über Responder das Ergebnis weitergeben. Dabei wird empfohlen, für die Responder eigene Klassen anzulegen. D.h. die Commands brauchen nicht das IResponder-Interface zu implementieren.
- Im Command werden Responder-Klassen erstellt, welche ebenfalls ebenfalls eine Referenz zu den Callback-Funktionen erhalten, welche von den Cairngorm-Events „übermittelt“ werden. Damit können die Responder innerhalb ihrer result- oder fault-Methode diese Callbacks aufrufen, welche dann Model-Daten updaten. Um das Fault-Handling zu vereinfachen, wird zudem eine Super-Klasse für die Responder emfpohlen, welche das Error-Handling bereits implementiert
- Controller
- Große Controller sind zu vermeiden: Statt den Controller unübersichtlich mit unzähligen „addCommand(…, …)“ zu befüllen, bieten sich SubController an oder einfach auch Methoden für bestimmte Mappings, wie z.B. addAccountManagementCommands()
- Views
- View erhalten ihre Daten über Binding zu ihrem Model (PM)
- Logik der Views wird weitgehendst in PM ausgelagert (siehe Punkt 2). Dazu zählt aber nicht die Logik des User-Interfaces, wie z.B. Animationen, Drag und Drop, Stylen von Grafische Elemente, usw.
- Custom Components sollten keine Referenz zum ModelLocator haben. Stattdessen sollten die notwendigen Daten injiziert werden (siehe auch Punkt 1)
- Unit Testing
- Aufgrund des massiven Einsatzes von PM sind Model-Daten gut testbar! Falls nicht, sind in den PM noch zu starke Abhängigkeiten.
- Business-Logik in eigenen Klassen halten. D.h. raus aus Commands, Delegates, Responders.
- Zum Testen von Delegates empfiehlt sich das Verwenden von Factory-Klassen, welche mit Einsatz von Interfaces ein „produktives“ und ein „testbares“ Delegates liefert
- Cairngorm Plugin für Flex Builder
- Absolut empfehlenswert für noch schnelleres Arbeiten: Cairngorm Plugin bei Adobe Open Source
Übrigens: In den o.g. Folien der Präsentationen der Adobe Consultings findet Ihr auch eine Menge Code-Beispiele, die es sich ebenfalls lohnen, genauer unter die Lupe zu nehmen 😉
[NACHTRAG v. 13.01.2009] Ab heute ist die o.g. Cairngorm Präsentation von der Adobe MAX in San Francisco als Video auf AdobeTV online (via: Ted Patrick ). Hier könnt Ihr sie selbst noch einmal verfolgen. Prädikat: Sehr lohnenswert!! [/NACHTRAG]
-Jens
www.websector.de
Prima Zusammenfassung. Schon lustig, wie auf einmal bei Cairngorm der Schwenk Richtung IoC etc. gemacht wird.
Hey Dirk: sollte nicht so in der Regel immer gearbeitet werden? Dependency Injection ist es ja letzten Endes deswegen, weil die Komponenten extern konfiguriert werden. Im Grunde genommen ist das aber die einzig adäquate Methode um Komponenten zu implementieren. Sie geben nach aussen nur Preis, was sie brauchen und verraten nicht mehr. Würde man in den Komponenten den ModelLocator verwenden, hat das die Nachteile
– es ist für Entwickler nicht transparent
– Wiederverwendbarkeit geht gegen null
– man schleppt immer dass gesamte Model der Anwendung mit sich herum
Mein Senf 😉
@Dirk: Ja, das ist wirklich interessant, wie jetzt bei vielen Flex-Frameworks IoC die Runde macht: Mate, Swiz, Spring Actionscript (ehemals Prana-Framework), jetzt auch noch Cairngorm, selbst bei PureMVC wird jetzt „injiziert“, zumindest bei dem Utility „AS3 StateMachine„.
Wie auch immer… Auf jeden Fall schön zu sehen, dass damit bei Cairngorm wenigstens ein Weg gezeigt wird, gegen die bekannte Singleton-Problematik anzugehen. Was ich aber immer noch vermisse, sind gute und vor allem aktuelle Code-Beispiele von den Cairngorm-Jungs selbst. Denke, das ist ein wichtiger Grund, warum soviel Schabernack mit Cairngorm angestellt wird…
-Jens
Hej Jens,
danke für die schöne Zusammenfassung.
Cheers
Jens
@Florian: na klar, sehe ich 100% auch so.
Durch die Diskussion in der Community bzgl. „Cairngorm ist aber sch… weil“ bzw. „Framework X ist aber besser als Framwork Y“ ist ja erst Fahrt in das Thema IoC und Cairngorm gekommen. Vorher hatte mal ja immer den Eindruck, dass (laut Adobe Consulting und dort insbesondere Herr Webster) Cairngorm so wie es ist total super sei. Was dabei dann rauskommt habe ich schon häufiger bei frustierten Kunden gesehen, die im Cairngorm Wust untergehen…
Im Projektalltag hat denke ich jeder ernsthafte Entwickler an dem Vorgehen gemäß „Cairngorm Lehrbuch“ zu Recht seine Zweifel und letztendlich passt man sich alles so an, wie es Sinn macht. Aber das ist dann eben was selbstgebautes (was ja ok ist) – ich habe die Erfahrung gemacht, dass viele Kunden sich da aber was „offizielles“ oder „richtiges“ wünschen, unabhängig davon, wie toll die eigene Lösung auch sein mag.
@Dirk: heisst das nun, die Dokumentation von Cairngorm war schlecht oder es wurde nur falsch benutzt?
Ich muss zugeben, ich habe mich nie wirklich mit Cairngorm befasst, da ich eher der Typ bin, der „domain-driven“ arbeitet und ich durch meinen Java Background auch lieber in Anlehnung an das IoC Pattern (mit einem leicten Schlielen auf Spring und get/set Injection) implementiert.
Ich glaube eines der Hauptprobleme ist, dass viele Frameworks über die Architektur stellen oder im schlimmsten Fall sogar denken, dass das Framework letzten Endes die Architektur darstellt. Das das Framework (oder ein anderes Framework) ist aber letzten Endes nichts anderes als eine von vielen Möglichkeit ist, eine vernünftiges Wiring/Infrastruktur für den Datenfluss der Architektur zu schaffen ist vielen glaube ich nicht klar.
Beste Grüße
„Alle weiteren Views werden ihre notwendigen Models injiziert“
Cairngorm bietet dafür aber keine Möglichkeit bzw. gibts irgendwo ein Beispiel wie das gemacht wird.
@Hannes: Nicht vom Begriff „injizieren“ irritieren lassen, ist nur eine 1 zu 1 Übersetzung vom englischen Original. Wenn ich Borre Wessel auf seinem Vortrag auf der 360Flex im letzten Jahr richtig verstanden habe, werden die benötigten Models zu den Views „durchgereicht“. Evtl. gibt es aber auch eine Möglichkeit einer echten Injektion ala IoC mit Hilfe von Spring Actionscript (ex Prana-Framework). Habe selbst aber Spring Actionscript noch nie benutzt.
Wie auch immer, persönlich finde ich die Geheimniskrämerei der „Cairngorm-Consultants“ um aktuelle Cairngorm-Trends, wie z.B. der Einsatz eines PresentationModels, sehr fragwürdig. Hier z.B. ein Frage dazu, die von Steven Webster nie ganz geklärt wurde. Aber vielleicht liegt es daran, dass die Jungs ihr Cairngorm Buch gut verkaufen wollen (siehe dazu 4. Kommentar im Beitrag von Alistair McLeod), welches für Frühjahr 2009 angekündigt ist. Mal sehen, wer so lange warten kann oder doch lieber auf die besser dokumentierten Framework-Alternativen zurückgreift 😉
-Jens
@Jens @Hannes Genau die Idee mit dem Injekten des PresentationModels in den View beschreibt Christophe Herreman in diesem Blogeintrag http://www.herrodius.com/blog/158 ganz unten. Viel Spass
Sorry, dass ich hier eine generell Frage zu Cairngorm poste… mag deplaziert aussehen… nur bin ich langsam ratlos…
zur Frage:
Wir sind gezwungen mehrere Cairngorm Komponenten innerhalb einer App zu nutzen… Ergo meherere Komonenten (einzelne Cairngorm Konstrukte mit jeweiligen views, models, controllers) müssen miteinander kummunizieren…
Wie geschiet dies?
Im idealfall sind Komponenten ja von einander abgeschottet… also weiss eine Komponente nicht über die Existenz der anderen…
Wie tausche ich daten zwischeinanander aus?
Kann ich dafür normale Custom Events nutzen um die Daten von einer Komponente über die HauptApp zu anderen Komponente durchzuschleifen?
Oder sollte ich ich die Referenz zu einem super modell an alle komponenten veregeben damit jene nur dieses updaten… downside wäre hier das VO’s geshared werden müssten… das wäre dann aber nicht mehr Komponenten konform….
Falls einer den Durchblick hat bitte ich um Feeback… da das Internet zu diesem Thema wirklich keine Informationen bietet…
Universal Minds bieten Ansätze – jedoch ist das Thema Komponenten in Cairngorm anscheinend nicht wichtig genug für die Welt – Dafür hab ich aber schon 800 Dokus über das das Einlesen von Twitter Feeds per cairngorm gefunden… was für ein scheiss…
DANKE FÜR HELP
MO