Follow my new blog

Mittwoch, 14. Oktober 2009

Stirnrunzeln über das Neueste von Microsoft seit geschnitten Brot [OOP 2010]

Grad scheint Microsoft wieder mal “the best thing since sliced bread” erfunden, wie es scheint. Der Reactive Framework (Rx) zaubert jedenfalls einiges breites Grinsen auf Gesichter bei Microsoft, hier der Erfinder des Ganzen, Erik Meijer, in einem Interview über Rx.

image
(Achtung: Dieses Interview ist auf sehr hohem Abstraktionsniveau! Eine Beschreibung von Rx für Praktiker sucht man hier vergebens.)

Den schätze ich eigentlich sehr, nicht nur für sein früheres “brainchild” Linq. In der letzten Zeit zaubert Erik Meijer aber zumindest mir kein beseeltes Grinsen mehr auf Gesicht, sondern Stirnrunzeln. Da war zuerst das ganz unglückliche Project Volta, welches fundamentalen Erkenntnissen zu verteilten Anwendungen zuwiderlief und jetzt zurecht offline ist. Und jetzt kommt der Reactive Framework.

Was ist der Rx? Das kann man hier und hier recht gut lesen. Ich möchte das jedoch lieber nicht selbst wiedergeben. Denn für mich besteht das Problem darin, dass ich neues Vokabular für etwas Altes benutzen müsste. Meine Kritik am Rx ist: es ist eben keine tolle neue Erfindung seit geschnitten Brot, sondern etwas lange Bekanntes in aufgehübschtes Gewand kleidet.

Mit Rx ist Microsoft aus meiner Sicht nur über Complex Event Processing (CEP) gestolpert. Wenn Erik Meijer die Rx-Interfaces als komplementär zu IEnumerable/IEnumerator ansieht und damit Linq-Queries auf Strömen von Events visioniert, dann ist das nichts anderes als eben CEP: statt auf fixen Daten Queries zu fahren, liest man Ströme von Daten ein und verarbeitet sie mit Queries. Das ist nicht neu, das ist kein Hexenwerk.

Wer wirklich einmal ausprobieren will, was man mit einer Abfragesprache auf Event-Strömen tun kann, der kann mit NEsper spielen: http://esper.codehaus.org/. Das ist (zusammen mit seinem Java-Bruder Esper) ein enterprise ready Open Source CEP Framework. Hier ein kurzes Beispiel für die Ermittlung des Durchschnittspreises “vorbeirauschender” Bestellungen (OrderEvent) innerhalb von jeweils 30-Sekunden-Fenstern.

select avg(price) from org.myapp.event.OrderEvent.win:time(30 sec)

Das ist grundsätzlich nichts anderes tut Rx (s. dazu das Beispiel zur Generierung von Mouse Drag Events hier).

Oder nehmen wir einfach nur Datenflüsse (data flows). Wo ist denn der Unterschied zwischen Rx, das nun wundersamerweise z.B. Mausereignisse als abfragbare Ereignisflüsse sieht? Oder als Flüsse, auf denen man Ereignisbehandlungsroutinen notieren kann. Tut mir leid, da ist nichts neues für mich dabei. Wenn ich im etablierten Paradigma data flow denke, dann ist das etwas uraltes und kann mit heutigen Mitteln bewältigt werden.

Hier ein einfacher Event-Strom mit “Event-Handler”:

new[] {1, 2, 3}.Subscribe(Console.WriteLine);

Der “Event-Handler” braucht nur das altbekannte IEnumerable:

static class EnumExt

{

    public static void Subscribe<T>(this IEnumerable<T> eventStream,
                                    Action
<T> handleEvent)

    {

        foreach (T e in eventStream)

            handleEvent(e);

    }

}

Aber damit nicht genug! Man kann auch IEnumerable-Ströme zusammenstecken zu “Pipes and Filters”. Das ist dann ein Flow. Warum nicht aus einer Zahlenliste die ungeraden herausziehen und negieren?

Zahlen –> UngeradeZahl | ZahlNegieren –> Liste der negierten ungerade Zahlen

Die Formulierung in Code ist denkbar einfach:

new[] {1, 2, 3, 4, 5, 6, 7}
    .Where(n => n%2 != 0)
    .Transform(n => -n)
    .Subscribe(Console.WriteLine);

Und wenn noch ein Schritt dazukommen soll – z.B. die Quadratur der ungeraden Zahlen –, dann wird der einfach eingefügt:

new[] {1, 2, 3, 4, 5, 6, 7}
    .Where(n => n%2 != 0)
    .Transform(n => n*n)
    .Transform(n => -n)
    .Subscribe(Console.WriteLine);

Die Transformationsmethode ist straightforward eine Extension Method wie oben Subscribe():

public static IEnumerable<TOut> Transform<TIn, TOut>(
                 this IEnumerable<TIn> eventStream, 
                 Func<TIn, TOut> processEvent)

{

    foreach (TIn e in eventStream)

        yield return processEvent(e);

}

Wer will, kann sowas auch asynchron machen. Das habe ich schon in früheren Blogposts beschrieben:

http://ralfw.blogspot.com/2009/07/ccr-flows-asynchrone-prozesse-mit-der.html
http://ralfw.blogspot.com/2009/07/verstandnisvorteil-fur-flows.html

Flows habe ich aber natürlich nicht erfunden. Die sind alt. Hier eine Quelle, die das Paradigma schon in den 1970ern propagiert hat: http://jpaulmorrison.com/fbp/. Mainstream ist es aber nicht geworden, wie wir sehen. Schade. Denn in die Schritte in einem Flow steigern die Evolvierbarkeit von Software, finde ich.

Jetzt noch die Umsetzung von Mausbewegungen in einen Strom, den man abfragen kann:

public partial class Form1 : Form

{

    private readonly EventStream mouseMovements = new EventStream();

 

    public Form1()

    {

        InitializeComponent();

 

        this.MouseMove += this.mouseMovements;

    }

    …

Eine Klasse EventStream sorgt dafür, die Mausbewegungen (oder auch andere Events) in ein IEnumerable zu transformieren. Das kann man dann z.B. so durchlaufen:

this.mouseMovements.Events<MouseEventArgs>()
    .Where(args => args.X < 100 && args.Y < 100)
    .Subscribe(args => Console.WriteLine("{0}, {1}", args.X, args.Y));

Wie macht EventStream das? Die Windows Message Loop darf ja nicht aufgehalten werden. Es geht nur asynchron. Also rufe ich die Concurrency Coordination Runtime (CCR) zur Hilfe:

class EventStream

{

    public class Event

    {

        public object Sender;

        public EventArgs Args;

    }

 

    private Port<Event> events = new Port<Event>();

 

 

    private void EventListener(object sender, EventArgs args)

    {

        this.events.Post(new Event{Sender = sender, Args=args});

    }

 

 

    public IEnumerable<TEvent> Events<TEvent>() where TEvent : EventArgs

    {

        Event e;

        while (this.events.Test(out e))

            yield return (TEvent)e.Args;

    }

 

 

    public static implicit operator MouseEventHandler(EventStream stream)

    {

        return stream.EventListener;

    }

    …

}

Mit der impliziten Konvertierung kann ich den EventStream einfach an einen Eventhandler für die Mausbewegungen binden, ohne zu verraten, wer intern die Verarbeitung übernimmt.

Der Eventhandler schiebt dann jeden Event in einen CCR Port. Das ist sogar Thread-sicher. Und wenn ich die aufgelaufenen Events prozessieren will, dann hole ich sie mir über Events() als IEnumerable wieder heraus.

Alternativ könnte ich natürlich auch einen Eventhandler registrieren, der life auf neue Events reagiert und sie z.B. in einen asynchronen Flow einspeist. Dann könnte ich in einer Kette von asynchronen Schritten filtern, transformieren, reagieren. Auch da wären Where(), Transform() und Subscribe() wie oben in den synchronen Beispielen möglich.

Wo also ist das entscheidend neue beim Rx? Beats me. Ich kann nur die grübelnd die Stirn runzeln.

Ok, der Rx mag hier und da etwas einfacher machen, weil er schon Abstraktionen bietet, die ich vielleicht erst bauen muss/müsste. Das wäre ne nette Sache – aber deshalb hat Erik Meijer nun nicht gleich “the best thing since sliced bread” erfunden. Er steht nur in einer langen Tradition. Die zu erwähnen und weniger die Flügel zu schlagen, um nicht zuviel Hype-Staub aufzuwirbeln, das fänd ich angemessen.

PS: Oder übersehe ich hier die eigentliche Erfindung? Geht der brilliante Innovationshub an mir vorbei? Ich bitte um Erhellung.

Sonntag, 11. Oktober 2009

Fokussieren durch bezahlen [OOP 2010]

Wir zahlen zuwenig. Dieser Gedanke ist mir gestern gekommen. Ich hatte mit Google Reader meine RSS-Feeds durchstöbert, dann bei InfoQ geblättert und schließlich eine neue Zeitschrift zur Hand genommen, von der ich ein Probeexemplar bestellt hatte: NOVO argumente. Ganz normal hatte ich also im Überfluss an Lesestoff ein Bad genommen. Ganz normal hatte ich dabei cherry picking betrieben: nur, was mir auf Anhieb interessant erschien, las ich.

Hört sich doch eigentlich auch gut an, oder? Ist es nicht toll, wenn uns soviele Daten “at our fingertips” zur Verfügung stehen? Selbstverständlich. Das möchte ich auch nicht missen. Eine zivilisatorische Errungenschaft ersten Grades.

Und dennoch… Das Bad im Überfluss wollte mich nicht so recht erfrischen. Der Grund: Ich habe mich nicht fokussiert. Ich bin nicht tief gegangen. Ich habe mich nicht verstören lassen.

Meine Tochter hingegen hat nur eine sehr überschaubare Zahl an CDs und Kassetten mit Kindergeschichten wie Bibi & Tina oder Elea Eluander. Die hört sie wieder und wieder. Darin taucht sie tief ein, bis sie jede Einzelheit kennt und mit mir sogar arambolisch spricht. (Arambolisch ist die Sprache einer “Parallelwelt” bei Elea Eluander.)

Der Unterschied zwischen meiner Tochter und mir: Sie lebt im Mangel, ich im Überfluss. Sie taucht tief, ich schwimme an der Oberfläche.

Das ist natürlich eine verkürzte Darstellung. Der überzeichnete Kontrast hilft mir aber, meinen gestrigen Gedanken zu begründen: Ist der Überflüss an Daten vielleicht kontraproduktiv? Haben wir den falschen Wunsch, wenn wir uns noch mehr wünschen? Ist die “Umsonst-Kultur” des Internets nicht nur für Produzenten eine wirtschaftlich schwierige Sache, sondern auch für die Konsumenten?

Mich durchzuckte gestern jedenfalls beim Griff nach der Zeitschrift der Wunsch, es möge mehr kostenpflichtige Angebote geben. Die Zeitschriftenartikel kann ich im Internet kostenlos lesen – wie auch z.B. die der brand eins –, aber ich gebe für sie Geld aus.

Hatte ich zunächst gedacht, das täte ich nur, um in einem Heft bequemer als am Bildschirm lesen können, so sehe ich jetzt einen zweiten positiven Effekt: ich fokussiere mich mehr.

Lesestoff, für den ich bezahle, schenke ich mehr Aufmerksamkeit.

Das ist meine gestrige Erkenntnis. Der Volksmund weiß zwar schon lange, “Was nix kostet, ist auch nix wert”, doch gestern habe ich das echt gespürt, weil ich die Konsequenz gesehen habe. Meine Augen flogen über die kostenlosen Inhalte hinweg. War das Geschriebene zu holprig, bin ich gesprungen oder habe den nächsten RSS-Feedeintrag geöffnet. War ein Video zu langweilig, bin ich gesprungen oder habe das nächste gestartet.

Ohne spürbare Kosten gibt es keinen Anreiz, bei einem Inhalt zu verweilen.

Ist das schlimm? Ich würde sagen, ja, das ist aus mehreren Gründen “schlimm”:

  1. Wir verbrauchen die undiskutierbar endliche Ressource Zeit ineffektiv und ineffizient. Wohlgemerkt beziehe ich mich jetzt auf Zeit, in der wir etwas lernen wollen/sollen. Der Entspannung mag “Zappen” ja (gelegentlich) zuträglich sein.
  2. Wir geben Neuem/Unbekanntem weniger Chancen, weil wir schon genug damit zu tun haben, das Bekannte und Beliebte anzuklicken. Wenn wir hingegen gezahlt haben, tendieren wir dazu, auch mal das nicht unmittelbar Erfreuliche, Bekannte, Flauschige zu ertragen – und schließlich gar zu mögen und zu vertreten. Wir haben schließlich gezahlt, also nutzen wir auch die bezahlten Inhalte.
  3. Wir begünstigen die Abnahme der Qualität von Inhalten, weil die im Überfluss unter immer größeren Konkurrenzdruck geraten. Der könnte theoretisch zwar auch dazu führen, dass die durchschnittliche Qualität zunimmt – de facto scheint das aber nicht so zu sein. Überlebensfähiger scheint nicht inhaltlich Tiefgehendes zu sein, sondern schnelle Aufmerksamkeitsattraktionen und schnell Befriedigendes.
    Das bedeutet nicht, dass es keine “guten Inhalte” mehr gibt, aber sie sind schwerer als im Mangel zu finden.

Mein Fazit: Wir müssen mehr zahlen für Inhalte. Wieviel genau mehr und in welcher Form, weiß ich nicht. Dass aber Zahlungen nötig sind, scheint mir unausweichlich. Nur wenn wir zahlen, wenn Konsum insofern spürbar wird, kommen wir zu einem bewussteren Umgang mit unserer Zeit, mit unseren Ressourcen.

Welchen Schaden die Abwesenheit von Kosten anrichten kann, sehen wir jeden Tag an der wachsenden Spam-Flut (auch innerhalb von Unternehmen). Da Emails nicht kosten, gibt es kein Halten. Jeder verbreitet alles an alle, wenn ihm danach ist. Was ihm keine Mühe macht, belastet allerdings die Empfänger. Das ist umso schlimmer, da Email ein Push-Medium ist.

Ähnliches gilt für die Veröffentlichung in anderen Medien. Mit dem Internet ist es jedem jederzeit möglich auf jedem Niveau etwas zu veröffentlichen – sei es in Newsgroups, Blogkommentaren oder gar eigenen Blogs. Das kostet nichts beim Schreiben und nichts beim Lesen. Google bringt es in haltlos wachsender Menge vor meine Augen.

Wenn es aber noch vor dem Internet eine zivilisatorische Errungenschaft gab, dann ist es die Impulskontrolle. Sie ist sogar womöglich im Kern der Definition von Zivilisation. Wir sollten nicht jedem Impuls nachgeben. Warum preisen wir dann das Internet mit seiner Null-Kosten-Kultur so hoch? Ist das nicht merkwürdig. Dort leben wir jeden Impuls zur Äußerung und Konsumption einfach aus. Kost´ ja nix.

Zwar beschert uns das vorher ungekannte Freiheit und Datenfülle. Andererseits scheint es mir sowohl bei der Produktion wie der Rezeption Qualitätsmängeln Vorschub zu leisten.

Deshalb mein Gedanken, Produktion und Rezeption mit Geld zu steuern. Denn um nichts anderes geht es: Steuern von Zeitinvestitionen. Eine Latte, über die man springen muss, damit die knappe Ressource Zeit lohnenswert investiert ist.

Das ginge zwar auch irgendwie wohl mit mehr Selbstdisziplin und/oder Medienkompetenz. Vielleicht fehlt die mir ja schlicht als prä-Digital Native? Doch das gute alte Geld scheint mir ein einfacheres Mittel. Ich bin also im Allgemeinen dafür, mehr zu zahlen. Und ich bin auch bereit, selbst ganz konkret mehr zu zahlen und dadurch weniger Inhalte “at my fingertips” zu haben.

Dass das Bezahlen online anders als offline funktionieren muss, ist klar. Im Internet muss es Möglichkeiten zum kostenlosen Stöbern geben wie im Buchladen. Und Inhalte sollten in verschiedenen Granularitäten gekauft werden können. Am Ende tun wir uns aber, so glaube ich, alle einen Gefallen, wenn wir wieder für Inhalte zahlen.

Mehr, deutlich mehr kostenpflichtige Inhalte scheinen mir unausweichlich. Im historischen Rückblick werden deshalb wohl die ersten 15-20 Jahre “öffentliches Internet” mit seiner Null-Kosten-Kultur als Zeit der Verirrung angesehen werden. Schiere Datenflut ist eben nicht genug. Es braucht Hilfe beim Lenken und Fokussieren von Ressourcen. Und da ist Geld immer schon ein sehr probates Mittel gewesen.

Donnerstag, 8. Oktober 2009

Material zu meinen Vorträgen auf der ADC 2009

Die ADC 09 ist fast vorbei – nur noch morgen ein Workshop zum Thema Architektur. Hat wieder Spaß gemacht. Gute Gespräche, ein interessiertes Publikum, Sedgeway fahren :-) Und: die ersten CCD-Mausmatten haben den Weg in die Community gefunden.

Da ich in guter Tradition meine Vorträge ohne PPT-Folien gemacht habe, um den Aufmerksamkeitsfokus der Teilnehmer nicht vom Wesentlichen, dem Thema, auf irgendwelche Projektionen abzulenken, hier einige Hinweise für die, die sich damit weiter beschäftigen möchten:

  • Der Quellcode meiner CCR- und ApplicationSpace-Vorträge steht hier zum Download inkl. Microsoft CCR. Der CCR Space als Wrapper um die CCR ist ein Open Source Projekt bei Google: http://code.google.com/p/ccrspace. Der Application Space ist ebenfalls Open Source, aber bei CodePlex: http://xcoappspace.codeplex.com/
  • Die CCR ist Teil des Robotics Studio, dessen Nutzung einer Lizenz unterliegt. Wer die CCR produktiv einsetzen will – und das kann man tun, denn sie ist ausgereift –, sollte sich daher einmal anschauen, welche Lizenz passt. Mit einer MSDN Subscription “hat” man die CCR auch, wenn ich mich nicht irre; ansonsten kann man sie auch als sog. “CCR und DSS Toolkit” für kleines Geld kaufen.
  • Literatur zur CCR kann ich leider nicht so recht empfehlen. Es gibt versprengt im Netz einiges – aber das beleuchtet die CCR nur punktuell. Die CCR Doku ist nicht ausführlich. In der dotnetpro habe ich aber zwei Artikel im Jahr 2009 darüber geschrieben; die sind natürlich über das online Archiv hier und hier verfügbar.
  • Clean Code Developer ist ausführlich im Wiki beschriebe: www.clean-code-developer.de. Dort gibt es auch Hinweise auf Berichte über CCD inkl. Videos. Wer dann mitdiskutieren will, ist herzlich zu den Foren bei XING und Google eingeladen.
  • Über Agile Führung bzw. Soziokratie habe ich schon recht ausführlich hier im Blog geschrieben. Außerdem äußere ich gelegentlich Gedanken dazu in einem eigenen Blog: http://soziokratie.blogspot.com. Dort gibt es auch weitere Hinweise zu Quellen gleich in einem der ersten Beiträge. Und es gibt natürlich auch eine “offizielle Repräsentation” dieses Organisationskonzeptes; das ist in Deutschland das Soziokratische Zentrum: www.soziokratie.org.
  • Im Architekturworkshop ging es um die systematische Transformation von Anforderungen in wartbare “Grobstrukturen” und dann deren Übersetzung in konkreten Code. Das Softwareuniversum und Softwarezellen waren Thema. Dazu habe ich schon einiges über die Jahre geschrieben. Hier der Lesestoff in ziemlich chronologischer Reihenfolge:

Auf der ADC habe ich schon einige Fragen zu diesen Themen beantworten können. Doch es ergeben sich im Nachhinein bestimmt noch mehr. Bitte zögern Sie dann nicht, mich per Email (info (at) ralfw (dot) de) oder über die Kommentare hier im Blog zu kontaktieren. Ich bin gespannt auf Ihre Gedanken.

Donnerstag, 24. September 2009

Modelle für Geschäftsanwendungen mit Domain-Driven Design

Software soll man zuerst modellieren, heißt es. Nicht gleich loscodieren, sondern erst irgendwie planen. Dieses Planen bezeichnet man oft als Modellieren. Aber was bedeutet “Modellieren”? Was ist ein Modell für eine Software?

Was ist ein Modell?

Wikipedia sagt zum Begriff “Modell”:

“Von einem Modell spricht man oftmals als Gegenstand wissenschaftlicher Methodik und meint damit, dass eine zu untersuchende Realität durch bestimmte Erklärungsgrößen im Rahmen einer wissenschaftlich handhabbaren Theorie abgebildet wird. Da im Allgemeinen nicht alle Aspekte der untersuchten Realität in Modellen abbildbar sind, wird Modellbildung oftmals als Reduktion, Konstruktion oder Abstraktion bezeichnet.”

Achso, alles klar, oder? ;-) Nein, ich glaube, das verdient noch etwas Übersetzungsmühe. Die wichtigen Begriffe sind aus meiner Sicht:

  • Realität: Die Problemdomäne mit ihren Anforderungen
  • Theorie: Das Modell als eine mit Unsicherheiten/Unvollständigkeiten behaftete Beschreibung der Realität
  • Reduktion: Das Modell beschreibt nur einen Ausschnitt der Realität
  • Abstraktion: Das Modell beschreibt die Realität in allgemeinen Begriffen

Ein Modell beschreibt also einen Ausschnitt der Realität in allgemeinerer Form und unter bewusster Auslassung mancher Details. Modelle konzentrieren sich also auf das Wesentliche aus einem bestimmten Blickwinkel.

image Beispiel: Für die Problemdomäne “Schuss aus einer Kanone” ist die Formel y=x^2 ein Modell, das den Flug der Kanonenkugel beschreibt. Das Modell reduziert die Problemdomäne, weil in ihm z.B. Flugbahneinflüsse durch Wind nicht berücksichtigt werden; und es abstrahiert von den Konkreta Kanone, Pulver, Kugel usw., indem es die Flugbahn mit rein mathematischen Mitteln beschreibt. In der Formel gibt es keine Kanone und keine Kugel und kein Ziel mehr, sondern nur noch Punkte in einem Koordinatensystem.

Der Zweck solchen Modells ist es, eine Domäne in der Realität besser zu verstehen, um dann Antworten zu liefern. Ein Modell hilft also Fragen zu klären, die sich im Detailreichtum der Realität nicht so einfach beantworten lassen, z.B. die, wie eine Kanone ausgerichtet werden muss, um ein Ziel zu treffen.

image Modelle sind damit wie Landkarten. Sie schaffen Überblick. Mit ihnen wird die Planung einer Lösung handhabbar, ohne dass man sie sogleich ausführen muss.

Sie können sich von A nach B einen Weg durch ein Terrain bahnen. Das ist dann schon eine konkrete Lösung. Oder Sie können auf einer Landkarte mit dem Finger wandern. Da gewinnen Sie einen Überblick, erkennen Hindernisse, können Alternativen diskutieren. Im Gelände “implementieren” Sie dann Ihre Weg-Planung. Das geht zwar nicht glatt, aber die Wahrscheinlichkeit großer Überraschungen ist viel geringer als ohne Terrain-Modell. Die Landkarte hilft also bei Beantwortungen von Fragen an ein Terrain.

Gleiches gilt für das Modell eines Hauses. Früher war ein solches Modell materiell. Es sollte z.B. dem Auftraggeber einen Überblick über das spätere Erscheinungsbild geben. Der konnte sich das anhand von Blaupausen schlecht vorstellen. Also baute ein Modellbauer ein Modell zum “Sehen und Anfassen”. Vor der Ausführung konnten anhand des Modells dann Fragen beantwortet werden wie z.B. “Ist die Anordnung der Räume so praktikabel, wie man es sich gedacht hat?” oder “Pass sich das Haus gut in die Umgebung ein?”

Details der Realität wie Baustoffe oder Stabilität blendet so ein Modell aus, es reduziert die Realität. Und die Abstraktion besteht in der Handhabbarmachung. Das Modell ist kleiner als das spätere reale Haus. Es konzentriert sich auch auf das für die Fragestellungen Wesentliche, z.B. Größenverhältnisse oder Stil. Damit dient es einem einfacheren Erkenntnisgewinn als er möglich wäre, würde das Haus erst komplett ausgeführt.

Eine Kulisse ist deshalb kein Modell. Erstens dient sie ohnehin nicht dem Erkenntnisgewinn, zweitens macht sie die Realität nicht wirklich handhabbarer, weil sie Originalgröße hat. Da nützt auch die Reduktion nichts, die eine Kulisse betreibt. Sie besteht z.B. nicht aus dem Baustoff realer Häuser.

Dass dann heute Hausmodell meist virtuell sind, tut ihrem Modellcharakter keinen Abbruch. Im Gegenteil! Die Virtualität betont ihn. Sie reduzieren quasi maximal und können je nach Fragestellungen ganz unterschiedlich abstrahieren, z.B. indem sie sich auf das Aussehen oder die Wärmeleitung oder einen anderen Aspekt konzentrieren.

Modelle in der Softwareentwicklung

Modelle in der Softwareentwicklung müssen dieselben Kriterien wie Modelle in anderen Bereichen erfüllen, um wirklich Modelle zu sein. Sie müssen also reduzieren und abstrahieren und es damit einfacher machen, Fragen zu beantworten bzw. einen Überblick zu gewinnen.

Diese Modelle können sich auf die Problemdomäne beziehen und z.B. einfach nur die Realität des Kunden beschreiben. Dann dienen sie der Analyse. Oder sie können sich auf die Lösung beziehen, d.h. die Software, welche Anforderungen in der Problemdomäne des Kunden erfüllen soll. Dann dienen sie dem Entwurf. Wenn von Softwaremodellierung die Rede ist, sind Entwurfsmodelle gemeint. Darauf konzentriere ich mich denn auch im Folgenden.

Wie könnte nun ein Softwaremodell aussehen? Im Grunde ist alles recht, was reduziert und abstrahiert – und zwar von der Implementation! Ha!

Das müssen wir uns auf der Zunge zergehen lassen: Ein Entwurfsmodell abstrahiert von der Implementation. (Die Reduktion lasse ich mal unter den Tisch fallen, um die Argumentation einfacher zu halten.)

Klar, abstrahieren muss ein Modell, sonst bietet es keinen Vorteil gegenüber der Implementation. Oder anders: Modellierung findet nur dort statt, wo abstrahiert wird. Was nicht abstrahiert, das ist kein Modell.

Klassendiagramme modellieren nicht

Das lässt eigentlich nur eine sehr ernüchternde Erkenntnis zu: Die üblichen Klassendiagramme sind keine Modelle. Sie abstrahieren einfach nicht. Klassendiagramme sind nur eine andere Notation für das, was auch in Quellcode ausgedrückt werden kann – und zwar 1:1. Sie machen das zwar visuell, aber deshalb reduzieren sie allerhöchstens wenig (weil sie Methodenimplementationen auslassen). Vor allem abstrahieren sie dadurch jedoch nicht. Eine Klasse als Rechteck liegt auf keinem höheren Abstraktionsniveau als eine textuell beschriebene Klasse.

Wer direkt mit Klassen seine Software entwirft, der modelliert sie also nicht, sondern legt gleich sozusagen “Stein auf Stein”. Da macht es auch keinen Unterschied, wenn diese Klassen mit CRC Cards im Rollenspiel gefunden werden. Solange Klassen gesucht werden, findet keine Modellierung statt.

Das ist natürlich nicht per se falsch. Aber man sollte sich bewusst sein, dass man eben im Terrain wandert und nicht auf eine Karte blickt. Visualität macht noch kein Modell. Modell ist, was abstrahiert. Egal wie.

Etablierte Modelle der Softwareentwicklung

Nachdem ich nun die für manche wohl heilige Kuh “Klassendiagramm” geschlachtet habe ;-), stellt sich ganz berechtigt die Frage, was denn dann Modelle sein sollen.

imageEin Blick in die Informatikliteratur erhöht die Modellkenntnis, könnte man in Anlehnung an ein juristisches Sprichwort sagen. Da findet sich nämlich z.B. ein Titel wie dieser: “Modellierung – Grundlagen und formale Methoden”.

Darin – soviel sollte inzwischen gewiss sein – findet sich kein einziges Klassendiagramm. Modellierung hat einfach nichts mit einem Programmierparadigma wie der Objektorientierung zu tun. Ja, ich möchte fast sagen, sofern in einer Darstellung Spuren einer Plattform oder eines Implementationsparadigmas zu finden sind, kann es kein Modell sein. Das trifft allemal auf Klassen und ihre Verwandten die Module zu. Klingt rigoros und ist hier bewusst so gemeint. Sie werden sehen, worauf ich abziele.

Wenn kein Klassendiagramm, was aber dann als Modell? Unter anderem bietet das empfehlenswerte Büchlein diese Modellarten:

  • Graphen
  • Endliche Automaten
  • Grammatiken

Wenn Sie einen online Shop programmieren sollen, dann könnten Sie den z.B. als endlichen Automaten modellieren.

image

Das ist eine echte Abstraktion der angestrebten Lösung! So bekommt man Übersicht, so lassen sich Fragen leicht stellen. Das versteht womöglich sogar der Kunde, für den Sie den Shop entwickeln.

Die Visualität der Darstellung macht die Modellhaftigkeit allerdings nicht aus. Der Automat wäre immer noch ein Modell, würden Sie ihn als Tabelle beschreiben:

  Suchen In Warenkorb Zur Kasse Menge ändern Bezahlen
Z1 Z1 Z2      
Z2 Z2   Z3    
Z3       Z3 Z1


Warum nun aber ein Modell für den Shop und nicht einfach nur ein hübsches Klassendiagramm? Der Sprung wäre zu weit von der Problemdomäne direkt in die Lösungsdomäne. Sie würden quasi mühevoll einen Berg durchtunneln. Den Berg, der das Tal des Problems vom Tal der Lösung trennt.

Mit einem Modell dazwischen machen Sie eine Wanderung vom einen ins andere Tal. Sie arbeiten sich einen Abstraktionsberg hinauf, der Ihnen auf dem Gipfel eine schöne Aussicht auf beide Täler bietet. Zumindest beim Abstieg ins Lösungstal können Sie daher Ihren Weg planen, weil Sie vom hohen Abstraktionsgipfel auf die Niederungen des Lösungsterrains blicken. Außerdem übersehen Sie aber auch noch das Terrain Ihres Aufstiegs. Sie bekommen also auch einen besseren Überblick über das Problem.

In Bezug auf das Shop-Beispiel bedeutet das: Die herausgearbeiteten Ereignisse und Zustände machen dem Kunden klar, wie Sie seine Problemdomäne verstanden haben. Ihm geht jetzt womöglich auf, dass man nach dem Gang zur Kasse keinen weiteren Artikel mehr in den Warenkorb legen kann.

Und Sie haben eine sehr abstrakte Beschreibung Ihrer Lösung, die Sie einfach in Code umsetzen können. Für Zustandsautomaten gibt es etablierte Implementationsstrategien. Die können Sie natürlich als Klassendiagramme skizzieren. Die Ebene des Modells verlassen Sie jedoch damit.

Gleiches gilt, wenn Sie z.B. die Kommunikation zwischen Client und Server als Konversation in einer Sprache modellieren, die Sie mit einer Grammatik beschreiben.

Und es gilt auch, wenn Sie Ihren Ansatz zur Lösung der KataPotter als Graph modellieren.

Spüren Sie doch einmal in sich hinein: Fühlen Sie beim Umgang mit einem echten Modell nicht auch eine gewisse Leichtigkeit? Ist es nicht entspannend, sich nicht mit Klassen herumschlagen zu müssen? Oder wenn, dann sollten die Klassen sich quasi von allein ergeben aus dem Modell – als Implementierungsdetails nach einer Übersetzungsvorschrift. Das kann doch nur der Korrektheit Ihrer Lösung zuträglich sein.

Modelle für Geschäftsanwendungen

Jetzt zur Masterfrage: Wie sollen denn Modelle für Geschäftsanwendungen aussehen? Was, wenn Graphen, Automaten, Grammatiken nicht passen und auch keine griffige Formel Problem bzw. Lösung hübsch abstrakt beschreiben?

Nun, nicht triviale Geschäftsanwendungen bieten sicherlich Platz für mehrere Modelle. Die Benutzerinteraktion mag eben doch passend mit einem endlichen Automaten modelliert werden. Und für die Planung von Ressourcen bietet sich vielleicht ein mathematisches Modell an.

Doch die formalen Modelle aus Informatik und Mathematik decken sicherlich nicht die ganze Anwendung ab. Was also tun mit den Lücken? Oder was tun, um die verschiedenen kleineren Modelle unter einem Dach zusammenzufassen?

imageIch glaube, genau dafür macht ”Domain-Driven Design” (DDD) von Eric Evans einen Vorschlag. Der lautet: Modelliere (Geschäfts)Anwendungen mit Services, Entitäten bzw. Aggregaten und Value Objects sowie den “Hilfsdiensten” Applikationsschicht und Repository.

Dass es sich bei Services usw. um Elemente eines Modells handelt, können sie an der Abwesenheit von Implementationsdetails erkennen. Diese Konzepte haben nichts direkt zu tun mit Klassen. Sie können Service, Entität oder Repository auch mit C implementieren. Mit C# mag es leichter fallen, doch Objektorientierung ist nicht zwingend nötig.

Die dynamischen Aspekte eines online Shops mögen Sie nun also mit einem endlichen Automaten modellieren. Was ist aber mit den statischen Aspekten? Was fließt durch den Automaten? Wer sind die Beteiligten an einem Bestellvorgang?

Hier kommt DDD ins Spiel. Denken Sie nicht sofort in Klassen, sondern in DDD Begriffen. Für die gibt es später Übersetzungen in Klassen. Aber zunächst wollen Sie nichts von diesen Details wissen. Der online Shop lässt sich leichter auf einem höheren Abstraktionsniveau entwerfen.

Fragen Sie also: Was sind die Entitäten? Was sind die Value Objects? Was sind die Services?

Ohne hier näher auf DDD eingehen zu wollen, liegen folgende Elemente eines online-Shop-Modells nahe:

  • Warenkorb-Entität
  • Warenkorbposition-Value-Object
  • Produkt-Entität
  • Kunde-Entität
  • Warenkorb-Aggregat
  • Warenkorb-Repository
  • Produkt-Repository
  • Kunde-Repository
  • Bestellung-Service

Ähnliches hätten Sie auch gleich mit einem normalen Klassendiagramm entwerfen können? Irgendwie natürlich schon. Aber Sie hätten Ihr Denken damit nicht beschränkt. Sie hätten sich schnell in Details verloren. Zum Beispiel frisst “die Persistenzfrage” oft viele mentale Ressourcen.

Mit DDD gibt es “die Persistenzfrage” jedoch im Grunde nicht. DDD sagt: Wo Entitäten sind, da sind Repositories mit ganz einfacher Schnittstelle für die Persistenz zuständig. DDD abstrahiert also von den vielen möglichen Wegen, Daten zu persistieren.

Der Wert eines DDD-Modells liegt also in den Entscheidungen, die es schon für Sie getroffen hat. Wie werden Daten überhaupt zusammengefasst? Wie greift man auf Daten zu? Wie modifiziert man Date? Wie werden Daten persistiert? Darauf hat DDD einfache Antworten. Wer DDD betreibt, tut es dann halt so – und bekommt durch diese Beschränkung – oder besser: durch diese Fokussierung – Freiraum, sich um das Wesentliche der Problemlösung zu kümmern.

Wie endliche Automaten und Grammatiken und mathematische Formeln ist DDD natürlich keine “one size fits all” Modellart. Ob sich ein Game oder eine Maschinensteuerung damit geeignet modellieren lässt, mag bezweifelt werden. Oder vielleicht auch nicht. Denn die Modellelemente von DDD sind so allgemein, dass sie sich womöglich in allen nicht trivialen Anwendungen finden lassen.

Aber einerlei: Auch DDD hat selbstverständlich seine Grenzen.

Dennoch glaube ich, dass es sich lohnt, beim Entwurf von Software Ausschau zu halten nach Anwendungsmöglichkeiten für DDD. DDD bietet ein unaufdringliches Metamodell mit einfach zu verstehenden Elementen. So hilft DDD, Software echt zu modellieren, d.h. sich nicht in Implementationsdetails zu verlieren.

Montag, 21. September 2009

Motivationshappen

Da habe ich angekündigt, dass Teilnehmer von Entwicklerkonferenzen der nächsten Zeit in ihren Taschen Clean Code Developer Mausmatten finden würden – aber ich hab mir keine Gedanken gemacht, wie diese Taschen überhaupt an Teilnehmer kommen. Tststs, wie nachlässig von mir. Das darf ich doch nicht einer unsicheren Chefentscheidung überlassen ;-)

Deshalb hier für die bisher noch Unentschiedenen oder Chefabhängiggen zwei Motivationshappen:

image Wer zur ADC 2009 nach Bonn kommen und auch noch meinen Workshop zum Thema Softwarearchitektur besuchen möchte, der kann sich bei mir per Email melden und bekommt einen Promocode, der ihm oder ihr 200 EUR Rabatt gewährt. Die ADC bietet ein breites Spektrum an Vorträgen zu vielen Themen der .NET Softwareentwicklung. Dieser Happen kann bis zum 25.09.2009 geschnappt werden.

image Wer hingegen oder ebenfalls nach München zur prio 2009 kommen möchte, um sich speziell rund um das Thema “User Interfaces für .NET Software” auf den aktuellen Stand zu bringen, der kann sich ebenfalls bei mir per Email melden und erhält einen Promocode für 400 EUR Rabatt auf den regulären Veranstaltungspreis. Von diesem Happen sind noch 10 auf dem Teller.

Der Rechtsweg ist für beide Angebote natürlich ausgeschlossen.

Also: Ran an die Email! Ich hoffe, wir sehen uns auf zumindest einer der beiden Konferenzen. Die Mauspads wollen zu euch ;-)

Sonntag, 20. September 2009

Clean Code Developer Bausteine immer zur Hand [endlich-clean.net]

Endlich ist es soweit: Clean Code Developer (CCD) bringt seine Bausteine auf den Desktop. Wir haben keine Mühen und Kosten gescheut, um einen Weg zu finden, die Inhalte der CCD-Grade gleichermaßen übersichtlich wie praktisch und auch noch – so hoffen wir – angenehm fürs Auge zu visualisieren. Die tollen Initiativen der CCD-Communities mit Tetraedern, Pyramiden und Mindmaps haben Stefan und mich angeregt und angespornt. Mit dem Professional Developer College haben wir dann einen Sponsor gefunden, der die Entwurfs- und Herstellungskosten trägt.

Das Ergebnis sind zunächst eine Mausmatte:

image

und ein Bildschirmhintergrund:

image

Die Mausmatte werden wir auf den Entwicklerkonferenzen des Herbstes verteilen. Beim .NET Open Space imagehaben wir ein Kontingent dabei, das wir kostenlos an Interessierte  verteilen. Und bei der ADC 2009 imagesowie der prio 2009 imagefinden alle Teilnehmer eine Mausmatte in ihrer Veranstaltungstasche.  Wer bisher noch keinen Grund gesehen hatte, mindestens eine dieser Veranstaltungen zu besuchen, der sollte also jetzt nochmal darüber nachdenken ;-)

Für die Daheimbleibenden mag allerdings der Bildschirmhintergrund ein kleiner Trost sein. Mit dem hat man zwar die CCD-Bausteine nicht im wahrsten Sinne des Wortes “zur Hand”, aber immerhin vor Augen. Hier der die Bitmap in der Auflösung 1200x800 zum Download.

Viel Freude und Erfolg mit diesen CCD-Gedächtnisstützen!

Donnerstag, 17. September 2009

Root Cause Analysis einer Code Kata [endlich-clean.net]

Stefan Lieser tut es nun auch: Er hält seine Codierfinger mit Code Katas geschmeidig. Gerade hat er beschrieben, wie es ihm da bei der KataPotter ergangen ist. Zunächst ist ihm die Lösung leicht gefallen:

“Da ich es gewohnt bin, testgetrieben zu arbeiten, hatte ich mit den ersten Schritten keine Probleme. Die ersten Tests waren schnell erstellt und haben die Implementierung schnell in die richtige Richtung getrieben.”

Später war es nicht mehr so einfach:

“Dann kamen jedoch die komplizierteren Beispiele an die Reihe und ich habe länger mit der Implementierung gekämpft.”

Seine Schlussfolgerung zur Ursache mit den Lösungsschwierigkeiten:

“Ich habe erkannt, dass ich mit dem Refaktorisieren tendenziell zu früh beginne.”

Hört sich gut an, oder? So soll es sein: Erkenntnisgewinn durch Code Kata.

Da ich diese Kata neulich auch gemacht habe und auch Schwierigkeiten hatte, erlaube ich mir jedoch, hinter den Erkenntnisgewinn zu schauen. Ich bezweifle nicht, dass es einer ist und wir alle daraus etwas lernen können: TDD ist kein Selbstzweck; auch mit TDD müssen wir schauen, dass wir Nutzen produzieren, bevor wir innere Code Qualität herstellen.

Aber ich frage mich, ob Stefan damit sein Ursprungsproblem aufgedeckt hat. Hat er hier erfolgreich eine Root Cause Analysis betrieben?

Ich vermute, seine Schwierigkeit ist ein Folgeproblem eines Symptoms, das durch TDD quasi provoziert wird. Das nenne ich jetzt mal das No Design Up Front (NDUF) Symptom.

Aus meiner Sicht ist passiert, was heufig passiert und scheinbar durch TDD auch noch gutgeheißen wird: Stefan hat ein Problem gelesen, kurz darüber nachgedacht, ob er es versteht, und dann mit dem Codieren begonnen in dem Glauben, dass sich schon ein angemessenes Design bei der Codierung ergeben wird. TDD = Test Driven Design.

Der Gedanke ist sicher nicht falsch. Die Frage ist nur, wofür sich ein angemessenes Design durch die kleinen TDD-Schritte ergibt?

Meine Antwort ist: TDD führt zu einem angemessenen Design für das Modell, das man sich von einer Lösung gemacht hat. Nicht mehr, nicht weniger.

TDD ist also ein Werkzeug, das mich eine Zielvorstellung konkretisieren lässt. Mit TDD kann ich ein evolvierbares Design manifestieren. Ich schlage es mit TDD-Schritten sozusagen als Skulptur aus einem Marmorblock heraus.

Tja… was aber, wenn ich einen falschen Marmorblock gewählt habe? Wenn du zu klein ist, dann komme ich nicht zu der Skulptur, die ich gern hätte.

Verräterisch an Stefans Aussage ist, dass die  Tests “die Implementierung schnell in die richtige Richtung getrieben” haben – und er trotzdem am Ende mit den komplizierten Beispielen zu kämpfen hatte. Ich behaupte mal, Stefans anfängliche Tests bzw. die Implementierung haben eben nicht (!) in die “richtige Richtung” gezielt. Nur weil Tests grün waren, heißt das eben nicht, dass irgendwie die Gesamtlösung näher gerückt ist. Denn die Gesamtlösung enthält eben auch und gerade die komplizierten Fälle.

Mein Verdacht ist eher – und den erlaube ich mir, weil ich selbst in diese Falle getappt bin –, dass Stefan keinen Leitstern hatte und damit keine Richtung. Er hatte kein Modell der Lösung, auf das hin er Code geschrieben hat. Er hat nur unmittelbar vor seine Füße geschaut. Dort lag dann immer nur ein nächster Testfall, den er in ad hoc Manier gelöst hat.

Tut man das, dann läuft man bei der KataPotter aber unweigerlich gegen eine Mauer. Ab einem gewissen Punkt muss man mit seiner Lösungsstrategie umschwenken. Da geht es nicht mehr mit “brute force”. Das ist der Fall, wenn der beste Preis für einen Warenkorb nicht der naheliegende ist. Die Kata-Beschreibung nennt diesen Fall explizit.

Und da setzt meine Kritik an: Wider besseren Wissens ist Stefan mit Babysteps losgelaufen und hat einfach Test auf Test gehäuft. Das Problem ist dann am Ende nicht gewesen, dass er zu früh refaktorisiert hat, sondern dass er nicht vor dem ersten Schritt überlegt hat, wie die Lösung im Modell aussehen soll. Der komplizierte Warenkorb hat ihn überrascht wie den geschäftigen Familienvater alle Jahre wieder das Weihnachtsfest.

Dabei glaube ich, dass Stefan schon vor dem ersten Test ein Modell im Kopf hatte. Wenn er die Lösung für den komplizierten Warenkorb selbst gefunden hat, dann hat er auch eine implementierbare Strategie gekannt. Ich sag mal als Stichwort “Baum” ;-)

Warum hat er dann diese Strategie nicht auf einem Blatt aufgezeichnet und überlegt, welche Algorithmen und Datenstrukturen dafür nützlich wären? Warum hat er dann diese Algorithmen und Datenstrukturen nicht vom ersten Test an angepeilt? Auch das hätte kleinschrittig mit TDD geschehen können.

Stattdessen hat er sich sozusagen dümmer gestellt als er war. Er hat sich ganz TDD überlassen in dem Glauben, dass sich durch TDD schon eine Problemlösung ergeben würde. Aber TDD führt nur zu Strukturen, nicht zu Algorithmen. Die Algorithmen, die grundsätzlichen Lösungsansätze, die Modelle, die entstehen im Kopf. Sie sind die Leitsterne für das Voranschreiten mit TDD.

Da liegt für mich das Wurzelproblem. Nicht nur bei Stefan. Ich bin ja selbst in diese Falle getappt. TDD bietet sich so vollmundig als Design-Werkzeug an, dass wir (und sicher auch andere) ihm auf den Leim gehen und allzuleicht glauben, dass wir uns weitere Gedanken ersparen können. Mit TDD gleich loslegen können: das ist so verlockend.

Aber TDD ist immer nur so gut wie das Modell, das ich für eine Lösung habe. TDD ist ein Werkzeug, das mir den Weg zu wartbarem Code für ein gegebenes Modell zeigt. TDD ersetzt die Modellierung aber nicht. Und die lohnt sich eben – wie hier zu sehen ist – auch für ein so kleines Problem wie die KataPotter. Mich lehren meine eigenen und nun auch Stefans Schwierigkeiten deshalb, dass sich ein paar Gedanken zur Lösung immer lohnen. Die Lösung sollte ich im Kopf haben – aber nicht ihre Struktur. Zu der führt mich TDD.