Foundations for Professionals .NET Professionals im Profil guide to C# guidgen.de

Blog

Nutze den Augenblick
und teile der Welt mit, was Du zu sagen hast.

Terminologie von EBCs

Sonntag, 8. August 2010, 23:42 Uhr
Permalink | Kommentare (8) | Kommentare als RSSRSS

Nach meinem ersten Eindruck von Event-Based Components habe ich vor einigen Tagen über den Nutzen von EBCs geschrieben. Als Schlüssel zum Verständnis sehe ich dabei den Aspekt, dass EBCs topologieunabhängig sind – in einen einzigen Satz zusammengefasst habe ich dies folgendermaßen formuliert:

Im Gegensatz zu klassischen Komponenten rufen EBCs keine Methoden anderer Komponenten auf, sondern stellen nur den Wunsch nach Weiterverarbeitung ihrer Daten in den Raum.

Eine Frage dazu habe ich jedoch noch nicht beantwortet: Wie sieht eine konkrete Implementierung einer solchen topologieunabhängigen Komponente aus?

Ich habe vor einigen Tagen ebenfalls darüber geschrieben, dass das Konzept von EBCs vergleichbar mit dem von Hardwarechips sei, und dass EBCs wie jene auch Input- und Output-Pins anbieten würden.

Die Frage lautet also, wie diese Pins in Code implementiert werden. Eine kurze Antwort darauf habe ich schon gegeben:

Input-Pins entsprechen klassischen Methoden, Output-Pins werden als Events deklariert, woher auch der Name der EBCs rührt.

Das bedeutet: Eine EBC ist zunächst nichts anderes als eine herkömmliche Klasse. Weder ist eine spezielle Basisklasse erforderlich, noch müssen spezielle Schnittstellen implementiert werden – eine EBC ist zunächst einfach nur eine Klasse.

Damit aus einer Klasse jedoch eine EBC wird, müssen von ihr drei Anforderungen erfüllt werden, die sich allesamt auf ihren Kontrakt – also die öffentliche Schnittstelle der Klasse – beziehen:

  • Methoden: Alle Methoden des Kontrakts verfügen über nur einen einzigen Parameter und verzichten auf einen Rückgabewert – ihr Rückgabetyp ist also void. Die Signatur jeder einzelnen Methode entspricht damit der Signatur des Action<T>-Delegaten. Diese Methoden stellen die Input-Pins dar und ermöglichen es, Requests an die Klasse zu stellen. Sind für einen solchen Request mehrere Parameter erforderlich, können diese in einem gemeinsamen Parameterobjekt gekapselt werden.
  • Ereignisse: Für manche Methoden des Kontrakts ist die Einschränkung auf void als Rückgabetyp problemlos – da sie ihre Aufgabe erfüllen und keinen Rückgabewert benötigen. Andere Methoden benötigen diese Möglichkeit jedoch. Für diese wird bei EBCs ein anderer Weg gewählt: Statt das Ergebnis direkt an den Aufrufer zurück zu geben, wird ein Ereignis ausgelöst, dem das Ergebnis als Parameter mitgegeben wird. Der Typ des Ereignisses entspricht auch hier wieder Action<T>, die Ereignisse an sich entsprechen den Output-Pins.

Zunächst mag dies ungewohnt erscheinen – der Sinn offenbart sich jedoch schlagartig, sobald mehr als eine EBC ins Spiel kommt: Es wird kein Verbund von Komponenten mehr benötigt, die untereinander funktionale Abhängigkeiten aufweisen. Statt dessen wird ein Fluss von Daten modelliert, bei dem Daten immer von einer EBC an die nächste weitergereicht werden.

Dieser Fluss wird modelliert, indem das Output-Pin einer EBC mit dem Input-Pin einer anderen EBC verbunden wird. Ein Methode mit Rückgabewert entspricht dann einfach zwei gegenläufig verdrahteten Input- und Output-Pins.

Damit ist die Topologieunabhängigkeit bereits umgesetzt – schließlich erfolgt die Verdrahtung der Ereignisse von außerhalb der EBCs, so dass diese gar nicht wissen, wer auf ein ausgelöstes Ereignis reagiert. Sie wissen noch nicht einmal, ob überhaupt jemand auf das Ereignis reagiert.

EBCs stellen also isolierte Funktionalität bereit, erhalten von irgendwoher Daten zur Verarbeitung, verarbeiten diese, und stellen diese wieder in den Raum zur weiteren Verarbeitung. Sie verhalten sich damit analog zu Chips: Auch diese erhalten von irgendwoher ihre Signale, verarbeiten diese, und senden Signale aus, ohne Kenntnis von vorhergehenden oder nachfolgenden Chips.

Natürlich können EBCs nicht nur sequenziell hintereinandergeschaltet werden: Neben dem sequenziellen sind prinzipiell auch alle anderen Signalflüsse denkbar, die sich mit Ereignissen modellieren lassen: So kann ein Ereignis beispielsweise auf mehrere ereignisbehandelnde Methoden gebunden werden, so dass es zu einer Verteilung der Daten kommt.

Es verbleibt die Frage, nach welchem Schema die Methoden und Ereignisse von EBCs benannt werden können. Ralf Westphal hat dazu in seinem EBC-Binder Konventionen definiert. Dies ist begrüßenswert, ermöglicht dies doch eine einfachere Entwicklung – allerdings gefällt mir persönlich der Vorschlag, Ereignisnamen mit dem Präfix On zu versehen, überhaupt nicht.

Schließlich ist das On-Prefix im Kontext von Ereignissen in .NET bereits anderweitig belegt, nämlich für die ereignisauslösenden Methoden. Deshalb habe ich für mich folgende Konventionen definiert:

  • Requests: Requestmethoden werden – unabhängig davon, ob sie ein Output-Pin ansteuern oder nicht – derart bezeichnet, wie man es auch klassischerweise machen würde. Eine Requestmethode kann also beispielsweise RunProcess oder aber auch LoadCustomer heißen, der Rückgabetyp ist aber stets void.
  • Ereignisse: Der Name des Ereignisses ergibt sich dann ebenfalls ganz klassisch auf Grund der zugehörigen Requestmethode. Ein Ereignis könnte also beispielsweise CustomerLoading oder CustomerLoaded heißen.

Von Verben wie Process oder Handle würde ich in den Namen der Requestmethoden von EBCs absehen – ebenso wie dies auch bei klassischem Code gilt. Das On-Präfix bleibt damit den ereignisauslösenden Methoden vorbehalten. Auf diese Art bewegt man sich trotz EBC-Ansatz ein wenig näher an der gängigen .NET-Terminologie, was EBCs –zumindest aus meiner Sicht – ein bisschen greifbarer macht.

Zu guter letzt bleibt noch die Frage, wer EBCs verdrahtet: Dies macht die Platine, auf der EBCs angeordnet werden – ganz so, wie auch die Leiterbahnen von Chips auf einer Platine verlötet werden. Da der Begriff Platine jedoch sehr hardwarelastig ist, weiche ich an dieser Stelle auf den Begriff Container aus.

Natürlich bleibt die Wahl der Terminologie letztlich jedem selbst überlassen. Vielleicht hilft die Übersetzung von Ralfs gewählter EBC-Terminologie in .NET-affine Begriff jedoch dem ein oder anderen beim grundlegenden Verständnis, weil man sich trotz einem neuen Konzept in syntaktisch vertrauten Gefilden bewegt.

Wie viel kosten Unittests?

Dienstag, 3. August 2010, 10:03 Uhr
Permalink | Kommentare (3) | Kommentare als RSSRSS

Vor rund zwei Wochen hat Thomas Bandt in seinem Blogeintrag TDD in der (meiner) Praxis – Wunsch und Wirklichkeit die Frage aufgeworfen, wie sehr Theorie und Praxis bei TDD auseinanderklaffen. Prinzipiell gesteht er TDD zunächst einen gewissen Charme zu:

Test Driven Development, wozu ich insbesondere „test first“ zähle, hat für mich einen gewissen Charme. Es ist zweifelsfrei so, dass dadurch die Architektur der eigenen Anwendung verbessert wird und viele kleine Fehler vermieden werden können.

TDD betrachtet er also prinzipiell – rein akademisch gesehen – als erstrebenswert. Doch dann äußert er seine Zweifel:

Die Frage ist nur: zu welchem Preis?

Er ist jedoch nicht der einzige, der sich mit dieser Frage beschäftigt: Hagen Siegel hat auf myCSharp.de den Thread Tatsächlicher Nutzen von Unit-Tests? begonnen. Die für ihn essenzielle Frage lautet:

Ich selbst habe Zeifel am Nutzen von Unit-Tests, wenn man den Aufand ins Verhältnis setzt. Führt der sachgemäße Einsatz von Unit-Tests tatsächlich zu qualitativ hochwertiger Software?

So wohl Thomas wie auch Hagen führen also den Preis beziehungsweise den Aufwand als Argument an und fragen sich, ob das Verhältnis zwischen diesem und dem Nutzen im richtigen Verhältnis steht.

Dieser Frage begegnet man in der Diskussion mit Entwicklern, die TDD noch nicht oder noch nicht durchgängig einsetzen, immer wieder. Reduziert auf ihre kürzeste Form lautet sie:

Wie viel kosten Unittests?

Häufig wird als Antwort impliziert, dass Unittests im Allgemeinen und TDD im Speziellen zu teuer seien, um es durchgängig und konsequent anzuwenden. Mich erinnert das an meine Argumentation vom vergangenen November, als auch ich mich gefragt habe: Wie viel Sinn machen Unittests?. Mein Fazit damals lautete:

Die Frage ist also nicht, ob eine 100%ige Testabdeckung wünschenswert ist – dies gilt rein von der Theorie her ohne jegliche Zweifel – sondern ob eine 100%ige Testabdeckung mit vernünftigem und vertretbaren Aufwand erreicht werden kann: Diese Frage kann durchaus mit Nein beantwortet werden.

Wie stehe ich heute zu dieser Antwort?

Für mein heutiges Empfinden sind all diese Fragen falsch gestellt. Die grundlegende Frage nach den Kosten sollte nämlich nicht

Wie viel kosten Unittests?

lauten, sondern vielmehr:

Wie viel kostet es, auf Unittests zu verzichten?

Ich will diese Frage an Hand eines aktuellen Beispiels beantworten. Derzeit arbeite ich an einem EBC-basierten Prototypen einer bestehenden Anwendung. Primär dient dieser Prototyp dazu, die Fähigkeiten von EBCs auszuloten – für mich ist es jedoch zusätzlich das erste Projekt, in dem ich konsequent und strikt nach 4-Step TDD vorgehe.

Gestern Abend habe ich bemerkt, dass ein Kontrakt nicht so entworfen war, wie er hätte sein sollen: Weder hat die Vererbungshierarchie noch hat die Terminologie gepasst. Da ich die Pfadfinderregel der Clean Code Developer-Initiative

Hinterlasse einen Ort immer in einem besseren Zustand als du ihn vorgefunden hast.

sehr schätze, habe ich beschlossen, den Kontrakt zu refaktorisieren. Da dieser Kontrakt eine sehr grundlegende Rolle in der Anwendung spielt und daher in vielen Projekten der Solution genutzt wird, hatte meine Refaktorisierung Auswirkungen auf nahezu die Hälfte der Projekte.

Nach rund 90 Minuten war meine Refaktorisierung so weit gediehen, dass der Compiler die Anwendung wieder übersetzen konnte. Früher, das heißt, in den Zeiten, in denen ich noch kein TDD angewendet habe, hätte ich die Anwendung nun vermutlich gestartet, um die wichtigsten Funktionen sicherheitshalber noch einmal zu testen: Funktioniert alles noch so, wie ursprünglich vorgesehen?

Dass Fehler bei einem derartigen Test potenziell unentdeckt bleiben, liegt auf der Hand – es ist schlicht und ergreifend nicht möglich, alle denkbaren Fälle durchzugehen. Dies ist weder zeitlich noch logistisch zu meistern, erst recht nicht nach jeder Änderung, Erweiterung oder Refaktorisierung.

Daher hätte ich wohl oder übel darauf hoffen müssen, dass die Anwendung noch so funktioniert wie vorher.

Vielleicht hätte sie das getan – gestern jedoch tat sie es nicht.

Die Ausführung aller Tests dauert derzeit knapp 45 Sekunden. Neun davon sind gestern Abend fehlgeschlagen. Ich wusste also nach weniger als 45 Sekunden, dass meine Anwendung nicht mehr so funktionierte wie vorher. Die Fehler zu finden, war leicht. Die Fehler zu beheben, war ebenfalls leicht. Nach rund 10 Minuten liefen alle Tests wieder erfolgreich durch.

Was bedeutet das nun?

Das Refaktorisieren hätte auch ohne Tests 45 Minuten gedauert, denn die Tests waren von der Refaktorisierung nicht betroffen. Doch ich wage zu bezweifeln, dass mich das Entdecken, Erkennen, Finden und Beheben der Fehler nur 10 Minuten gekostet hätte, wenn ich die Anwendung ohne Tests per Hand hätte überprüfen müssen – wenn ich die Fehler dann überhaupt entdeckt hätte.

Natürlich ist nicht garantiert, dass die Tests jeden denkbaren Fall abdecken – doch auf das, was getestet wird, kann ich mich verlassen. Jederzeit.

Was verbleibt, ist die zum ursprünglichen Schreiben der Tests benötigte Zeit. Diese fällt ausgesprochen gering aus, da ich jede EBC isoliert für sich testen kann und daher keine Zeit in aufwändiges Mocking stecken muss. In Welchen Nutzen bieten EBCs? habe ich diesen Vorteil zumindest implizit bereits thematisiert:

Damit gewinnt man Topologieunabhängigkeit, denn jede EBC ist von ihrer Umgebung entkoppelt und kann entweder für sich alleine oder transparent im Verbund mit anderen Komponenten genutzt werden. Dass sich die Funktionalität von EBCs damit perfekt per Unittest validieren lässt, liegt auf der Hand. Daher eignen sich EBCs ausgezeichnet auch für die Entwicklung mit 4-Step TDD.

Da ich – bevor ich die Entwicklung einer Komponente beginne – auf Grund von EBCs und TDD ohnehin detailliert plane, wie deren API aussehen und wie sich diese API für einen Verwender anfühlen wird, erfordert die Planung häufig deutlich mehr Zeit als die eigentliche Implementierung.

Der Aufwand, die Implementierung im Sinne von TDD noch mit Unittests auszustatten, geht daher gegen Null.

Welchen Nutzen bieten EBCs?

Donnerstag, 29. Juli 2010, 07:57 Uhr
Permalink | Kommentare (11) | Kommentare als RSSRSS

Gestern habe ich über meinen ersten Eindruck von Event-Based Components (EBC) geschrieben. Mein Fazit war sehr positiv – mit dem einzigen Kritikpunkt, dass sich EBCs noch sehr ungewohnt anfühlen und bislang bewährte und etablierte Best Practices fehlen.

Worum geht es bei EBCs überhaupt? Prinzipiell hat Ralf Westphal dies bereits in seinem Blogeintrag EBCs – Der nächste Schritt der Komponentenorientierung? beschrieben. Doch da ich gestern in Reaktion auf meinen Blogeintrag gefragt wurde, ob ich Sinn und Zweck von EBCs noch einmal in meinen Worten erklären könnte, will ich dieser Bitte gerne nachkommen.

Das bisher favorisierte Verfahren zur komponentenorientierten Entwicklung von Software basiert im Wesentlichen auf der strikten Trennung von Implementierung und Kontrakt, so dass Komponenten austauschbar werden – sofern sie den gleichen Kontrakt erfüllen.

Da Komponenten in der Regel nur im Verbund in der Lage sind, eine gestellte Aufgabe zu bewältigen, müssen diese dabei irgendwie miteinander in Kontakt treten. Hierfür enthalten Komponenten Referenzen auf andere Komponenten, von deren Funktionalität sie abhängen. Diese Referenzen verweisen dabei stets nur auf die Kontrakte und nicht auf die konkrete Implementierung.

Um eine Abhängigkeit aufzulösen, muss dann zur Laufzeit entschieden werden, welche konkrete Komponente instanziiert werden soll – wofür üblicherweise die Idee eines Kernels eingesetzt wird, wie beispielsweise in Form eines Dependency Injection-Containers wie LightCore.

So weit, so gut.

Das Problem bei diesem Ansatz zur komponentenorientierten Entwicklung besteht nun darin, dass sich die Reduktion von Komponenten auf ihre Kontrakte zwar positiv auf ihre Austauschbarkeit auswirkt – nicht jedoch auf ihre Unabhängigkeit. Komponenten sind zwar unabhängig von der konkreten Implementierung einer anderen Komponente – aber funktional sind sie dennoch abhängig, nur eben über den Kontrakt.

Dass dies überhaupt ein Problem darstellt, zeigt die Tatsache, dass es nicht möglich ist, eine Komponente nur für sich und isoliert zu testen. In der Regel müssen für andere Komponenten zumindest Stubs, wenn nicht gar Mocks entwickelt und injiziert werden. Das ist aufwändig – zu aufwändig, könnte man mutmaßen.

Denn Komponenten werden häufig mit Lego-Bausteinen verglichen, die man einfach so aufeinander stecken kann – dem Kontrakt sei Dank – doch so wirklich will sich dieses Lego-Gefühl bei der herkömmlichen komponentenorientierten Entwicklung von Software nicht einstellen: Einem roten Lego-Baustein ist es nämlich egal, ob er für sich alleine genutzt wird, oder in Verbund mit einem grünem, einem gelben oder einem blauen.

Ralf nennt diese Eigenschaft topologieunabhängig, weil Lego-Bausteine eben nicht von ihrer Umgebung abhängen. Und genau diese Eigenschaft der Topologieunabhängigkeit trifft auf klassische Komponenten nicht zu: Sie sind abhängig von ihrer Umgebung, allein schon deshalb, weil sie andere Komponenten benötigen, um ihre volle Funktionalität entfalten zu können.

Wendet man sich von Lego-Bausteinen einem anderen Feld, das der IT ein wenig näher steht, zu, kann man problemlos die gravierenden und relevanten Unterschiede zur komponentenorientierten Softwareentwicklung erkennen: Dem Feld von Platinen und Chips.

Ein Chip verkörpert das EVA-Prinzip in Reinkultur: Er erhält Daten per Stromfluss als Eingabe, verarbeitet diese, und gibt Daten per Stromfluss als Ausgabe wieder nach außen. Einem Chip ist es dabei vollkommen gleich, woher die Eingabedaten stammen oder wohin die Ausgabedaten fließen.

Für die Funktionsweise eines Chips sind nun nur zwei Aspekte wichtig:

  • Pins: Ein Chip verfügt über Ein- und Ausgabepins, über die er mit anderen Chips verdrahtet werden und mit diesen in Kontakt treten kann. Ob dies geschieht – und wenn ja, in welcher Form – beeinflusst die grundlegende Funktionsweise des Chips jedoch nicht.
  • Stromfluss: Den einzigen gemeinsamen Nenner, den zwei Chips aufweisen müssen, damit sie auf funktionsfähige Art miteinander verdrahtet werden können, ist ein gemeinsames Verständnis des Stromflusses. Anders formuliert: Alle an einer Kommunikation beteiligten Chips müssen die gleiche “Sprache” verstehen.

EBCs schließlich sind ein Ansatz, genau dieses Konzept von topologieunabhängigen Komponenten, deren einzige Gemeinsamkeit eine gemeinsame “Sprache” ist, auf Software zu übertragen.

Die Idee dazu ist prinzipiell einfach: Das grundlegende Problem der funktionalen Kopplung von Komponenten basiert auf der Tatsache, dass gegenseitig Methoden aufgerufen werden müssen.

EBCs ziehen aus dieser Tatsache die einzig logische Konsequenz: Wenn diese Art der funktionalen Kopplung vermieden werden soll, dürfen Komponenten keine Methoden anderer Komponenten aufrufen. Statt dessen dürfen sie nur signalisieren, dass sie gerne Daten zur Weiterverarbeitung an andere Komponenten abgeben würden – ob darauf dann eine andere Komponente reagiert oder nicht, betrifft die ursprüngliche Komponente nicht mehr.

In einem Satz zusammengefasst bildet dies den Schlüssel zum Verständnis von EBCs:

Im Gegensatz zu klassischen Komponenten rufen EBCs keine Methoden anderer Komponenten auf, sondern stellen nur den Wunsch nach Weiterverarbeitung ihrer Daten in den Raum.

Damit gewinnt man Topologieunabhängigkeit, denn jede EBC ist von ihrer Umgebung entkoppelt und kann entweder für sich alleine oder transparent im Verbund mit anderen Komponenten genutzt werden. Dass sich die Funktionalität von EBCs damit perfekt per Unittest validieren lässt, liegt auf der Hand. Daher eignen sich EBCs ausgezeichnet auch für die Entwicklung mit 4-Step TDD.

Die einzige verbleibende Frage ist, wie dieses Schema umgesetzt werden kann. Die Antwort ist – nochmals – sehr einfach: Input-Pins entsprechen klassischen Methoden, Output-Pins werden als Events deklariert, woher auch der Name der EBCs rührt.

Passt die Signatur eines solchen Events einer Komponente zur Signatur einer Methode einer anderen Komponente, können beide per Eventbinding von außen miteinander verdrahtet werden – die Komponenten selbst bemerken dies nicht und agieren auch im Verbund ebenso wie sie es isoliert für sich täten.

Dadurch entsteht anders als bei klassischen Komponenten kein Codefluss von direkter Aktion und Reaktion, sondern ein Fluss von Daten: Jeweils eine Komponente verarbeitet Daten und reicht diese danach an eine oder mehrere andere Komponenten weiter.

Auch Rückgabewerte lassen sich auf diese Art realisieren: Statt aus der aufgerufenen Methode einen Rückgabewert zurückzuliefern, wird ein entsprechendes Event ausgelöst – auf das die ursprünglich “aufrufende” Komponente dann entweder reagieren kann oder nicht – je nach Belieben. Der “aufgerufenen” Komponente ist das gleich – sie löst unabhängig von ihrer Umwelt lediglich ihre Events aus.

Dies sind die grundlegenden Ideen von EBCs, im nächsten Blogeintrag wird es dann darum gehen, wie eine konkrete Implementierung einer solchen EBC aussehen und wie diese mit anderen EBCs verdrahtet werden kann.

Erster Eindruck von Event-Based Components

Mittwoch, 28. Juli 2010, 15:47 Uhr
Permalink | Kommentare (0) | Kommentare als RSSRSS

Vor ungefähr fünf Monaten hat Ralf Westphal in seinem Blog die Frage aufgeworfen, ob nachrichtenorientierte Komponenten den nächsten Schritt der Komponentenorientierung darstellen.

Als entsprechendes Architekturmodell hat die sogenannten Event-Based Components (EBC) vorgestellt: Ein einfaches Komponentenmodell mit einigen kompakten Regeln, dessen wesentliches Merkmal des Einsatz von Events als Kommunikationsmedium an Stelle klassischer Methodenaufrufe ist.

Im Prinzip ähnelt das Konzept der EBCs dem von Chips und Platinen: Ähnlich wie diese können auch EBCs zusammengesteckt werden und größere Komponenten bilden. Der Vorteil des Ganzen liegt in einer ausgesprochen geringen Kopplung – effektiv sind die einzelnen EBCs nicht mehr voneinander, sondern nur noch von gemeinsamen Typen abhängig.

Die funktionale Abhängigkeit ist aufgelöst. Die Vorteile liegen auf der Hand: EBCs sind einfacher zu instanziieren, einfach zu komponieren, einfacher zu isolieren und daher auch einfacher zu testen.

So weit, so gut. Die Frage ist, inwieweit dieses theoretisch interessante Konzept in der Praxis funktioniert.

In den vergangenen Tagen hatte ich die Gelegenheit, einen EBC-basierten Prototypen einer bestehenden Anwendung zu erstellen: Die zu erzielende Funktionalität war also vorgegeben, die einzige Aufgabe war also tatsächlich, das Konzept der EBCs in die Praxis umzusetzen.

Inzwischen ist dieser Prototyp so weit gediehen, dass er die ersten funktionalen Anforderungen der ursprünglichen Anwendung erfüllt. Zeit, im Rahmen einer kleinen Retrospektive zurückzublicken und ein erstes Fazit zu ziehen. Die aus meiner Sicht zwei wesentlichsten Aspekte sind:

  • EBCs sind effizient: EBCs ersparen einem die Mühe, eine aufwändige Architektur zu entwickeln – sie implizieren eine kompakte Form. Diese kann in technischer Hinsicht auch leicht umgesetzt werden – auch oder erst recht mit TDD. Die geringe Kopplung wirkt sich hierfür enorm positiv aus. Die Erweiterbarkeit des gesamten Systems ist beeindruckend, und auch die Wart- und Evolvierbarkeit des Codes können sich sehen lassen. Noch mehr als von TDD alleine wird man durch den Einsatz von EBCs mit TDD gezwungen, sich zuvor fundierte Gedanken über das Design der Komponenten zu machen.
  • EBCs sind ungewohnt: Der größte Makel von EBCs ist – für mich persönlich – derzeit ihre Andersartigkeit. Sie fühlen sich schlicht und ergreifend ungewohnt an, denn die Kommunikation zwischen den Komponenten folgt nicht mehr dem klassischen und zur Genüge gewohnten Aktion-Reaktion-Schema. Statt dessen modellieren EBCs einen Fluss von Daten durch die Anwendung. Die größte Herausforderung in den vergangenen Tagen war, gedanklich immer wieder zu diesem Fluss-basierten Modell zurückzukehren und sich zu überlegen, wie Funktionalität als Fluss implementiert werden kann.

Natürlich ist der zweite Punkt reine Gewohnheits- und Übungssache. Je öfter man EBCs modelliert, desto leichter gelingt dies. Der Einstieg in EBCs ähnelt daher dem Einstieg in TDD in gewissem Sinne – es ist gar nicht so sehr das rein technische Vorgehen, das kann kompakt und übersichtlich veranschaulicht werden, sondern es sind das fehlende Gefühl für EBCs und die fehlenden Best Practices.

Während das Gefühl nur jeder für sich entwickeln kann, indem er sich mit EBCs beschäftigt und die Arbeit mit ihnen ausprobiert, können Best Practices vermittelt werden – falls diese bereits bekannt sind. Hierzu ist es notwendig, einen Konsens oder zumindest verschiedene, fundierte und argumentativ belegte Meinungen zu finden.

Ralf hat zu EBCs seine Sicht der Dinge – ich habe meine. Aus diesem Grund werde ich in den kommenden Tagen viel über meine Erfahrungen und Erkenntnisse bezüglich EBCs schreiben.

Wenn ich eine andere Meinung vertrete oder EBCs anders nutze als Ralf, werde ich dies begründen – nicht, um Ralfs Position zu schwächen, sondern schlichtweg, um einen zweiten Standpunkt darzulegen.

Vielleicht ergeben sich in der Synergie aus Ralfs Sichtweise, meiner Sichtweise und der Sichtweise von allen anderen Verwendern von EBCs ja Best Practices, die es wert sind, weitergetragen zu werden.

EBCs an sich sind dies allemal wert – sie sind ein großartiges Konzept, das mir sehr gut gefällt. Der langfristige Nutzen wird sich noch beweisen müssen, aber so weit ich EBCs bislang beurteilen kann, sind sie definitiv ein wichtiger Schritt in die richtige Richtung für die moderne Softwareentwicklung.