BDD dein MVC

Vor ca. zwei Wochen habe ich mit dem ASP.NET MVC Framework im Rahmen eines verteilten Architektur-Prototypen begonnen. Ich war ich natürlich gespannt, ob sich mit dem MVC Framework auch nach BDD entwickeln lässt. Dies ist schließlich das Versprechen des MVC-Teams: Testbarkeit.

Ich kann sagen, dass nicht zu viel versprochen worden ist. Die Arbeit mit dem MVC Framework und die Erstellung einer Web-UI damit lässt sich problemlos mit Behavior Driven Development durchführen. Nachdem Albert schon einige seiner Erweiterungen vorgestellt hat, möchte ich mich dem anschließen. Davon abgesehen ist dies ein guter Zeitpunkt, einmal Top-Down einen Controller mittels BDD zu entwickeln und damit BDD an einem konkreten Beispiel zu demonstrieren.

Eingesetzte Frameworks

Zunächst einmal ist es wohl fast Pflicht das Projekt MvcContrib herunterzuladen, da es viele “fehlende” Erweiterungen mitbringt. Fehlend ist dabei in Anführungszeichen, weil sich das MVC Framework durch sehr gute Erweiterbarkeit auszeichnet: Factories für Controller, Routen und auch die komplette Render-Engine lassen sich austauschen. MvcContrib bringt eine Reihe von fertigen Implementierungen für IoC-Container (Castle Windsor, Spring.NET, …) und auch Render-Engines (Brails, NHaml, …) mit. Als Render-Engine setzte ich ASP.NET ein, Windsor ist mein IoC Container der Wahl.

Darüber hinaus kommt für Unit- und Integrationstests xUnit mit Björns xUnit.BDDExtensions zum Einsatz.

Entwicklung eines Controllers anhand einer Userstory

Für diesen Artikel habe ich eine Userstory gekürzt: Wenn der Anwender die Webseite “Index” aufruft, soll ihm “alle” gespeicherten Produkte auf der View “Index” angezeigt werden.

Zunächst erstellen wir also eine Specification für diese Userstory. Hier empfiehlt es sich Björns Templates für den Resharper zu installieren. Eine Specification spiegelt immer genau einen Kontext einer Userstory wieder. Diese Specification erzeugt einen ShopController (zunächst ohne weiteren Kontext). Bisher existiert der ShopController nicht. Diesen legen wir dann an. Damit haben wir in unserer Specification vorerst alles arrangiert (der Arrange-Teil von AAA). Wir können die Specification nun ausführen. Nun fügen wir Verhalten hinzu (der Act-Teil von AAA): die Aktion “Index” wird aufgerufen. Diese aufgerufene Methode des System-Under-Test fügen wir nun in die Klasse ShopController ein. Nun kompiliert die Specification wieder und wir können diese wiederum ausführen. Nun ist es an der Zeit, Beobachtungen einzufügen (der Assert-Teil von AAA). Nach der Erstellung einer Beobachtung in der Specification führen wir diese aus (Resultat: Failure, Rot), danach implementieren wir soviel, bis die Specification wieder grün wird. Anschließend fügen wir inkrementell weitere Beobachtungen ein und erfüllen diese wie beschrieben.

Im optimalen Fall beschreibt eine Userstory immer genau einen Kontext, andernfalls müsste diese noch feiner zerlegt werden. Eine Specification entspricht wie bereits gesagt genau einem Kontext, der sich im Namen der Specification samt Beschreibung der Handlung widerspiegelt. Unüblich für C# und Ähnliche ist die Verwendung von Unterstrichen anstelle von Camel Casing. Trotzdem sollte dieser Stil genutzt werden, da er die Lesbarkeit auch in den Testrunnern und Methoden-Übersichten deutlich erhöht.

Bei der Erstellung des Kontext werden auch alle Abhängigkeiten initialisiert. Dabei versteckt die Basisklasse für Specifications die Mechanik (Mocking Framework, …) zur Erzeugung von Abhängigkeiten. Speziell für das MVC Framework habe ich die Basisklasse “ControllerInstanceContextSpecification” angelegt, da diese die Testhelper von MvcContrib versteckt, um einen Controller vollständig zu initialisieren.

Als Beobachtungen sind grundsätzlich Überprüfung des Ergebnisses oder Überprüfung von Methodenaufrufen und Exceptions denkbar. Für Ergebnisse werden diese nach der Handlung in einem privaten Feld der Specification gespeichert (hier: “result”). Für die Überprüfung von Methodenaufrufen und Exceptions ist ein Mocking Framework nötig, das den AAA-Stil unterstützt (zB Rhino.Mocks). Ältere Record-Reply Varianten funktionieren damit nicht. Zur erhöhten Lesbarkeit werden Assertions auf Werten und Methodenaufrufen hinter besser lesbaren Extension-Methods versteckt. Beobachtungen erfüllen somit auch die Forderung, pro “Test” nur eine Assertion auszuführen – andernfalls sind Fehlschläge in Tests schwerer zu lokalisieren.

Der beschriebene Quelltext

Hier nun die komplette Specification:

   1: [Concern(typeof (ShopController))]
   2: public class when_a_shop_controller_handles_the_index_action :
   3:     ControllerInstanceContextSpecification<ShopController>
   4: {
   5:     private IDiscService discService;
   6:     private ActionResult result;
   7:  
   8:     protected override void EstablishContext()
   9:     {
  10:         discService = Dependency<IDiscService>();
  11:  
  12:         discService.WhenToldTo(x => x.FindDiscsForSale())
  13:             .Return(new List<Disc>
  14:                         {
  15:                             new Disc(3698, "U2 / All the best", 
  16:                                      2003,
  17:                                      "classical"),
  18:                         });
  19:     }
  20:  
  21:     protected override ShopController CreateSut()
  22:     {
  23:         return new ShopController(discService);
  24:     }
  25:  
  26:     protected override void Because()
  27:     {
  28:         result = Sut.Index();
  29:     }
  30:  
  31:     [Observation]
  32:     public void should_redirect_to_search_view()
  33:     {
  34:         result.should_be_rendered_view("Index");
  35:     }
  36:  
  37:     [Observation]
  38:     public void should_retrieve_discs_from_disc_service()
  39:     {
  40:         discService.AssertWasCalled(x => x.FindDiscsForSale());
  41:     }
  42: }

Die Implementierung des Controllers sieht dann wie folgt aus:



   1: [HandleError]
   2: public class ShopController : Controller
   3: {
   4:     private readonly IDiscService service;
   5:  
   6:     public ShopController(IDiscService service)
   7:     {
   8:         this.service = service;
   9:     }
  10:  
  11:     public ActionResult Index()
  12:     {
  13:         /* ...
  14:         */
  15:  
  16:         var model = new ShopViewModel();
  17:         model.Discs = service.FindDiscsForSale();
  18:         return View("Index", model);
  19:      }
  20: }

Zu guter letzt ist noch die neue Basisklasse für Instance-Specifications nötig. Diese ist speziell für Controller des MVC Frameworks und versteckt die Mechanik der Testhelper von MvcContrib bei der Initialisierung eines Controllers.



   1: public abstract class ControllerInstanceContextSpecification<T> : InstanceContextSpecification<T>
   2:     where T : Controller
   3: {
   4:     protected override void InitializeSystemUnderTest()
   5:     {
   6:         base.InitializeSystemUnderTest();
   7:         new TestControllerBuilder().InitializeController(Sut);
   8:     }
   9: }

.NET Open Space 2008 rekapituliert

PICT2600Mit ganz viel Verspätung kommt nun also meine Zusammenfassung des .NET Open Space 2008 in Leipzig. Zunächst ist zu sagen, dass Leipzig wirklich eine schöne Stadt ist. Dank eines ortskundigen Teilnehmers konnten wir am Freitag einige tolle Ecken von Leipzig besichtigen (Auerbachs Keller war natürlich ein Muss). Die Party am Freitag Abend war eine angenehme, lustige Runde zum Kennenlernen.

 

 

 

 

PICT2608Der Samstag startete dann mit einer Erklärung des Open Space Konzeptes durch Stefan und der anschließenden Planung der Sessions. Der Versuch, demokratisch jedem Wunsch (und jeder Kollisions-Vermeidung) bei den Sessions beizukommen stellte sich im Laufe des Tages noch als Problem heraus – es dauerte einfach zu lange.

 

Die erste Session zum Thema “Testen, Test-First, Testbarkeit” interessierte anscheinend fast alle Teilnehmer. Dies führte schnell zur Wandlung in eine (sehr gute) Einstiegs-Veranstaltung und schließlich dann auf die Frage:

Wie verkaufe ich das ans Management?

Dank Björn und Gabriel kam die Diskussion von TDD schnell zu BDD.

Die zweite Session des Tages (die ich besuchte) war ein großer Pool von xDDs: “DDD, BDD, FDD, MDD, MDA, MDSD”. Abgesehen von der Tatsache, dass die Session einfach zu viele Themen gruppierte, gab es zunächst eine Einführung in einige der genannten xDDs. Leider kam die Diskussion zu “xDD – Wieviel wovon?”, die Lars und ich uns gewünscht hätten, nicht zum Zuge. Dafür gab es schnell mal wieder die Frage

Wie verkaufe ich das ans Management?

Überhaupt schien dies für manche ein zentraler Aspekt der Konferenz (oder ihrer Probleme) zu sein: Wie lassen sich aktuelle Entwicklungsmethoden, Ansätze, Philosophien verkaufen? Manch einer soll über TDD auch sagen, dass es einfach zur Professionalität eines jeden Entwicklers gehört, maschinell überprüfbare Tests zu schreiben… Ich hätte gedacht, dass die treibenden Kräfte hinter dieser Dauer-Frage sich schließlich doch zu einer separaten Session treffen, um dies ausführlich zu diskutieren – leider kam es dazu nicht. Somit blieb die Frage weiterhin immer offen im Raum herumschwirren.

PICT2606Open Space wird auch die organisierte  Kaffeepause genannt. Und in den Pausen von dieser organisierten Pause ergaben sich dann einige sehr Interessante Diskussionen unter anderem mit Lars und Björn über Architektur aus der ALT.NET-Sicht und “Von Java lernen”.

In der letzten Session, die ich am Samstag besuchte, war das Thema “ORMs – NHibernate vs LLBLGen”. Es stellte sich schnell heraus, dass hier datenzentrische auf objektzentrische Entwickler trafen, und die wahl der Tools davon maßgeblich geprägt ist. Heftig diskutiert war auch die Frage nach der Einstiegsschwelle von NHibernate. Einige Ehrfahrungsberichte brachten dann doch nahe, dass die grunsätzliche Schwelle niedrig ist – komplizierte Szenarien aber einfach von ihrer Natur her kompliziert sind.

Der erste Tag zeigte, dass die Organisation der Konferenz super, ja (fast) perfekt war. Das Konzept funktionierte wunderbar. Zu meiner Überraschung war das mehrheitliche Interesse doch im Themenbereich ALT.NET angesiedelt (neben den Bereichen Mobile und Softskills).

Am Abend setzten sich die Diskussionen in kleineren Runden auf der Party fort.

PICT2622Der Sonntag stand zunächst ganz im Zeichen einer schnelleren Session-Aufteilung (Continuous Improvement !) und einer Live-Coding Session zur Demonstration von BDD und Pairprogramming. Diese wurde von Björn und Gabriel durchgeführt. Für mich zeigte sich wieder einmal, dass BDD unschlagbar gut zu vermitteln ist - im Gegensatz zu reinem, alten TDD. Auch die Art der Präsentation (Pairprogramming), wie sie bereits von JP Boodhoo in Bonn demonstriert wurde, scheint einfach gut zu funktionieren.

PICT2629 Später kam es dann zur ersehnten Session zum Thema “ALT.NET Architektur – Von Java Lernen”. Diskutiert wurden zunächst ein typischen Szenario einer verteilten Anwendung. Das Szenario waren drei typische Services für Warenkorb, Kundenmanagement und Bestellungsbearbeitung. Anschließend stellte ein Teilnehmer seine .NET Architektur vor und ich habe mit Lars die gängigen Konzepte im Java Enterprise Bereich und auf  Java Application Servern vorgestellt. Offenkundig war die starke Tendenz, Skalierbarkeit in der Performanz durch Asynchronität und Messaging zu realisieren.

Als Ergebnis der Diskussion würde ich sehen, dass wir im ALT.NET Umfeld gerade erst noch am Anfang der Diskussion stehen. Eigentlich bauen alle irgendwie Enterprise Architekturen in .NET, nur scheint kaum jemand darüber zu sprechen (und die MS Guidelines sind von 2005…), gerade über komplexere Themen wie Skalierbarkeit, Sicherheit, … Wir können und müssen wohl noch einiges vom Java Enterprise Bereich lernen. Mehr dazu demnächst…

PICT2633

Technorati Tags: ,

.NET Open Space 2008, Twitter

Morgen geht’s los zum .NET Open Space 2008 in Leipzig. Wer mir folgen möchte, kann dies nun auch auf Twitter tun:

http://www.twitter.com/sjancke

Ich bemühe mich das ganze dort (und hier) zu dokumentieren – wir werden sehen ob’s klappt.

DDD – Vortrag in Köln (UPDATE)

Hallo,

kurzfristig hat sich der Ort der Veranstaltung geändert. Die DNUG trifft sich morgen (07. Oktober 2008), 19h nun hier:

Grünfeld an der Brüsseler Straße 47.

Siehe dazu auch diese von Albert erstellte Karte.

Wie Albert schon angekündigt hat, gebe ich am 07. Oktober 2008 einen Vortrag zum Thema Domain Driven Design in der DNUG Köln.

Allgemein ist die Konstruktion von Modellen ein effektives Mittel, um die Komplexität eines Problems zu beherrschen. Domain Driven Design setzt als Basis unserer Entwicklungsprozesse die Fokussierung auf die Domäne und ihre Modelle, uneingeschränkt durch technische Komplexität, die heutige Projekte meist überlädt. Das wichtigste Werkzeug ist dabei die allgegenwärtige Sprache als Modell der Domäne und der Kontext, in dem sich das Modell einer Domäne befindet.

Der Vortrag gibt eine Einführung in das Thema und einen Überblick über fortgeschrittenere Techniken:

  • Voraussetzungen
  • Allgegenwärtige Sprache
  • Grundlegende Bausteine als Basis der Sprache und Orientierungshilfe
  • Modelle reichhaltiger gestalten
  • Modelle durch ihren Kontext trennen und integrieren
  • DDD in der Praxis: gängige Probleme und häufige Fragen

Technorati Tags: ,

Angefangen hat Aspektorientierug mit Gregor Kiczales und seinem damaligen Forschuntsteam bei Xerox PARC. Seine Arbeit an “Metaobject Protocols” führte zur Erkenntnis, dass vor allem die Modularisierung von sog. “cross-cutting concerns” die größte Verbesserung brachte. Bei Xerox entstand dann AspectJ (welches heute ein Projekt im Eclipse-Bereich ist). AspectJ ist derzeit wohl die am meisten verbreitete AO-Sprache und vielleicht die einzige die wirklich in Produktion eingesetzt wird. Daneben existieren eine vielzahl von AO-Ansätzen durch Container wie das Spring-Framework oder Enterprise Java Beans (EJB), die eine weite Verbreitung gefunden haben und einer großen Zahl von Entwicklern einen einfachen Zugang zu AO-Technologie bieten.  Um zu verstehen, warum der Schritt zu Aspektorientierung natürlich und logisch ist, müssen wir zunächst verstehen, was treibende Kraft in der Weiterentwicklung der verschiedenen Paradigmen ist.

1974 war es Edsger W. Dijkstra, der in seinem Artikel “On the role of scientific thought” den Begriff “separation of concerns” prägte:

Let me try to explain to you, what to my taste is characteristic for all intelligent thinking. It is, that one is willing to study in depth an aspect of one's subject matter in isolation for the sake of its own consistency, all the time knowing that one is occupying oneself only with one of the aspects.

[..] But nothing is gained --on the contrary!-- by tackling these various aspects simultaneously. It is what I sometimes have called "the separation of concerns", which, even if not perfectly possible, is yet the only available technique for effective ordering of one's thoughts, that I know of. This is what I mean by "focussing one's attention upon some aspect": it does not mean ignoring the other aspects, it is just doing justice to the fact that from this aspect's point of view, the other is irrelevant.

(30th August 1974, Prof. Edsger W. Dijkstra)

Dijkstra argumentierte, das wissenschaftliches Denken in der Entwicklung von Programmen fehlte, jedoch nötig sei um gute, fehlerfreie Programme zu konstruieren. Spätestens seit der erneuten Definition durch Chris Reade in seinem Buch “Elements of Functional Programming” gilt die Trennung der Anliegen als nötig, um die Komplexität eines Systems in den Griff zu bekommen. Die “Separation of concerns” kann als Geisteshaltung hinter dem Ziel der Modularisierung betrachtet werden. Damit ist aber noch nicht geklärt, was genau ein “concern” denn genau ist. Man könnte einen concern als jede Anforderung und jedes Anliegen an eine Software definieren, und dies scheint die anerkannte Definition zu sein. Dabei kann ein concern so generell wie “Interaktion mit einer Datenbank” sein, aber eben auch eine spezielle Berechnung detailliert vorgeben.

Vor dem Problemen der nötigen Modularisierung stehen wir aber nicht alleine. Andere Branchen haben es auf ihre eigene Art gelöst. Architekten scheinen separate Pläne für Wasserversorgung, Stromleitungen, Abflüsse, Lichtinstallationen und natürlich die Konstruktion an sich anzufertigen. Darüber hinaus ist die Innenarchitektur ein  ganz eigenständiger Beruf.

Modularisierung ist auf der einen Seite zwingend notwendig, um die Komplexität heutiger Anforderungen in Teile zu zerlegen und so zu reduzieren, damit ist jedoch unklar, wie weit wir die Modularisierung treiben müssen. Die Professorin Carliss Y. Baldwin von der Universität Harvard hat die Modularisierung von einem ökonomischen Blickpunkt aus untersucht und kam zu dem Schluss, dass Modularisierung eine treibende ökonomische Kraft ist, die ganze Märkte (zB den PC-Markt seit Einführung des modularisierten IBM-kompatiblen PCs) umkrempeln kann. Darüber hinaus hat sie auch die Modularisierung mittels Aspekten und den Optionswert von Aspekten untersucht und war Keynote-Speakerin bei der Konferenz AOSD 06. Interessant finde ich an dieser Stelle, dass auch Kent Beck bei seinem Plädoyer für möglichst späte Entscheidungen im eXtreme Programming mit Optionswerten argumentiert hat.

Alle Paradigmen, die bisher zu Felde geführt wurden, von der Strukturierten Programmierung über Prozedurale, Funktionale bis hin zur Objektorientierten Programmierung hatten ein Ziel: bessere Modularisierung. Dabei hat jedes Paradigma seine eigenen Konzepte, ein Modul abzubilden (…, Funktionen, Objekte) kreiert. Dabei wurde jedoch eine Gruppe von Anliegen stets ausgeschlossen, weil sie bei der Dekomposition in Module dieser Paradigmen über Module hinweg verstreut waren und und somit faktisch unsichtbar wurden.  Die genannten Paradigmen sind nicht im Stande, diese Gruppe von Anliegen selbst zu modularisieren. Der Grund dafür ist die einfache Tatsache, dass es immer zu einer Zahl von Anliegen einige Anliegen gibt, die andere kreuzen (darauf komme ich noch zurück).

Ich denke es ist klar, dass ich auf cross-cutting concerns hinaus will. Zu oft ist aber versucht worden AO zu verkaufen und dabei die “Neuen” mit einer Reihe von Fachbegriffen zu überladen. Da es sich bei der Aspektorientierung um einen völligen Paradigma-Wechsel handelt (der dennoch rückwärts kompatibel ist), halte ich es für eine gute Idee, vorerst auf genau diese Fachwörter ("buzzwords” ?) zu verzichten. Ich denke dieser Ansatz wird auch durch die Aussage von Gregor Kiczales gestützt, dass die Geisteshaltung von Aspektorientierung weitaus wichtiger ist, als die derzeitigen technischen Umsetzungen und ihre spezielle Ausprägung der Fachbegriffe. Würde man diese nutzen wollen, so müsste zunächst ihre allgemeine Semantik erklärt werden. Dies wird fast nie getan und erscheint für eine Einführung auch zu fortgeschritten.

Im Jahre 2004 stellte Ted Neward, bei einer Podiumsdiskussion zum Thema AOP auf der Konferenz “The Server Side Symposium”, eine Aufgabe: Aspektorientierung zu erklären, ohne die gängigen “buzzwords” zu verwenden. Der Projektleiter des AspectJ-Projektes, Adrian Colyer (heute auch für SpringSource tätig) antwortete mit seinem Artikel “The Ted Neward Challenge (AOP without the buzzwords)”. Seine Argumentation basiert auf der Annahme, dass eine echte Trennung der Anliegen nur erreicht werden kann, wenn das Verhältnis von Konzepten zu Implementierungen genau 1:1 ist, also ein Konzept an genau einer Stelle in der Software Implementiert ist.

Nehmen wir uns ein einfaches Problem (welches auch von Gregor Kiczales untersucht wurde): Eine Zeichentafel (Canvas) und eine Vielzahl verschiedener geometrischer Objekte (Shapes). Die verschiedenen Shapes (Dreieck, Viereck, Kreis, Oktaeder, …) verwalten ihre Eigenschaften und ihr Zeichenverhalten selbst. Wir modellieren sie als Objekte. Ebenso den Canvas. Ein weiteres Anliegen ist auch die Benachrichtigung des Canvas, wenn ein Shape sich verändert. Im Allgemeinen würde man dieses Anliegen durch eine Subject-Observer Beziehung zwischen Canvas und den verschiedenen Shape-Objekten implementieren. Bei allen Änderungen benachrichtigen die verschiedenen Shape-Objekte den Canvas. Das Anliegen der Benachrichtigung ist damit aber nicht mehr eigenständig modularisiert, denn alle verschiedenen Objekte (oder Klassen von Objekten) implementieren die Benachrichtigung auf ihre eigene Art. Wir haben also ein Verhältnis Konzept : Implementierung von 1 : n. Umgekehrt haben wir in einem Objekt nun mehr als ein Konzept implementiert und haben hier ein Verhältnis Konzept : Implementierung von n : 1. Die Krux liegt darin, dass wir schon bei einem sehr einfachen Beispiel ein Anliegen nicht mehr richtig Modularisieren konnten, weil es ein übergreifendes Anliegen ist. Skaliert man das Beispiel auf ein durchschnittlich großes System, ist die ganze Problematik daran vorstellbar.

Nun ließe sich erwidern, dass vielleicht eine andere Art der Dekomposition das Problem gelöst hätte. Dies ist in der Forschung untersucht worden und derzeitiger Stand ist anscheinend, dass es nicht möglich ist. Das Problem wird “Tyranny of the dominant decomposition” genannt. Dies möchte ich anhand eines Beispieles illustrieren: Es soll eine Zeit gegeben haben, in der wir statt MP3s jede Menge CDs im Regal stehen hatten. Wir wollen aus den CDs schnell einige zu einem speziellen Genre suchen. Dazu könnten wir sie nach Genre sortieren. Allerdings würden wir auch gerne schnell CDs nach einem Namen suchen. Vielleicht wäre es also besser, die CDs nach Namen zu sortieren. Dann könnten wir aber nicht mehr schnell nach Genre ähnliche CDs suchen. Die Lösung scheint greifbar: wir sortieren nach Genre und jedes Genre wiederum nach Namen. Damit gehen wir den Kompromiss ein, dass wir nicht sehr schnell nach Namen suchen können, aber wir können sehr gut nach Genre suchen, selbst wenn wir zunächst eine spezielle CD gesucht haben. Das Anliegen “Genre” ist also hier die dominante Dekomposition über dem Anliegen “Namen” (verkürzt gesagt). Kommt nun aber noch das Anliegen hinzu, CDs zu einem Jahr zu finden, haben wir ein Problem, egal welche Dekomposition wir als dominant wählen. Es gibt also nur einen Ausweg: wir müssten sowohl die Suche nach Genre, als auch die Suche nach Namen und auch die Suche nach Jahren eigenständig Modularisieren. Dies scheint mit den Mitteln Plazierung der CDs im Regal nicht möglich, wir brauchen also einen Paradigma-Wechsel.

Das Beispiel der CD-Sortierung zeigt nicht nur die Existenz von übergreifenden Anliegen aus der Problemdomäne heraus. Das Beispiel zeigt vor allem im Gegensatz zum Zeichenbrett, dass übergreifende Anliegen “mehrdimensional” sind und die Zahl der Dimensionen “unbegrenzt” sein kann. Diesem Umstand hat auch IBM mit der Forschung im HyperJ-Projekt Rechnung getragen.

Für Viele ist dennoch Aspektorientierung derzeit vor allem eines: Aspektorientierte Programmierung (AOP), mit einem starken Hang eine Sache Namens “Logging” besonders schön zu lösen. Dabei ist der eigentliche Witz am “Hello world”-Beispiel der AOP die Tatsache, dass dort Tracing modularisiert wird. Innerhalb von Experimenten beobachtet wurde, das in vielen Fällen richtiges Logging – die Präsentation von Debug und Context-Informationen – eigentlich kein cross-cutting concern ist, weil für jeden Context die Anforderungen völlig unterschiedlich sind. Eine Ausnahme bildet vielleicht die einheitliche Protokollierung von Fehlern im System. Darüber hinaus scheint für Viele die Formel cross-cutting = nicht-funktional zu gelten. Das auch diese Reduktion der Aspektorientierung zu kurz greift, zeigt die Tatsache, dass erfahrene AO-Experten in der Regel den wahren Wert von AO bei funktionalen, zur Domäne gehörigen cross-cutting concerns sehen. Nicht zuletzt, weil nicht-funktionale, Infrastruktur-Anliegen heute von Containern (EJB, Spring, …) hinreichend gut modularisiert wurden. Gleichzeitig scheint mir hierher die Popularität der (falschen) Formel cross-cutting = nicht-funtional zu kommen. Eben weil die obigen Beispiele mit dem Zeichenbrett oder der CD-Sortierung keinerlei nicht-funktionale Anliegen enthält, mag ich diese besonders. Sie zeigen zum einen, dass bereits sehr simple Domänen cross-cutting concerns enthalten. Zum anderen ist aber auch sichtbar, dass diese meist aus der Problemdomäne entstammen und (gefühlt) die “kleine” Zahl der nicht-funktionalen Infrastruktur Anliegen übersteigt.

Heute, ca. 10 Jahre nach der “Erfindung” der AO ist die Aspektorientierte Programmierung weitgehend stabil und wird produktiv eingesetzt (zumindest im Falle von AspectJ). Forschung findet natürlich auch noch hier statt, scheint sich aber derzeit vor allem auf die Auswirkungen von AO im Bereich des Software Engineerings zu konzentrieren: Requirements Engineering, Refactoring, Patterns, Productlines, Tooling und nicht zuletzt “Aspect Mining”. Diese Bereich bieten trotz akuter Forschung trotzdem bereits nutzbare Ergebnisse, die auch Anwendung zu scheinen finden. So gibt es einige nützliche Ergebnisse, bei der Anwendung von AspectJ zur Implementierung von Objektorientierten Patterns in einer Pattern-Library. Die Erweiterung von Use-Cases hin zu sog. “Use-Case slices” und die damit einhergehende 1:1 Implementierung der Kern-Usecases durch Objekte und der Varianten/Extension Points und anderen Usecases durch Aspekte ist sogar als Buch verfügbar. Hier können auch einfache Angriffspunkte zur Feature-Konfiguration im Sinne von Productlines gesetzt werden.

Für “Joe Developer” (Zitat aus dem se-radio.net) scheinen aber viele dieser Techniken/Prozesse/Tools und Ergebnisse im Zusammenhang mit AO bisher unsichtbar gewesen zu sein. Um so mehr ist es an der Zeit, diese Dinge genau zu Beleuchten und statt AspectJ-Tracing-Tutorials lieber “Best practices” und mögliche Einsatzgebiete zu benennen. Den Syntax einer Sprache oder die Details einer Technologie lassen sich schließlich gut aus Büchern und Dokumentation entnehmen. Die Einsatzmöglichkeiten und gute Vorgehensweisen einer Technologie entstammen aber der Erfahrung und dem Umgang damit. Sie können eigentlich nur von den bereits Erfahrenen vermittelt werden, oder aber durch viele Experimente (und Fehlschläge) selbst erlernt werden. Dabei bevorzuge ich eindeutig den ersten Weg und versuche von den Experten zu lernen.

Im Interview von Gregor Kiczales durch Markus Völter (auf se-radio.net) spekulierten schließlich beide darüber, dass zur Annahme des OO-Paradigmas 20 Jahre nötig waren, die Annahme von AO aber bereits nach 10 Jahren sehr weit fortgeschritten ist und die Zukunft positiv aussieht. Nicht zuletzt kommen wohl die meisten heute schon damit in Kontakt, wenn sie Middleware-Plattformen wie EJB-Container oder das Spring-Framework einsetzten.

Zum Schluss möchte ich noch darauf zu sprechen kommen, dass ich bisher nur für Aspektorientierung plädiert habe, nicht aber für den Einsatz einer speziellen AOP-Technologie. Auch habe ich weder nur für AO-Sprachen noch gegen Container-AOP (Spring.AOP, Method interception, …) plädiert. Solche Entscheidungen sind schließlich nicht allgemein entscheidbar, da sie immer von den speziellen Anforderungen, Budgets, etc.. abhängen. Auch die Frage, wie fein Aspekte granuliert werden sollen steht im Raum und beeinflusst insbesondere den Einsatz von “Method interception”, Spring.AOP, AspectJ oder auch eine Kombination dieser. Der Grad der technischen Umsetzung und Einsatz von AO-Technologie ist nicht zuletzt auch durch die “Adoption strategy” gesteuert. Hierzu gibt es wiederum allgemeine Empfehlungen, auf die ich aber ein anderes Mal eingehen möchte und werde.

Nachtrag: Ich habe gestern gesehen, dass Stefan Lieser die Thematik “Tyranny of the dominant decomposition” an einem anderen, aber ebenso schönen Beispiel erläutert hat: Ein Dokument mit Elementen (Text, Absätze, …) und dazu orthogonal die Frage der Formatierung.

Technorati Tags: ,


 

Copyright 2006| Blogger Templates by GeckoandFly modified and converted to Blogger Beta by Blogcrowds.
No part of the content or the blog may be reproduced without prior written permission.