Auf der guide to C# Live! Winter Edition hatten wir einige Diskussionen über die Architektur von Business
Anwendungen (Ganz ähnlich übrigens auch auf mycsharp.de in folgendem Beitrag:
http://www.mycsharp.de/wbb2/thread.php?threadid=61812). Den von mir vorgestellte Ansatz, die einzelnen
Dienste in Kategorieen einzuteilen und diese in einer Hierarchie anzuordnen, war manchen nicht ganz
verständlich gewesen. Der Bitte, das Ganze doch mal aufzuzeichnen, bin ich nun nachgekommen.
Folgende Skizze kann hoffentlich Abhilfe schaffen und helfen, den Ansatz besser zu verstehen:
Eine Dienste haben gar keine Pfeilspitzen abbekommen. Das liegt daran, dass in der Skizze keine Clients
und auch keine Stapelverarbeitungsdienste (z.B. Rechnungsdruck) enthalten sind.
Man kann sehr schön sehen, wie viele Abhängigkeiten es zwangsläufig gibt. Die Hierarchie gibt vor, dass
Dienste nur andere Dienste konsumieren dürfen, wenn diese über ihnen angebordnet sind. Niemals dürfen
Dienste andere Dienste konsumieren, die darunter oder auf gleicher Ebene angeordnet sind.
Diese Hierarchie muss allerdings vom Entwickler-Team auch so eingehalten werden. Es ist ein Konzept
bzw. eine Konvention. In einem drei bis vier Mann Team habe ich sehr gute Erfahrungen mit diesem Modell
gemacht. In größeren Teams ist da, denke ich, die Qualitätssicherungs-Abteilung gefordert. Damit alle auch
nach der Selben Hierarchie entwickeln, sollte diese unbedingt Dokumentiert werden (z.B. wie oben).
Ein Aspekt ist auf der Skizze allerings nicht abgebildet. Und zwar die Kommunikation nach außen. Wenn
ein Dienst externe Dienste (also z.B. einer Fremd-Applikation) konsumieren soll, muss dies immer entkoppelt
passieren. Das größe Problem dabei ist, Dinge wie Mandantenverwaltung, Sitzungen, Sicherheit und Locking
mit der externen Anwendung auf einen Nenner zu bekommen. Portal-Adapter-Paarungen zwischen internem
und externem Dienst können dabei für die Entkopplung und ggf. erforderliches Schnittstellen-Mapping sorgen.
Ein generischer Weg wäre z.B. der BizTalk Server.
Wenn man SOA ernsthaft umsetzen möchte, muss es sogar so sein, dass alle Dienste theoretisch
austauschbar sind. Das würde bedeuten, dass jeder Dienst auch eigene Kontrakte für alles, was er konsumiert.
Ohne Bus-System geht dann natürlich nichts mehr. Der Entwicklungs- und Testaufwand vervielfacht sich,
wenn die komplette Kommunikation über ein Bus-System laufen soll.
Aber auch ohne Bus-System bringt der Hierarchische-Ansatz eine Menge. Die Abhängigkeiten werden auf ein
Mindestmaß reduziert und folgen klaren Regeln. Dienste lassen sich gut testen, da man für einen Test den
Zugriff auf höher liegende Dienste auch auf einen Dummy-Dienst umleiten kann. Die Lösung ist in sich klar
strukturiert und die Kommunikation zwischen den Diensten funktioniert über explizite Schnittstellen. Die
Entwicklungsarbeit im Team lässt sich gut Aufteilen und parallele Entwicklung von Diensten ist - insofern
man Contract-First durchzieht - auch kein Problem. Die Entwicklung solcher Dienste ist einfach und nicht an
komplexe Container-Modelle oder Vererbungsbäume gebunden. Die Einarbeitungszweit für neue Entwickler ist
minimal - vorausgesetzt die Infrastrukturdienste (oben gelb dargestellt) stehen schon und es wurde eine intuitive
API für die Infrastruktur geschaffen (z.B. generischen Service-Locator, Microkernel, Statische Hilfsklasse für
den Sicherheitsdienst und das Locking).