Follow my new blog

Montag, 24. Mai 2010

Überraschende Relevanzwellen [OOP 2010]

image Schon interessant, was zu Wellen im Twitter-Teich führt. Da stolpere ich während der Lektüre von “Projektmanagement” von Thorsten Reichert beim “Zusammenfassungsservice” getAbstract über den Satz

„Viele Unternehmen haben nie Zeit, Dinge richtig zu tun, aber stets Zeit, Dinge mehrmals zu tun.”

Den twittere ich – und erzeuge unerwartet weitreichende Reaktionen. Wow!

Nicht, dass mich die Funktionsweise von Twitter wundert. Nein, mich wundert, was die Gemüter hier in Resonanz versetzt. Ist nicht mein erster Tweet, aber der erste, bei dem ich aus so unterschiedlichen Ecken Retweets sehe. Das Thema schlägt offensichtlich einige Saiten in der Entwicklergemeinde an.

Was sind denn typische Beispiele, wo das DRY-Prinzip vom Management nicht eingehalten wird? Doppeltarbeit statt “einmal richtig tun”? Wer mag Situationen und Fälle benennen? Je mehr Konkretes zusammengetragen wird, desto eher ists möglich, daraus Ursachenmuster abzuleiten und vielleicht doch mal etwas dagegen zu tun. In kleinen Schritten.

Freitag, 21. Mai 2010

Biosphere 2 - Sind Wissensinseln “böse”? [OOP 2010]

image Grad kommt alles zusammen. Ich lese einen Thriller über die Evolution, die auf einer abgeschiedenen Insel zu sehr bösen Kreaturen geführt hat (“Biosphere” von Warren Kaye). Dann höre ich Jens Coldewey auf der SET in Zürich, der darüber spricht, wie böse es für Projekte ausgehen kann, wenn sie sich nicht gegen Inseln wehren, gegen Wissensinseln.

Und dann spreche ich am selben Tag mit Ivan Engler, dem Regisseur des Sci-Fi Spielfilms “Cargo”, der kein Problem mit Wissensinseln zu haben scheint. Im Gegenteil! Sie machen für ihn einen Teil der Effizienz einer Spielfilmproduktion aus.

Ja, was denn nun? Sind (Wissens)inseln “gut” oder “böse”?

Natürlich gibt es da keine pauschale Antwort. Es kommt immer darauf an, auf den Kontext. Deshalb könnte ich das Thema auch zu den Akten legen und einfach sagen: Beim Film sind Wissensinseln ok, bei der Softwareentwicklung hingegen sind sie unakzeptabel. So ist das halt.

Doch ich mag mich noch nicht von den Wissensinseln in der Softwareentwicklung verabschieden. Der Begriff suggeriert Kontraproduktivität – aber den kann ich ja austauschen. Wenn ich stattdessen Spezialisierung sage, dann ist die Konotation schon ganz anders.

Wenn Wissensinseln pauschal “böse” sein sollten, dann ist Spezialisierung pauschal “gut”. Spezialisierung ist schließlich das Ergebnis einer komplizierten Welt, in der nicht mehr jeder alles können kann (oder will). Damit meine ich nun nicht die seelenlose Spezialisierung eines seiner Produkte entfremdeten Fließbandarbeiters. Nein, ich meine eine Spezialisierung wie die einer Maskenbildnerin oder eines Kameramannes oder eines Motoringenieurs oder eines Kommunikationselektronikers.

imageIvan Engler hat keine Angst, dass eine Maskenbildnerin krank wird. Sie ist auch in einer laufenden Filmproduktion in ihrer Funktion ersetzbar. Das mag nervig sein, weil dann Aufwand zu treiben ist für eine Ersatzkraft, doch das ist kein Beinbruch. Und auch VW hat keine Angst, dass ein Motoringenieur ausfällt. Ist der eine krank, übernimmt ein anderer diese hochspezialisierte Aufgabe.

In der Softwareentwicklung allerdings geht die Angst um. Der truck factor scheint quasi immer bei 1 zu sein, sobald sich eine Spezialisierung entwickelt. Das scheint mir der Befindlichkeit in vielen anderen Branchen zu widersprechen. Ich ahne eine Überempfindlichkeit der Softwareentwicklung.

Natürlich kann ich Jens Coldeweys grundsätzlichen Gedanken zustimmen. Es gibt Wissensinseln, die “böse” sind. Und man sollte sie sich auch nicht unbewusst entwickeln lassen. Praktiken wir Reviews und Pair Programming sind probat, um dem entgegen zu wirken. Kein Problem. Ich bin für diese Praktiken und Wissensaustausch im Team.

Und dennoch… Ich bin auch weiterhin der Überzeugung, dass es illusorisch ist anzunehmen, alle Entwickler könnten gleichermaßen Experten in all den Technologien sein, die in einer größeren Anwendung zum Einsatz kommen. Alle sind Silverlight-, WCF-, NHibernate-, WF-, Azure-, InRule-, Oracle-Profis usw.? Das ist Quatsch.

Im Umkehrschluss bedeutet das: Solange der Wille besteht, alle auf dem gleichen Level zu halten, kann dieses Level nur mittelmäßig at best sein.

Soweit die beiden Positionen: Wissensinseln sind “böse”, Spezialisierung ist für Höchstleistung unvermeidbar.

Lässt sich da noch eine Brücke schlagen?

Ja, mir scheint, das geht. Dazu müssen wir aber die Architektur in den Blick nehmen. Auch Jens Coldewey hat Conway´s Law erwähnt: Organisationsstrukturen spiegeln sich in Produktstrukturen wider. Da hake ich mal ein und frage: Wenn denn nun die Organisation dazu führt, dass eben keine Grenzen mehr zu sehen sind – alle sind in ihrem Wissen gleich –, wie soll denn dann die Software aussehen, die so eine Organisation produziert?

Vor dem Hintergrund von Conway´s Law bezweifle ich, dass eine Organisation, in der alle gleich sein sollen, Software herstellen kann, die wahrhaft modular ist, d.h. in der es ganz klare Verantwortlichkeiten gibt. Collective Code Ownership widerspricht insofern sauberer Architektur. Oder anders: Collective Code Ownership tut nichts dafür, dass es zu einer evolvierbaren Architektur durch Grenzziehung in Form von Entkopplung kommt. Wenn die hergestellt werden soll, dann muss ganz bewusst an anderer Stelle Kraft aufgewandt werden. Es gibt aus der Haltung zur Vermeidung von Wissensinseln heraus kein Bedürfnis, in Komponenten (oder gar “Services”) zu denken.

Und jetzt die Umkehrung: Ich setze voraus, dass Architektur modular (komponentenorientiert, serviceorientiert, entkoppelt usw.) sein soll. Punkt. Daran geht für mich nichts vorbei. Soviel ist der Langlebigkeit von Software geschuldet. Es geht ums pure Überleben des Produktes. Das bedeutet – im Sinne von Conway´s Law –, dass die Organisation ebenfalls “irgendwie” modular sein muss. Andernfalls reibt sie sich immer wieder auf, um Strukturen herzustellen, die ihr nicht entsprechen.

Unverbrüchliche Architekturprinzipien sollen also die Organisation treiben!

Daraus folgt für mich, dass z.B. eine grundlegende Trennung von Infrastruktur und Domäne in der Organisation zu sehen sein sollte. Domänenlogik ist etwas ganz anderes als ein Frontend, die Persistenz, die Sicherheit, die Kommunikation usw.

Nun die Masterfrage: In welchem dieser Bereiche sind Wissensinseln ein Problem? Aus meiner Sicht nur bei der Domäne. Software wird sehr sensibel überall dort, wo Domänenlogik im Spiel ist. Und das waren auch die Beispiele, die Jens Coldewey gebracht hat. Domänenlogik ist so sensibel, weil die Experten, die sich mit Softwareentwicklung und (!) Domäne auskennen, so dünn gesät sind.

Das ist übrigens auch der Fall im Filmbusiness. Kameramann und Regisseur und Schauspieler sind nicht so leicht auszutauschen wie eine Maskenbildnerin oder ein Mikrofongalgenhalter. Jene sind mit dem Thema des Films, der Vision eng verwoben; das ist die Domäne einer Produktion. Alles andere ist “Beiwerk” – wichtig, aber ohne Domänenbindung. Maskenbildner etc. haben generische Kompetenz.

Übertragen auf die Softwareentwicklung meine ich daher, dass wir dahin kommen müssen, architektonische Prinzipien ernst zu nehmen. Alles, was mit Infrastruktur zu tun hat, ist domänenunabhängig von der Architektur so zu kapseln, dass es von Experten mit generischer Kompetenz realisiert werden kann. Das mögen – je nach Anwendung – 5%, 10% oder 30% der Code sein. Immer bleibt der Löwenanteil jedoch in der Domäne.

Dennoch ist das ein Gewinn. Es ist nun ganz klar, welche Funktionalität grundsätzlich ohne truck factor realisierbar ist. Denn fällt der Silverlight-Experte aus, wird der nächste angeheuert. Der braucht nur wenig Einarbeitung, weil er keine Ahnung von der Domäne haben muss. Das hochspezialisierte Wissen für optimalen Technologieeinsatz macht kein Wissensinselproblem, weil es breit verfügbar ist (oder zumindest sein könnte). Hier kommt es vor allem auf Erfahrung mit nicht-funktionalen Anforderungen an. Die sind aber quasi in jedem Projekt zu gewinnen.

Es bleibt übrig der Bereich der Domäne. Hier werden die Experten in jedem Team individuell herangezüchtet. Und tatsächlich darf es in Bezug auf die Domäne im Team keine Wissensinseln geben. Domänenwissen ist so breit wie möglich verfügbar zu machen im Team. Denn dort sitzen die quasi einzigen Experten weltweit.

Von Domänenexperten dann aber auch noch Hochleistungen in technologischer Hinsicht zu erwarten, halte ich für eine Überforderung. Natürlich darf, kann, soll jeder Domänenexperte über eine Domänenkenntnis und gute “Programmierkenntnisse” der Plattform hinaus auch noch technologische Spezialgebiete haben. Nur sollte sich ein Projekt darauf nicht verlassen. Und es sollte nicht versuchen, solche technologischen Kompetenzen breit zu streuen. Das funktioniert nicht.

Stattdessen ist es Aufgabe der Architektur, Spezialgebiete (oder Belange) deutlich zu trennen. Die Domäne ist ein solches Spezialgebiet, Persistenz, Frontend etc. sind andere. Und für jedes Spezialgebiet ist Redundanz in Bezug auf die Kompetenzen herzustellen.

Redundanz in der Domäne ist Aufgabe des Projekteams, Redundanz bei Infrastrukturtechnologiekompetenzen ist Aufgabe des Marktes.

Die Filmindustrie hat das hinbekommen. Maskenbildern, Tischler, Bühnenbildner gibt es zuhauf. Bei der Domäne ist es dort aber naturgemäß schwierig. Dafür sind die Projekte auch zu kurz und personengebunden. Deshalb gibt es Versicherungen. Fällt der Hauptdarsteller wegen Unfall aus, kompensiert eine Versicherung den Verlust.

Das könnte auch in der Softwareindustrie funktionieren – wenn denn ein Team nachweisen kann, dass es Wissensinseln vermieden hat, soweit das möglich ist. Aber das ist ein anderes Thema…

An dieser Stelle ich mir wichtig, die Vereinigung aus Spezialisierung und Vermeidung von Wissensinseln herzustellen. Die liegt darin, die architektonisch saubere Separation of Concerns auf das Team zu übertragen. Daraus folgt, dass das Team bzw. Kernteam vor allem die Verantwortung für die Domäne bekommt. Darin sollen dann alle im Team Experten werden; Wissensinseln sind zu vermeiden, weil es außerhalb des Teams kaum Ersatz gibt.

Alle anderen Belange sollte das Kernteam aber nicht auch noch exzellent abdecken. Stattdessen sollte es sie strukturell isolieren und von externen Experten aufsetzen lassen. Im Team muss dann nur noch  Pflegekompetenz existieren. Teammitglieder müssen damit arbeiten und nur noch verstehen, was da gemacht wurde und hier und da korrigierend eingreifen können. Falls tiefere Kenntnis nötig werden sollte, wird wieder ein Experte “eingekauft”.

Damit vermeiden Teams den unmöglichen Spagat zwischen hoher Domänenkompetenz auf der einen Seite und technologischer Exzellenz auf der anderen Seite. Und so entsteht auch ein Markt für technologische “Söldnerexzellenz", die öfter als bisher in unterschiedlichen Projekten eingesetzt wird.


Anders, so glaube ich, kommen wir nicht heraus aus dem ewig mittelmäßig bis schlechten Einsatz von Technologien. Wissensinseln sind also tatsächlich zu vermeiden; das bedeutet jedoch nicht, wir müssen auf eine Spezialisierung verzichten. Spezialisten sind nötig, dürfen nur nicht unersetzbar sein. Deshalb darf der Anspruch nicht sein, alle Spezialisten “selbst herzustellen”. Das ist die Herausforderung.

Natürlich ist es einfacher, “alle sollen möglichst gleich sein” zu denken. Das macht weniger Planungsaufwand. Und das ist auch ok. Nur darf ein Team dann nicht erwarten, wenn es in vielen Disziplinen “gleichgeschaltet ist”, in allen auch Höchstleistungen zu erbringen. Das Prinzip “Wissensinseln vermeiden” sollte daher nicht pauschal allein Anwendung finden.

image

image PS: Ivan Engler wird übrigens auf der prio.conference die Keynote halten. Zumindest wenn er dann nicht gerade in Hollywood weilen muss. Doch ich bin da mal zuversichtlich…

Montag, 10. Mai 2010

Kaffeehauskonsultation in München

Umfrage: Kaffee ist Teil einer ausgewogenen Ernährung Am Donnerstag 27.5.2010 ist es wieder so weit: kostenlose Beratung in Sachen .NET Softwareentwicklung in München. Von 10h bis 17h können Sie mich in meiner “Praxis” konsultieren. Die öffne ich im Café Mozart und bin gespannt, worüber wir uns unterhalten. Sie finden mich dort “im Hinterzimmer” für die Kaffeehauskonsultation.

Bringen Sie Ihren Laptop mit, dann können wir uns auch Ihren Code ansehen, falls nötig. Einen Block für Diagramme habe ich dabei. Und dann reden wir über Softwarearchitektur, Clean Code Developer und andere spannende Themen.

Sie können natürlich einfach so vorbeischauen. Besser ist´s jedoch, wenn Sie mir schnell eine Email schicken, damit wir einen Termin abmachen. Jedes Gespräch sollte nicht länger als 75 Minuten dauern, damit auch andere eine Chance auf Konsultation bei Kaffee haben.

image

Donnerstag, 6. Mai 2010

Asynchrone Kommunikation mit EBCs statt “Async-Pattern”

Freut mich, dass Thomas Christian im build broken Blog eine Lanze für die asynchrone Kommunikation mit Events gebrochen hat. Schade allerdings, dass der Code dafür so umständlich aussieht.

Kommunikation à la Async-Pattern

Ein kleines Formular fordert von einem Calculator die Quadratur einer Zahl an: m_calculator.CalcAsync(number). Was würden Sie dann im Calculator für Code erwarten? Irgendwo sollte number * number stehen. Klar. Und ansonsten? Schauen Sie einmal, wie der Calculator bei Thomas aussieht:

image
image

Puh… Da ist es gar nicht so leicht, das zu finden, worauf es eigentlich ankommt, finde ich. Sehen Sie die kalkulierende Businesslogik? Und was macht der Rest des Codes? Der ist dazu da, ein Pattern zu implementieren.

Wenig Code für das Wesentliche, viel für Infrastruktur – das hört sich für mich nicht so gut an, auch wenn ich das Kommunikationsmodell voll unterstütze.

Ich schlage daher einen anderen Weg vor. Hier meine Version der Szenarios:

Kommunikation à la Event-Based Components

Zunächst die Businesslogik:

image

Hier finden Sie keine Rauschen durch Infrastrukturcode. Der Fokus ist ganz klar auf der Problemdomäne. Aber Achtung: Ich habe keine Funktion für Calc() geschrieben, sondern eine Prozedur, d.h. eine Methode ohne Rückgabewert. Das Resultat liefert die Methode dann über einen Event: DeliverCalcResult(). So ist das bei Event-Based Components.

Jetzt der Client-Code im Formular:

image

Auch hier kein Rauschen durch Infrastruktur. Nicht mal der Calculator wird als Komponenteninstanz injiziert. Das Formular kennt keinen Calculator. Es ist völlig unabhängig von einer solchen Funktionseinheit. Es äußert Berechnungswünsche lediglich über einen Event – CalcRequest – und empfängt Berechnungsresultate mit OnCalcResult().

Das ist im Prinzip sehr ähnlich wie bei Thomas. Im Detail ist es jedoch anders, da das Formular eben auf die Kenntnis einer Service-Funktionseinheit verzichtet. Die wird bei Thomas noch im Formular instanziert.

Und wie kommt es nun zu Berechnungen, wenn das Formular den Calculator nicht kennt? Beide Funktionseinheiten werden von außen verdrahtet. Damit sind Logik und Abhängigkeiten als Concerns sauber getrennt.

image

Voilà! Jetzt kann das Programm starten und berechnet Quadratzahlen. Zuerst werden die Funktionseinheiten instanziert. Dann werden die Eventhandler in die Events gesteckt. Mehr ist nicht nötig. Keine Funktionseinheit weiß von der anderen. Nur der Verdrahtungscode kennt sie.

Asynchrone Kommunikation

Die kleine Anwendung funktioniert nun zwar, aber synchron. Thomas Beispiel will ja aber gerade zeigen, wie einfach asynchrone Kommunikation mit Events ist. Was muss ich also tun, um meinen Nachbau ebenfalls asynchron zu machen?

Asynchronizität erfodert keine (!) Veränderung an der Geschäftslogik oder im Frontend. Das halte ich für den wesentlichen Vorteil meines Vorgehens. Ich muss lediglich die Verdrahtung anpassen:

image

Ich instanziere zwei kleine Standard-Funktionseinheiten, eine, die Events asynchron weiterleitet und eine, die Events zurück in den GUI-Thread bringt. Diese Funktionseinheiten schalte ich zwischen den Dialog und den Calculator. War die Verbindung z.B. bisher direkt

dlg.CalcRequest = calc.Calc;

so ist sie nun indirekt:

dlg.CalcRequest = asyncProcessAsynchronously;
async.OnAsynProcessing = calc.Calc;

Die Standard-Komponenten sind natürlich auch Event-Based Components, d.h. Input erhalten sie über Eventhandler und Output generieren sie mittels Events.

Das war´s. Mehr ist nicht zu tun. Die Geschäftslogik läuft jetzt im Hintergrund. Und die Ergebnisse kommen problemfrei im Vordergrund an. Wie das funktioniert? Egal :-) Das ist die Magie der Standard-Komponenten.

Fazit

Asynchrone Kommunikation mit Events ist eine gute Sache, da stimme ich Thomas zu. Aber man sollte diese Sache dann auch so einfach wie möglich halten. Das bedeutet für mich, dass ich in der Geschäftslogik (oder auch im Frontend) von technischen Klimmzügen, die die Asynchronizität herstellen, nichts sehen will. Geschäftslogik muss frei von diesem Concern sein. Der steckt am besten in wiederverwendbaren Standard-Komponenten. Event-Based Components bieten dafür eine gute Grundlage.

P.S.

Na, schön. Hier nun doch noch der Code für die Standard-Komponenten. Damit keiner sage, der sei bestimmt total kompliziert ;-)

image

image

Dieser Code ist wiederverwendbar. Er folgt nur dem Event-Based Component Muster für die Kommunikation. Deshalb kann er mit beliebigen Pins von anderen Komponenten zusammengesteckt werden, ohne dass die etwas davon merken. Das ist Composability.

Montag, 3. Mai 2010

Nullonade – Monade statt Null

In der Diskussion um Null als Rückgabewert gab es ein Codeschnippsel, mit dem Thomas Bandt zeigen wollte, dass der TryGetUserById(…)-Vorschlag nicht zwangsläufig zu intuitivem Code führt. Ich formuliere das Beispiel hier mal etwas knapper:

User tmpUser;
bool isAuth = repo.TryGetUserById("987", out tmpUser) &&
              sec.CheckUser("somepassword", tmpUser);

Als Problem sieht Thomas – durchaus zurecht – die Abhängigkeit von CheckUser() von einem Seiteneffekt. Die globale Variable tmpUser muss vor Aufruf gesetzt sein, was innerhalb des logischen Ausdrucks nicht ganz so offensichtlich ist.

Etwas deutlicher wäre die Abhängigkeit der Reihenfolge beider Methodenaufrufe, wenn der Ausdruck traditioneller als Schachtelung formuliert wäre:

bool isAuth;
User tmpUser;
if (repo.TryGetUserById("987", out tmpUser))
    isAuth = sec.CheckUser("somepassword", tmpUser);
else
    isAuth = false;

Doch eigentlich sind Schachtelungen ja “böse” ;-) Sie erhöhen die (zyklomatische) Komplexität des Codes. Also vielleicht lieber so:

User tmpUser;
bool isAuth = repo.TryGetUserById("987", out tmpUser);
isAuth = isAuth && sec.CheckUser("somepassword", tmpUser);

Das mag besser lesbar sein – doch das Grundproblem ist eigentlich nicht gelöst. Das besteht in der Abhängigkeit selbst, also letztlich in der zu beiden Methoden globalen Variablen tmpUser. Die ist nötig, weil Thomas keine Exception werfen möchte, falls es den angeforderten User nicht gibt. Wäre das anders, könnte er nämlich auch ohne diese Variable formulieren:

bool isAuth = sec.CheckUser(“somepassword”,
                            repo.GetUserById(“987”));

Das ist zwar wieder geschachtelter Code, doch irgendwie sind wir sowas ja gewohnt ;-)

Get into the flow

So richtig cool finde ich das aber alles noch nicht. Deshalb schlage ich mal eine weitere Alternative vor. Wäre es nicht am allerschönsten, wenn wir es so schreiben könnten:

var isAuth = repo.GetUserById(“987”) |> sec.CheckUser(“somepassword”);

Das ist natürlich Pseudocode. Aber schön wärs, oder? GetUserById() würde immer noch keine Exception werfen und trotzdem (!) würde das Ganze immer funktionieren.

In F# geht das. Da gibt es so einen Pipe-Operator |> und noch etwas anderes, das nötig ist, einen Option-Typ. Aber in C# sitzen wir erstmal auf dem Trockenen :-(

Zum Glück können wir daran etwas tun. Wir können mit etwas Vorarbeit auch in C# so einen “Flow” von Anweisungen schreiben. Hier meine C#-Version:

bool isAuth = repo.GetUserById("987")
                  .Continue(user => sec.CheckUser("somepassword", user))
                  .WithDefault(false);

Liest sich doch gar nicht schlecht, oder? Es soll ein User geladen werden und danach soll geprüft werden, ob der User ein bestimmtes Passwort hat. Ist das so, dann ist das Ergebnis true, ansonsten false.

Die Sequenz der Verarbeitungsschritte in unserem Kopf findet sich im Code wieder – ohne dass wir eine temporäre Variable bräuchten. Naja, nicht ganz: denn der user-Parameter der Lambda-Funktion ist eine solche temporäre Variable. Doch die ist nicht global, sondern lokal. Es gibt also keine schwer zu überblickenden Abhängigkeiten.

Optionen als Zwischenwerte

Möglich ist so eine Formulierung, wenn als Resultat von GetUserById() kein User (oder gar Null), sondern ein sog. Option-Wert zurückgeliefert wird. Den gibt es in F# gratis; für C# können wir ihn so bauen:

public class Option<T>
{
    public Option()
    {
        this.IsSome = false;
    }

    public Option(T some)
    {
        this.Some = some;
        this.IsSome = true;
    }

    public T Some { get; private set; }

    public bool IsSome { get; private set; }
    public bool IsNone { get { return !IsSome; } }

    …
}

Der Trick an Optionswerten ist, dass es immer eine Instanz gibt. Es geht also nicht um Objekt oder Null, sondern um Options-Objekt gefüllt oder nicht gefüllt. Wenn es gefüllt ist, dann liefert IsSome true, wenn nicht, dann liefert IsSome false bzw. IsNone true. Zugriff auf den Wert gibt die Some-Property.

var optInt = new Option<int>(42);
Console.WriteLine(“{0}, {1}”, optInt.IsSome, optInt.Some);

gibt aus:

true, 42

Mit so einem Typen kann GetUserById() nun umformuliert werden zu:

Option<User> GetUserById(string id) {…}

Die Methode liefert immer ein Option-Objekt zurück und die Umgebung muss prüfen, ob etwas drin steckt oder nicht:

var optUser = repo.GetUserById(“987”);
if (optUser.IsSome)
    …

Das ist fast so wie eine Prüfung auf Null – aber besser. Denn mit einem Option-Objekt kann man immer weiterarbeiten.

Logik verstecken in einer Monade

Das Ziel ist immer noch der “Flow”, d.h. globale Variablen und Prüflogik auf unerwünschte Ergebnisse zu verstecken. Weil nun immer ein Option-Objekt vorliegt, können wir darauf immer eine Methode aufrufen

public class Option<T>
{
    …

    public IEnumerable<Option<TOutput>> Continue<TOutput>(Func<T, TOutput> processor)
    {
        return new[] {this}.Continue(processor);
    }
}

und auch noch Erweiterungsmethoden in Anschlag bringen

public static class OptionExtensions
{
    public static IEnumerable<Option<TOutput>> Continue<TInput, TOutput>(
                                     this IEnumerable<Option<TInput>> values,
                                     Func<TInput, TOutput> processor)
    {
        return values.Where(v => v.IsSome)
                     .Select(v => new Option<TOutput>(processor(v.Some)));
    }

    public static TInput WithDefault<TInput>(
                                     this IEnumerable<Option<TInput>> values,
                                     TInput defaultInCaseOfNone)
    {
        return (values.FirstOrDefault() ??
                     new Option<TInput>(defaultInCaseOfNone)).Some;
    }
}

Ich denke, damit habe ich eine Monade definiert, d.h. ein “Dings”, mit dem sich quasi unsichtbar ein Kontext um mehrere Anweisungen wickeln lassen kann.

Dass ich dafür auf IEnumerable<> zurückgegriffen habe, ist lediglich meiner Faulheit geschuldet ;-) (Mit IEnumerable<> kriegen ist nämlich die Verkettung geschenkt, weil der Typ selbst schon eine Monade ist.) Ebenso die Methode Continue() der Option-Klasse. Hätte ich mir mehr Mühe gegeben, hätte ich statt IEnumerable<> eine spezielle Monadenklasse gebastelt. Das wäre sauberer gewesen.

Für den Punkt, den ich hier rüberbringen wollte, geht es aber auch so, würd ich sagen. Ich möchte einfach einen weiteren Weg aufzeigen, ohne Null leben zu können – und dadurch lesbaren Code zu bekommen. Die Verkettung könnte noch weiter gehen, falls mehr “Transformationsschritte” nötig wären, die immer wieder Output erzeugen, der Input für den nächsten sind. Die Leistung der Monade besteht darin, die Schritte abzubrechen, falls kein Ergebnis geliefert wird (der frühere Null-Fall). Die verbirgt die Logik der Prüfung, ob ein Zwischenergebnis vorliegt und es noch weitergehen soll.

Die C#-Mittel bleiben dabei immer etwas hinter denen von F# zurück. Doch mir scheint “das Denken in Option-Werten” durchaus den einen oder anderen Versuch wert. Wie gesagt, mit etwas mehr einmalig aufgewandter Zeit, ist das auch noch eleganter ;-)

Sonntag, 2. Mai 2010

Es hilft nichts, dass es darauf ankommt – nicht nur beim Null-Problemo [OOP 2010]

Erst ein Feiertag, jetzt ein Sonntag und die Diskussion um “Null oder nicht Null” geht weiter. Als hätten diese Softwareentwickler nichts anderes zu tun… ;-) Ilker hat versucht, einen ausbalancierenden Schlussstrich unter die Diskussion zu ziehen, um uns wenigstens ein Rest schönes Wetter genießen lassen zu können. Doch mich wurm da noch etwas. Und weil der Stein, an dem ich mich da anstoße, bei ihm so ausdrücklich in seinem Blogartikel zu lesen ist, greife ich auch am Sonntag Morgen nochmal in die Tasten:

Woran ich mich in dieser Diskussion – die allerdings nur stellvertretend für viele andere ist – störe, das sind Aussagen wie

“Es kommt auf den Anwendungsfall an. Die beliebte ‘It-Depends’-Weisheit streckt das Thema mit geballter Kraft nieder.”

und

“So oder so – beides ist machbar und beides hat seine Berechtigung.”

Ich kann das einfach nicht mehr hören. (Sorry, Ilker, ist nix Persönliches. Diese Formulierungen sind vielmehr ein Anti-Pattern unserer Branche.) Kommt irgendeiner mit ‘ner Frage, was er tun soll – diese oder jene Technologie oder dieses oder jenes Sprachfeature oder diesen oder jenen Lösungs weg? –, dann antwortet die Branche unisono: “It depends!”, “ Kommt darauf an… “, “Im Prinzip ist alles möglich.”

Was soll denn das? Ja, ja, ich mache so einen Spruch auch mal. Am Ende sind diese Aussagen aber doch ein Armutszeugnis. Vor allem aber: Sie helfen nicht. Niemandem. Vor allem nicht dem, der gefragt hat.

“Es kommt darauf an…” ist eine triviale Antwort. Sie ist trivial und nutzlos, weil sie quasi immer wahr ist. Es kommt immer im Leben darauf an. Auf irgendwas. Wo Wahlmöglichkeiten bestehen, da kommt es immer auf den einen oder anderen Faktor an, ob die eine oder andere Möglichkeit gewählt werden sollte. Diese Faktoren mögen subjektiv sein, also rein persönlich, oder objektiv, d.h. irgendwie aus der Problenstellung bzw. der angestrebten Lösung abgeleitet.

Also: Leute, ihr habt/wir haben immer Recht, wenn wir sagen “Es kommt darauf an…”. Super. Lasst uns darauf einen trinken. Und dann lasst uns endlich damit aufhören. Wer “Es kommt darauf an…” sagt (oder etwas Sinngleiches), der zahlt in Zukunft 5 EUR in das Phrasenschwein. Wie wäre das? Wir kommen einfach nicht voran mit solchen Sprüchen. Sie dienen nie-man-dem. Wir bringen weder den einzelnen Frager noch “unsere Kunst” damit voran.

Ok, so ein Spruch geht also nicht mehr. Was aber dann? Wir sollten, wann immer wie reflexartig “Es kommt darauf an…” sagen wollen, innehalten. Mund zu, Denkmaschine anwerfen… Das halte ich für den ersten Schritt. Nachdenken, ob denn aus einer Problembeschreibung sich nicht doch irgendwie ein Hinweis auf eine vorzuziehende Lösungsmöglichkeit ergibt.

Ja, Nachdenken verbraucht auch Kalorien, aber wir sollten uns diesen Sport gönnen. Der bringt uns selbst und “unsere Kunst” nämlich voran. Die Ergebnisse sind nämlich immer positiv: Schärfung der Wahrnehmung, Reflexion des eigenen Tuns, Ausarbeitung von Regeln.

Eine Regel hat sich ja auch in dieser Diskussion um das Null-Problemo herauskristallisiert:

Null-Regel #1: Man darf Null benutzen und auch als Wert zurückgeben – aber Vorsicht! Erst prüfen, ob es nicht auch anders geht.

Das ist doch schon mal ne schöne Sache, oder? Darin sind wir uns einig. Prost!

Nur verstehe ich nicht, warum Ilker dann schreibt

“Für mich gibt es beim Umgang und bei der Anwendung von Null keine Faustregel.”

Denn diese Regel ist doch eine Faustregel. Sie lautet: Setze Null eher nicht ein. Punkt. Warum sollten wir das runter spielen.

image Mein Gefühl ist, dass “die Branche” da an einem kollektiven mangelnden Selbstvertrauen leidet. “Man” traut sich nicht, einen Pflock in den Boden zu hauen. Denn wer Pflöcke in den Boden haut und die dann auch  noch mit Latten zu einem Areal verbindet, der läuft Gefahr, dass andere einen Streit von diesem Zaun brechen. Und das will “man” doch nicht. Ne, Streit ist doof.

“Wer Regeln formuliert oder verbreitet, wird mit Stirnrunzeln oder gar flame comments bestraft.” – so lautet das unausgesprochene Gesetz.

Regeln stören den Seelenfrieden dessen, dem sie “aufgedrückt” werden. Oder sie stören womöglich sogar den Seelenfrieden dessen, der sie aufstellt. Denn wer Regeln formuliert, der muss sich ja auch daran halten. Will “man” das aber? Wer weiß, vielleicht findet “man” es morgen bequemer, es anders zu tun – und dann wäre die Regel hinfällig. Aaargh… Also besser mal keine Regel aufstellen. Und schon gar nicht anderen die Befolgung einer Regel nahelegen. Denn was auch, wenn die damit nicht zum Erfolg kommen? Dann sind sie sauer auf “einen”.

Das sind natürlich sehr verständliche Regungen. Aber: Leute, Leute, so kommen wir nicht voran. Niemand behauptet, dass “alles” reglementiert werden sollte oder gar könnte. Angst, in der “künstlerischen Programmiererfreiheit” eingeschränkt zu werden, ist völlig (!) unbegründet. Maler, Bildhauer, Schauspieler, Musiker… alle sind vielmehr erst Künstler durch die Regeln ihres Metiers. Ohne Regeln keine Kunst. Denn Kunst ist sozusagen “mit und in den Regeln schaffen und spielen”. Ohne Regeln ist alles keine Kunst. Wir schätzen einen Meister seines Metiers dafür, dass er “gar künstlich” (d.h. soviel wir “nach den Regeln der Kunst” oder “virtuos”) etwas (er)schafft.

image Wer am leeren Tisch sitzt und hört, “Schaffe mal ein Kunstwerk”, der hat es schwer, nicht leicht. Sitzt er aber vor einer Staffelei mit Ölfarbenpallette und Pinsel in der Hand und bekommt den Auftrag “Schaffe ein impressionistisches Landschaftsbild”, der kann loslegen. Öl, Pinsel, Leinwand, Stilrichtung, Motiv: das sind Begrenzungen mit impliziten Regeln, die erst die Möglichkeit bieten, Künstler zu sein.

(Ja, ja, es gibt immer mal wieder auch Künstler, die dadurch groß werden, dass sie (scheinbar) regellos oder gegen die Regeln arbeiten. Aber Achtung: Erstens können sie sich nur profilieren im Kontrast zu etablierten Regeln der Kunst, zweitens schaffen diese Künstler durch ihr Tun (bewusst oder unbewusst) wieder neue Regeln, und drittens sind solche Regelwerk sprengenden bzw. ausweitenden Künstler die Ausnahme. Wer mein, ohne Regeln auszukommen, läuft also Gefahr, sich zu überschätzen.)

Bottom line: Ohne Regeln geht es nicht. Und jeder, der in einer Situation sitzt, wo er nicht recht weiter weiß, der sehnt sich nach einer Regel, die ihn leitet. Warum also diese branchenweite Ambivalenz? Einerseits Regeln suchen für die eigene Anwendung, andererseits aber keine Regeln formulieren wollen, wenn “man” gefragt wird.

imageOhne Regeln ist das Verhalten ein Rumgeeiere wie hier von Ilker trefflich beschrieben:

“Ich gebe in einigen Methoden NULL zurück. Meistens genau dann, wenn ich wirklich damit ausdrücken möchte, dass etwas katastrophales passiert ist. Ich finde es sehr schwerwiegend, NULL als Zuweisung oder Rückgabe stehen zu lassen – aber ich mache es manchmal ganz bewusst.”

Ja, was denn nun? Keine Faustregel, aber “manchmal ganz bewusst”? Wie geht das? Bewusstsein erfordert (!) einen Raum, in dem es sich eben bewusst verortet durch Entscheidungen. Und die Wände dieses Raumes bestehen (zumindest zum Teil) aus… Regeln. Die mögen sehr speziell sein, aber immer noch sind es Regeln, die man dann auch äußern kann, um sie zur Diskussion zu stellen.

Thomas hatte das in seinem ursprünglichen Blogartikel getan:

“Außerdem erwarte ich von jeder Methode null als Rückgabewert für den Fall, dass keine Daten in der Datenbank gefunden wurden.”

Jede Methode (seines Repositories) liefert bei Erfolg ein Objekt und bei Misserfolg Null. So war seine Regeln. Ob die gut oder schlecht ist, sei mal dahin gestellt. Das wurde ja auch ausführlich diskutiert. Zumindest war das eine Regel basierend auf einer bewussten Entscheidung. Die hat er geäußert. Nur so konnte darüber ein Diskurs beginnen. Wunderbar.

Ilker hingegen sagt, er sei bewusst – eine Regel (außer der obigen Null-Regeln #1) mag er aber eben nicht benennen. Das finde ich sehr, sehr schade. Denn so – ich wiederhole mich – kommen wir eben nicht voran.

Oder? Hoppla, jetzt hab ich mich doch durch Ilkers Statement, er hätte keine (Faust)Regel verwirren lassen. Natürlich hat er welche. Die Regel #1 und auch noch seine persönliche Regel:

Null-Regel #2 (von Ilker; noch zu diskutieren): In Katastophenfällen darf Null zurükgegeben werden.

Das ist doch mal eine Aussage. Darüber kann man diskutieren. Aber nicht hier.

@Ilker: Vielleicht magst du ja in einem weiteren Blogartikel ausführen, was Katastrophenfälle sind und warum dann Null als Rückgabewert erlaubt ist und wie zwischen Null und Exceptions als Mittel zur Anzeige von Katastophenfällen entschieden werden sollte. Darüber würde ich gern mehr hören.

Ilker hat also Regeln (mindestens zwei), zieht sich aber darauf zurück, dass “die beliebte ‘It-Depends’ Weisheit” im Falle Thomas “alles niederstreckt”. Warum? Warum keine klare Aussage, keine Empfehlung mit Verweis auf eine seiner Regeln? Weiß Ilker nicht mehr weiter? Das glaube ich nicht.

Ich möchte ihm stellvertretend für uns alle zurufen: Nicht verzagen! Mach doch eine klare Aussage. Habe eine Präferenz. Zeige Kontur. Mach dich sichtbar – ja, und auch angreifbar. Haue einen Pflock in den Boden.

Denn niemand wird dich oder irgendwen für soetwas verhaften. Entweder ist die Empfehlung für den konkreten oder auch allgemeinen Fall richtig/praktikabel – oder es stellt sich im Diskurs heraus, dass sie es nicht ist. Dadurch können doch dann aber alle nur gewinnen. Und niemand steht deshalb schlechter da. Auch nicht der, der die Regeln/Empfehlung ausgesprochen hat.

Niemand muss ja auch seine Regel/Empfehlung kampflos ausgeben. Nur weil ein anderer damit nicht übereinstimmt, heißt das nicht, das man falsch liegt. Solange wir einen Diskurs führen, also sachlich bleiben, solange kommen wir voran – und können am Ende auch mal unterschiedliche Meinungen behalten. In der Malerei gibt es Schulen, in der Programmierung kann es die auch geben. Da könnte es z.B. die “Null geht gar nicht, nie, nimmer!”-Schule geben oder die “Null ist überhaupt kein Problem”-Schule oder die “Null mit Vorsicht”-Schule oder die “Null nur mit Vorsicht und mit folgenden Regeln”-Schule.

image Ich gehöre – soviel kann ich sagen – zur letzteren. Deshalb hier mein Pflock im Boden:

Null-Regel #3 (Ralfs Vorschlag): Null darf nur Rückgabewert sein, wenn Null zur selben Kategorie gehört wie ein Nicht-Null Rückgabewert.

Darüber können wir gern diskutieren. Einen Anfang habe ich hier gemacht. Also: Klare Aussage von mir, kein Rumgeeiere. Und jetzt die Argumente dagegen. Aus der Community. (Zur Regel #2 sage ich etwas, wenn Ilker sie begründet. Hier nur soviel vorab: Ich bin dagegen ;-)

Und jetzt noch ein letzter Schwenk zurück zum Allgemeinen. Wir brauchen also Regeln. Wir sollten uns der Reflexäußerung “Es kommt darauf an…” enthalten. (Auch das ist übrigens eine Regel ;-) Noch ein Pflock von mir im Boden.) Besser, wir schalten in solchen Situationen erstmal die Denkmaschine an. Analyse hilft.

Ebenfalls hilfreich ist allerdings auch: Fragen und Zuhören! Denn so mancher, der sagt “It depends”, leidet womöglich nicht unter mangelndem Selbstvertrauen oder Denkfaulheit, sondern schlicht unter Unwissen. Er weiß nicht genug, um eine Entscheidung zwischen den Alternativen klar treffen zu können.

Dem kann dann durch Nachfragen und genaues Hinhören abgeholfen werden. Wenn man sich denn als Befragter überhaupt interessiert. Womit wir bei einem weiteren Grund für “Es kommt darauf an…”-Antworten sind: Desinteresse. “Was interessiert mich das Problem des anderen? Ich hab schon selber genug Probleme. Wenn mir doch mal einer helfen würde…” usw.

Hieraus ergibt sich auch eine Empfehlung für Hilfesuchende: Wer fragt und “It depends” als Antwort bekommt, der sollte nicht zufrieden sein. “It depends” ist trivial und beliebig. Wer fragt, sollte die Antwort als Aufforderung verstehen, mehr über das Problem zu erzählen oder überhaupt mal festzustellen, ob der Befragte überhaupt ein Interesse an einer Antwort hat. (Von einer Kompetenz zur Antwort sehe ich hier mal ab. Jeder ist kompetent zumindest insofern, als dass er dem Fragenden ein Spiegel sein kann. Auch das hilft oft.)

Fazit: Es hilft also nichts, dass wir die Hände in die Luft werfen und sagen “Es kommt darauf an…” Diese Phrase können wir uns in Diskussionen sparen. Sie macht nur Sinn als Replik auf eine ebenso sinnlose allgemeine Frage. Beispielfrage: “Sollte man die Daten mit einem RDBMS oder einem ODBMS speichern?”, Antwort: “Es kommt darauf an…”

In solche einem Fall mag die allgemeine Frage allgemein mit einer Phrase beantwortet werden, um dadurch aufzuzeigen, dass schon die Frage schlecht formuliert war. In dem Fall ist “Es kommt darauf an…” aber sozusagen ein Stilmittel – dass sofort als solches aufgedeckt werden sollte: “Es kommt darauf an… Das sage ich, weil Ihre Frage zu allgemein ist. Erklären Sie mir bitte genauer, worum es geht.”

“Es kommt darauf an…” ist quasi immer richtig und hilft deshalb nicht. Wir müssen weg von dieser Phrase hin zu mehr Nachdenken und mehr Zuhören. Und daraus müssen sich mehr konkrete Regeln ergeben, die auf konkrete Fälle angewandt werden können. Ob das wenige oder viele, einfache oder komplizierte Regeln sind, ist erstmal egal. Wir brauchen sie als Fundament für “unsere Kunst”.

Niemand behauptet auch, dass die so bewusst erarbeiteten Regeln starr sein sollten. Im Gegenteil. Sie sollen lebendig bleiben im Rahmen eines Diskurses. Zwischendurch mal Ruhe ist auch gut. Einfach mal die Regeln lernen und anwenden, bevor man sie hinterfragt. Aber dann auch gern immer wieder Infragestellung. Die Zeiten ändern sich, also dürfen sich auch die Regeln ändern. Manche langsamer, manche schneller.

Unzweifelhaft ist jedoch, dass wir sie brauchen. Ich glaube sogar, dass wir als Branche unterspezifiziert sind mit Regeln. Deshalb habe ich auch www.clean-code-developer.de (CCD) mit gegründet. Und der Erfolg der Initiative gibt meiner Vermutung recht, würde ich sagen. Denn CCD ist eine Sammlung von Regeln und darauf stehen offensichtlich mehrere Tausend Entwickler, wenn ich mal die Mitgliedszahlen in den Foren und die vergebenen Armbänder zusammenrechne.

So, nach diesem Ausflug ins Grundsätzliche gern wieder zurück zum Konkreten: Da es beim Null-Problemo genauso “darauf ankommt” wie sonst im Leben, stellt sich immer noch die Frage: Worauf kommt es denn an? Was sind die Regeln für die Null-Verwendung? Was sind damit die Eigenschaften eines Szenarios, die geklärt werden müssen, um zu entscheiden, welche Regel zum Einsatz kommt?

Samstag, 1. Mai 2010

Sollte Architektur wirklich emergieren? [OOP 2010]

In Objektspektrum 3/2010 steht ein Artikel auf der Höhe der Zeit: “Emergente Architektur: Der machtlose Architekt”. Denn davon spricht man auch hier oder hier. Und woanders mag es auch Emergent Design heißen.

“Emergenz” scheint ein neues Zauberwort zu sein. Es bedeutet soviel wie Entstehung von etwas Ganzem, ohne dass dieses Ganze so geplant worden wäre. Eine Termitenbau entsteht auf diese Weise oder geordnete Menschenströme in einer Einkaufsstraße oder sogar die erfolgreiche Jagd eines Löwenrudels.

Klingt gut, oder? Wäre doch toll, wenn Softwareentwicklung nicht länger krampfhaft und bewusst versuchen müsste, der ewig nörgelnden Forderung nach einer sauberen Architektur nachzukommen, sondern sie irgendwie “wie von selbst” entstehen lassen, sie emergieren lassen könnte.

Zugegeben, eine schöne Vorstellung. Aber glauben tue ich an sie genauso wenig wie an die Rettung der Welt durch CASE, SOA oder O/R Mapper. Trotz aller Erkenntnisse der Komplexitätsforschung sehe ich weiterhin die Notwendigkeit zur Planung von Architektur. Denn:

  • Emergenz ist trivial: Wenn Systeme genügend unbekannt oder genügend groß in Bezug auf den Kenntnishorizont eines Teams sind, dann kann ihre Architektur nicht “auf einmal” geplant werden. Sie entwickelt sich vielmehr über die Zeit in Reaktion auf neue Erkenntnisse und Anforderungen. Jeder Entwicklungsschritt folgt dabei (hoffentlich) den lange bekannten Prinzipien “guter Architektur”. Jeder einzelne Architekt hat dann über die Zeit nur einen Teil zum großen Ganzen beigetragen.
    Emergenz ist letztlich also kein neues Phänomen, sondern nur ein modischer Begriff für Evolution. Weniger Rede von Emergenz und mehr von Evolution könnte helfen, nicht schon wieder nach einer neuen Silberkugel zu suchen.
  • Emergenz ist unvermeidbar: Auch wenn die Kenntnis über das zu realisierende System groß ist, endet die Verantwortung eines Architekten irgendwo. Er ist ja Architekt und nicht Entwickler. Und Planungspapiere sind kein Code. Bei der Umsetzung der Architekturplanung kann daher immer noch einiges passieren und passiert auch. Architekturvorstellungen werden selten 1:1 umgesetzt. Die Architektur eines Systems ist damit immer mehr oder weniger ungeplant und Resultat vieler kleiner Entscheidungen vor Ort während der Implementation.
  • Emergenz ist schwer planbar: Soll ein makroskopisches Ergebnis (z.B. Architektur) emergent entstehen, sind passende microskopische, einfache Regeln zu definieren. Solche Regeln a posteriori durch Analyse von Ergebnissen zu finden, ist eine Sache. Sie jedoch a priori zu postulieren, eine andere. Das makroskopische, am Ende recht simple Verhalten von Schwärmen hat schon Forscherjahre in der Analyse gekostet, auch wenn nur 3 Kernregeln dabei gerausgekommen sind. Was ist dann für so etwas komplexes wie Softwarearchitektur zu erwarten? Ich bin sehr im Zweifel, ob die Softwarekunst darauf schon eine Antwort hat. Entwickler mit TDD vor sich hinwerkeln zu lassen, mit S.O.L.I.D kräftig voran zu schreiten und darauf zu vertrauen, dass Featureteams es schon richten werden, halte ich für zuwenig. Damit sind zwar Richtschnüre auf der Microebene gespannt – doch die führen nicht so unausweichlich wie die Regeln eines Sardinenschwarms zu einem evolvierbaren großen Ganzen.

Architektur braucht, so glaube ich, auf unabsehbare Zeit immer noch ein gerüttelt Maß an expliziter Planung “in der Mitte”. BDUF ist out, soviel ist klar. Gesamtplanungen sind womöglich nicht mal machbar. Microplanung ist ebenfalls kontraproduktiv; sie zerstört Motivation und Effizienz. Doch “in der Mitte” gibt es Raum und Notwendigkeit für explizite Architekturplanung. Denken und Planen hilft, da bin ich mir sicher. Immer noch. Ameisen oder Sardinen mögen nicht planen müssen. Aber “große Maschinen”, die sich auch noch ständig ändern sollen, die deshalb auf der Metaebene konstant änderbar/evolvierbar sein müssen, solche “Maschinene” “sich ergeben zu lassen” durch lokale Anwendung überschaubarer Regeln… das halte ich für zumindest eine verfrühte Vorstellung.

Denn wahre Emergenz" bedeutet eben keine Planung des großen Ganzen. Niemand malt ein Architekturdiagramm. Niemand hat eine Vorstellung von der Form des Ganzen – sondern immer nur von seinem Verhältnis zur Umwelt. Viele kleinste Entscheidungen auf Microebene ergeben – oh, Wunder! – ein wahrhaft elegantes und zweckmäßiges Ganzes. (Wobei Zweckmäßigkeit von Software immer einschließt, dass die nicht nur heute vorhanden ist, sondern auch für morgige Anforderungen leicht hergestellt werden kann.)

Damit komme ich sozusagen zum philosophischen Teil meiner Position:

Keine Ameise versteht das Ganze ihres Staates. Kein Mensch versteht mehr das Ganze einer Volkswirtschaft. Dasselbe mag für ein genügend großes Softwaresystem gelten. Das Internet könnte dafür ein Beispiel sein. So ist das halt, wenn etwas sehr komplex wird.

Das bedeutet im Umkehrschluss jedoch, dass das, was da so groß und komplex ist, was über die Köpfe der Individuen hinaus gewachsen ist, keine (oder nur wenige) von den Individuen planbare Eigenschaften hat. Wir das an der Finanzkrise, wir sehen das an den Entwicklungen im und um das Internet und die neuen Medien.

Wie können womöglich noch etwas Emergiertes erkennen. Wir können das Ganze beobachten. Aber wir können ihm als “Rädchen im Getriebe” keine spezifischen Eigenschaften mehr verordnen. Klar, wir schrauben am Ganzen herum. Jede unserer Handlungen verändert das Ganze. Aber es in eine funktionale Richtung zu bewegen oder auf der Metaebene es Flexibel zu machen… das sind geradezu titanische Aufgaben, deren Lösung unabsehbar ist.

Was bedeutet das für Software, wenn wir uns für sie wünschen, dass ihre Architektur emergieren möge? Mir scheint es, dass Emergenz nur um den Preis eines Kontrollverlustes zu haben ist. Aber wer möchte den schon erleiden? Software soll sehr konkrete Zwecke erfüllen, Architektur ist dafür die Basis. Wenn Architektur dann jedoch “nur” emergiert, wenn Architekten machtlos sind und das Ganze “sich ergibt” aus regelhaften Einzelaktionen… wie stellt ein Team dann sicher, dass der durch den Kunden vorgegebene Zweck zeitig wie nachhaltig erfüllt wird?

image Ergo: Solange wir noch Ziele ansteuern, können wir uns nicht auf Emergenz verlassen. Softwareentwicklung ist kein Selbstzweck. Also kann ihr Ergebnis nicht komplett einer Emergenz anheim gestellt werden.

Das bedeutet nicht, dass wir nicht immer wieder prüfen sollten, wieviel Planung/Kontrolle wann angemessen ist. Wir sollen nach Microregeln suchen, die helfen, Makroeigenschaften “einfach so” herzustellen. Doch um explizite Architekturentscheidungen kommen wir nicht herum. Architekten werden nicht überflüssig und degenerieren auch nicht zu reinen Prozessmoderatoren.

Ein wenig Bescheidenheit mag allerdings angezeigt sein. Eine Haltung der Akzeptanz der Vorläufigkeit hilft. Etwas weniger Kontrolle haben wollen, schadet nicht. Kollektive Intelligenz fördern, ist sicherlich ein guter Ansatz. Aber Planen und Denken bleiben Kernaufgaben von Architekten.