----- Ursprüngliche Nachricht -----
Von: Denis
Gesendet: 03.11.11 08:16 Uhr
An: Event based Components
Betreff: Re: Dynamic Flow Design
--
Ralf Westphal
www.ralfw.de
mal so ganz platt gefragt: ändert sich irgendeines deiner Programme dynamisch in der Struktur, weil der Benutzer eine weitere Datei öffnet? Sind die Sensoren mit ihren Datenströmen nicht eher Daten die fließen, als Funktionseinheiten?
Viele Grüße
Stefan Lieser
Dadurch würde sich aber die FlowStruktur ändern, weil beim
"Anstöpseln" des Sensors die spezialisierte Auswerteeinheit in den
Flow eingehängt werden muss.
genau diese Aussage sehe ich anders.Wenn alle Sensoren im Vorfeld
bekannt wären, hättest Du recht.
> Welche Sensoren bzw. Sensortypen (für mehr würde ich keine AuswerterAber es ist nicht(!) von Anfang an klar, welche Sensoren zum Einsatz
> vorsehen) es Auswerter maximal geben muss, ist ja von vornherein klar.
kommen.
Genau wie Du würde ich daher erstmal nur für die zur Zeit benötigten
Sensoren Auswerteeinheiten vorsehen. Aber man könnte jederzeit neue
Sensoren mit spezifischen Auswertern hinzufügen.
Viele Grüße,
Christof
Wie schon in meinem ersten posting geschrieben hatte, ist mir die
Architektur weitestgehend vorgegeben.
Eine Applikation instanziiert
Objekte, die eine durch einen Standard vordefinierte Schnittstelle
implementieren. Die Anzahl der Objekte ist durch die Business-Logik
der Applikation vorgegeben. Die Objekte sind Instanzen von Klassen,
die durch eine Bibliothek bereitgestellt werden und somit von
beliebigen Applikationen benutzt werden können. Damit ist prinzipiell
erst zur Laufzeit bekannt, wieviele Objekte instanziiert werden.
Meine
Aufgabe ist es, die Methodenaufrufe auf diesen Objekten in Nachrichten
umzuwandeln und über eine!
Socketverbindung an einen Server zu
versenden, der diese auswertet und auch antwortet. Die instanziierten
Objekte können prinzipiell in verschiedenen Threads laufen. Da nur
eine Socket-Verbindung da ist, müssen die aus den Aufrufen
resultierenden Nachrichten sequentialisiert werden.
Informell würde ich das folgendermaßen in einem FD-Diagramm darstellen
ohne dass der Server berücksichtigt ist:
http://www.flickr.com/photos/69531831@N08/6316576058/
Aus den Schnittstellenobjekten fliessen also Methodennamen und
Argumente heraus und in eine Funktionseinheit, die aus diesen
entsprechend einem Protokoll eine Nachricht formt. Diese leitet die
erstellte Nachricht komplettiert mit einer eindeutigen Id für das
Objekt (diese wird der FE als Konfigurationswert übergeben, deswegen
das "(C)") an eine FE weiter, die die Nachrichten sequentialsiert und
dann über eine Socket versendet. Die Rückmeldung des Servers lasse ich
zur Vereinfachung erst mal weg.
Das Diagramm ist, denke ich, erst mal intuitiv verständlich. Aber
durch die drei Punkte ist es nur informell und deshalb ausserhalb
Ralfs Notation, denn die Semantik der drei Punkte ist nicht definiert.
Im allgemeinen geht es darum einer Applikation den Zugriff auf
Peripheriegeräte über eine Bibliothek bereitzustellen. Die
Schnittstelle dieser Bibliothek ist durch einen Industrie-Standard
(UnifiedPOS - http://en.wikipedia.org/wiki/UnifiedPOS) vorgegeben. Der
Standard definiert verschieden Geräte-Kategorien, die jede ein
abstraktes Modell für eine Peripherie-Geräte-Klasse definiert und
sowohl eine Methoden-Schnittstelle als auch die Semantik des Geräte-
Modells definiert. Der Standard definiert die Methoden-Schnittstelle
sprachunabhängig. Es gibt jedoch drei verschieden Plattformen, die den
Standard jeweils auf Java, .Net und OLE abbilden.
Jeder Geräte-Hersteller, der diesen Standard unterstützen möchte, muss
für sein Gerät einen Geräte-spezifischen Treiber für jede dieser
Plattformen implementieren.
Jede Applikation, die ein Peripherie-Geräte ansteuern möchte, für das
es einen Treiber nach diesem Standard gibt, muss ein
gerätespezifisches Treiber-Objekt instanziieren. Dazu stellt die
Bibliothek ein ebenfalls standardisiertes Konzept ähnlich einer
Factory-Methode bereit.
Wir wollen den Zugriff auf diese Bibliothek remote-fähig machen. Dabei
geht es weniger darum den Zugriff auf die Geräte wirklich im Netz
verfügbar zu machen, als Interoperabilität zwischen den Plattformen zu
realisieren um damit den Aufwand der Implementierung für alle
Plattformen zu vermeiden. Dabei wird der geräte-spezifische Treiber
nur für eine ausgewählte Plattform implementiert. Auf alle anderen
Plattformen wird die Funktionalität über eine Bibliothek
bereitgestellt, die für jede Gräte-Kategorie einen generischen Treiber
bereitstellt, der den Aufruf einer Methode der standardisierten
Schnittstelle quasi als Remote-Procedure-Call an einen Server
weiterleitet, der die eigentlichen funktionalen Treiber der
ausgewählten Plattform geladen hat, und den über's Netzwerk
transportieren Aufruf in einen lokalen Methoden-Aufruf umsetzt. Die
Rückgabeparameter des Methodenaufrufes müssen natürlich auch wieder
zurück transportiert werden.
Diese Architektur habe ich mal im folgenden Software-Holon-Diagramm
versucht darzustellen:
https://cacoo.com/diagrams/Yrox2aGF4eq9OLhh
Dies ist der architekturelle Rahmen, in dem ich mich bewege. Meine
Aufgabe, die ich design-technisch mit FD bewältigen möchte, ist jedoch
beschränkt auf die Entwicklung der Bibliothek auf der
Applikationsseite. Deswegen meinte ich auch in einem meiner Posts,
dass mir die Architektur weitgehend vorgegeben wäre. Eigentlich habe
ich diese Bibliothek für .Net auch bereits implementiert (übrigens dem
Konzept von Space-Based Componentes folgend, das Ralf mal in der
dotmetpro vorgestellt hatte, FD gab es damals noch nicht...). Da ich
diese Problemdomäne aufgrund der bereits vorgenommen Implementierung
recht gut durchdrungen hatte, schien es mir naheliegend daran mal FD
auszuprobieren. In diesem Sinne würde ich auch Design von Architektur
abgrenzen – es ist das Herausarbeiten einer konkreten
Lösungsvorschlags - einer Architektur - aus einem Lösungsraum, durch
das Festlegung oder Auswählen von Anforderungen, die die möglichen
Lösungen bzgl. dieser Anforderungen gewichten. In diesem Sinne würde
ein Design immer eine Architektur umfassen, jedoch zusätzlich zur
konkreten Architektur-Darstellung auch noch die Anforderung und
möglicherweise daraus resultierende Schlussfolgerungen aufzeigen, die
zu dieser konkreten Architektur geführt haben. … aber das ist
eigentlich eine andere Diskussion. :-)
Im Sinne der obigen Architektur versuche ich jetzt noch mal die
applikationsseitige Bibliothek mit Hilfe von FD zu designen und würde
mich natürlich sehr freuen, Eure Meinung darüber zu hören.
In meinem letzten Post, hatte ich ja schon mein Diagramm-Dilemma
gelöst, indem für jedes von der Applikation instanziierte Treiber-
Objekt der Event-Fluss neu instanziiert wird, wobei die FE, die den
TcpClient bedient, in allen instanziierten Event-Flüssen als Singleton
wiederverwendet wird (https://cacoo.com/diagrams/lInnM7GAdrg0ySwh). Im
Kontext der obigen Architektur würde ich das jetzt etwas angepasst und
ausführlicher folgendermaßen darstellen:
https://cacoo.com/diagrams/RW7CXLTZJzhtAaCC
Der oberen Teil stellt die Abstraktion eines Treiber-Objektes dar. Ich
habe mit Absicht keine Verbindungen zwischen dem umschließenden
Treiber-Objekt und der eingebetteten FE eingezeichnet. Damit soll
symbolisiert werden, dass hier ein Wechsel in der
Implementierungstechnologie stattfindet – von objektorientiert, mit
eingehenden Methodenaufrufen als einfließendem Fluss, nach FD mit
Events. Eigentlich ein Implementierungsdetail, aber hier auch
irgendwie wichtig.
Das umschließende Device-Objekt wandelt also ein eingehenden
Methodenaufruf in einen Datenobjekt vom Typ „Request“ um und startet
damit dem Datenfluss hinein in die FE „Send Call Request,
ReceiveAnswer and Receive Device Events“. Die „Device Events“ sind
hier jetzt keine Events im Sinne von EBC sondern asynchrone Events des
Device-Modells, die durch Zustandsänderungen am Hardware-Gerät erzeugt
werden. Dieses Modell-Konzept hatte ich oben noch nicht erwähnt.
Im unteren Teil wird in die oben genannte FE hineingezoomt: Aus dem
einfließende Request-Datenobjekt wird in ein Tupel aus DeviceId und
Nachricht berechnet. Die Nachricht wird entsprechend dem vorgegebenen
Nachrichten-Protokoll als String erzeugt. Bei einem späteren
Protokollwechsel wäre nur diese FE auszutauschen. Das erzeugte Tupel
fließt in die Singleton-FE „Coordinate Call Messages and Send“ ein,
die von jedem instanziierten Fluss in jedem anderen
Treiber-Objekt wiederverwendet wird. Diese FE hat eine Abhängigkeit
zum TcpClient-Objekt, der die Socket-Verbindung realisiert, über die
die Nachricht am Ende asynchron versendet wird.
Die DeviceId wird nach Versendung der Nachricht an die FE „Receive
Messages, Extract DeviceId“ weitergesendet, die diese in einem FIFO
puffert. Diese FE läuft in ihrem eigenen Thread und empfängt
Nachrichten über den TcpClient. Sie ist ebenfalls ein Singleton und
wird von allen instanziierten Flüssen in allen Device-Objekten
wiederverwendet, da ja für alle zusammen nur eine Socket-Verbindung
verwendet werden soll. Die FE analysiert, ob es sich um eine Antwort
auf eine „Call Message“ handelt oder um einen „Device Event“. Im Falle
einer Antwort wird eine DeviceId aus dem FIFO geholt und geprüft, ob
die Antwort dazu korrespondiert, d.h. ob sie die dieselbe DeviceId
enthält. Der Antwort-String wird zusammen mit der DeviceId an die FE
zur Analyse und Aufbereitung der Antwort-Argument weitergeleitet.
Ähnliches passiert für den Device-Event.
Im Falle eines Verbindungsabbruchs, oder einer unpassenden DeviceId
fließt ein Fehler aus der FE.
Wahrscheinlich wird man bei einer Implementierung der beiden
Singletons eventuell dazu kommen, dass sie noch weiter in Unter-FEs
zerlegt werden können – z.B. ist die Extraktion der DeviceId
protokollspezifisch und damit wert in einer eigenen FE realisiert zu
werden, um dann bei einem Protokollwechsel einfacher austauschbar zu
sein. Aber das Ausspezifizieren der FE kann man ja dann nachgelagerten
Arbeitsschritten überlassen. Das ist aus meiner Sicht ja gerade der
Vorteil des FD-Ansatz – einfaches Wechseln der Abstraktionsebene beim
Absteigen in die Implementierung.
Jetzt würde mich natürlich auch interessieren, ob das obige FD-Diagram
auch ohne meine zusätzlichen Ausführungen (abgesehen von der
Architekturbeschreibung, die natürlich unbedingt notwendig ist)
verständlich gewesen wäre. Denn ich stelle mir vor, in der produktiven
Verwendung der FD-Diagramme ohne diese zusätzlichen Erläuterungen
auszukommen. Oder sollten sie immer dabei sein, um alles verstehen zu
können?
Interessant wäre auch zu reflektieren, wie man unterschiedliche
Strategien mit FD realisieren könnte. Also wenn z.B. nicht nur eine
Socket-Verbindung für alle Treiber-Objekte, sondern für jeden Request
eine neue Verbindung aus einem endlichen Socket-Pool verwendet werden
soll...
Denis
On 6 Nov., 11:28, Denis <kun...@grammarcraft.de> wrote:
> Ich denke, ich habe eine Lösung für mein Diagramm-Dilemma.
>
> Deine Kriktik, Ralf, an meiner Darstellung kann ich verstehen und sie
> ist auch weitgehend berechtigt und sie hängt mit dem Grund meines
> Dilemmas zusammen. Auf die Anforderungen gehen ich nächste Woche noch
> mal konkreter ein. Hier erst mal die Lösung, die ich mir zurechtgelegt
> habe.
>
> Nachdem ich gestern das informelle Diagramm aufgezeichnet und gesendet
> hatte, viel mir auf, dass ich die verschiedenen Abstraktionsebenen
> mische. Was hat die Applikation auf derselben Ebene wie die
> Schnittstellen-Objekte (Obj1, Obj2 …ObjN) zu tun. Und diese wiederum
> sollten nicht mit den FE des Flow-Design zusammen gezeichnet werden.
> Ich war einfach noch zu stark in der UML-Denke gefangen, wo irgendwie
> immer alles ins Diagramm muss, egal welche Abstraktionsebene.
>
> Besser ist es erst mal nur die Architektur mit Hilfe von
> Softwarezellen zu beleuchten.
> Auf dieser Abstraktionsebene gibt es nur die Applikation und die
> Schnittstellen-Objekte, die sie instanziiert.https://cacoo.com/diagrams/Q2sfMbaWDAQM6uMu
Das mit der Domäne ist interessant. Meiner Meinung nach ist es immer
relativ, was man als "business domain" sieht.
Wir (bei uns in der Abteilung) beschäftigen uns eigentlich
ausschließlich mit Infrastruktur für Applikation, weil wir eben eine
Infrastruktur-Bibliothek herstellen. Die die Bibliothek benutzenden
Applikationen kennen wir meistens gar nicht. Deswegen würde ich unsere
"business domain" als die technischen Aspekte der Infrastruktur-
Bereitstellung sehen. Neben unsere "business domain" gibt es natürlich
auch in unserer Bibliothek wiederum technische bzw. Infrastruktur-
Belange, aber dann auf einer anderen Abstraktionsebene.
Oft ist es schwierig die technischen/Infrastruktur-Belange von denen
der Business-Domäne zu trennen, gerade wenn man nur in technischen
Bereichen unterwegs ist. Aber eine gute Trennung würde ja gerade ein
gutes Design ausmachen...
Hat man sie erst mal gut getrennt, ist der Ansatz die orthogonale
Belange als in Klassen gekapselte Flüsse zu realisieren durchaus
passend, wie ich finde. So zumindest habe ich Deinen letzten Kommentar
verstanden.
Vielleicht solltest Du der Kapselung von Flüssen in Klassen und damit
deren Integration in klassische OO-Architekturen in einem dotnepro-
Artikel oder in Deinem Buch noch mal etwas Raum einräumen. Das Problem
ist doch, dass die meisten von uns nicht in der Position sind, das
Design einer gesamten Applikation zu bestimmen. Vielmehr sind wir
meistens nur für einen Teil der Applikationsfunktionalität
verantwortlich, im besten Fall durch ein Interface vom Rest der
Applikation entkoppelt. Und nur in diesem Teil können wir dann EBC als
dessen Implementierung und FD als Design-Mittel anwenden. Das würde
doch vielleicht auch mehr Leute animieren, es mal im Kleinen mit FD/
EBC zu versuchen, oder?
Ist diese Implementierung im Kleinen dann erfolgreich, weil qualitativ
besser, besser erweitbar, besser wartbar, evolvierbarer als der Rest
der Implementierung der Gesamt-Applikation, dann könnte dies zusammen
mit den verantwortlichen Entwicklern doch die Keimzelle für die
schrittweise Transformation der klassischen OO-Applikationen in eine
FD-design-te, wartbare, professionelle, EBC-basierte Applikation sein.
Der politische Aspekt des Agierens in größeren Firmenstrukturen ist
hier nicht zu unterschätzen! Das wäre dann sozusagen eine Revolution
von unten. Ich habe schon öfter beobachtet, dass es so funktioniert,
und in manchen Strukturen funktioniert es nur so!
Auf meinen Versuch einer Begriffsbildung für Design und die
Unterscheidung von Architektur und Design ist bis jetzt keiner von
Euch eingegangen. Aber mich würde schon Eure Meinung dazu
interessieren. Ich sehe die Definition des Begriffs Design gerade
wegen der kontroversen Diskussion in Ralfs Blog (http://
ralfw.blogspot.com/2011/07/design-zur-diskussion-gestellt.html) immer
noch als offen an.
Denis
> > (UnifiedPOS -http://en.wikipedia.org/wiki/UnifiedPOS) vorgegeben. Der
> ...
>
> Erfahren Sie mehr »
Oft ist es schwierig die technischen/Infrastruktur-Belange von denen
der Business-Domäne zu trennen, gerade wenn man nur in technischen
Bereichen unterwegs ist. Aber eine gute Trennung würde ja gerade ein
gutes Design ausmachen...
Vielleicht solltest Du der Kapselung von Flüssen in Klassen und damit
deren Integration in klassische OO-Architekturen in einem dotnepro-
Artikel oder in Deinem Buch noch mal etwas Raum einräumen.
Das Problem
ist doch, dass die meisten von uns nicht in der Position sind, das
Design einer gesamten Applikation zu bestimmen. Vielmehr sind wir
meistens nur für einen Teil der Applikationsfunktionalität
verantwortlich, im besten Fall durch ein Interface vom Rest der
Applikation entkoppelt.
Auf meinen Versuch einer Begriffsbildung für Design und die
Unterscheidung von Architektur und Design ist bis jetzt keiner von
Euch eingegangen. Aber mich würde schon Eure Meinung dazu
interessieren. Ich sehe die Definition des Begriffs Design gerade
wegen der kontroversen Diskussion in Ralfs Blog (http://
ralfw.blogspot.com/2011/07/design-zur-diskussion-gestellt.html) immer
noch als offen an.
Es ist von der Abstraktion her schwer. Je näher die Business-Domäne
und Infrastruktur-Domäne liegen, also je technischer die Business-
Domäne, um schwieriger ist die Infrastruktur-Domäne zu abstrahieren.
Meine Erfahrung ist, dass viele Kollegen hier eine Vermischung
vornehmen. Oft trennen die Kollegen beide Belange einfach nicht. Ich
bin mir nicht sicher woran dies liegt, vermute aber eben, dass es
nicht ganz einfach ist, aus oben genannten Gründen.
> Ist doch aber gar nicht schwer: Wenn du einen Belang
> hast, dann beschreibst du dessen Funktionalität mit einer
> Schnittstelle.
> Das kann sogar eine traditionelle sein.
Nein, es ist nicht schwer, wenn man FD dann erst mal verstanden hat.
Ich betrachte das hier dann auch eher aus der Sicht der Propagation
des FD-Ansatzes. Da finde ich es wert, dass dieses Szenario mal in
einem Bespiel betrachtet wird. So in dem Sinne: Seht her, man kann
auch in einer Nicht-FD-designten Appplikation mit einer durch
Interfaces entkoppelten Komponente anfangen und diese mit FD designen
und mit ECB realisieren.
> Was bedeutet "verantwortlich sein"? Hier scheint mir ein tieferes
> Problem zu liegen. Wie ist denn das Verständnis von Teamarbeitet in so einem Projekt?
Ja, hier liegt ein tieferes Problem. Dies ist eher in der
Organsitation der Firma und in den vorhanden Machtstrukturen
begründet. Ick kann nur in der Art agieren, dass ich versuche Kollegen
zu überzeugen. Allerdings habe ich da noch mit ganz anderen,
einfacheren Herausforderungen zu kämpfen, als mit der, die Kollegen
von FD zu überzeugen. Da geht vielmehr erst mal grundlegende
Prinzipien und Methodiken: Regressionstestbarkeit von Code, gemeinsame
Verantwortung für gemeinsamen Code, automatischer Buildprozess, Build-
Artefakt-Repository, Continuous Integration usw.
Das Überzeugen funktioniert auch recht gut, findet aber irgendwie
versteckt vor dem Management statt. Sobald es aber um Veränderungen
geht, die die ganze Abteilung (oder darüber hinaus) betreffen, wie
z.B. die Einführung von Continuous Integration, muss das Managment
involviert werden und viel zu oft wird von diesem dann nur der
initiale Aufwand gesehen, aber nicht die mittel- und langfristigen
Vorteile und Produktivitätssteigerungen. Es mag sein, dass man FD im
Kleinen einführen kann, sozusagen zwischen den Entwickler-Kollegen,
aber sobald es explizit wird, z.B. in Form von Design-Dokumenten, oder
EBC-Realisierungen, dann geht es nicht ohne Involvierung des
Management und spätestens dann braucht man gute Argumente. Am besten
schon Teilkomponenten, die mit FD/EBC umgesetzt wurden, an deren Life-
Cycle und Qualität man die Vorteile erläutern kann.
Dieses produktive Ausprobieren einer neuen Technik kann man nun mal
nur für die Komponenten machen, für die man explizit verantwortlich
ist und dem Management für jede grundlegendere Änderung nicht gleich
Rede und Antwort stehen muss, wobei dann die Gefahr des Abwürgens
besteht!
Es gibt bei uns auch noch einen anderen Aspekt: Ich würde die
Bibliotheksentwickung bei uns nicht als Projekt bezeichnen. Das
impliziert irgenwie eine kurze Laufzeit von unter 2 Jahren. Die
Lebensdauer einer Version einer solchen Bibliothek bei uns ist sehr
lang - mehrere Jahre. Die letzte Version gibt es seit über 7 Jahren.
Sie wird immer weiterentwickelt, indem neue Geräte hinzugefügt werden.
Will man jetzt aber generell etwas ändern, will das gut überlegt sein,
da eben soviel Historie mitgeschleppt wird. Gibt es dann nicht mal
Regressionstest (ich bin seit 4 Jahren dabei, die Kollegen samt Chef
von Unit-Tests zu überzeugen, um eine Basis für Regressionstest zu
haben), dann sind generelle Änderungen nicht so einfach vorzunehmen.
Am Ende wird jede globale Änderung ein Politikum, wo gute Argument
erforderlich sind, bevor das Managment einer solchen Änderung
zustimmt. Bei den Unit-Tests habe ich es damit geschafft, es erst mal
für meinen Verantwortungsbereich einzuführen und hatte damit dann
vorweisbare Ergebnisse und gute Argumente...