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.

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.

Kommentare

Kommentar schreiben


(Zeigt dein Gravatar icon)  

  Country flag

biuquote
  • Kommentar
  • Live Vorschau
Loading