myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
   » Plugin für Firefox
   » Plugin für IE
   » Gadget für Windows
» Regeln
» Wie poste ich richtig?
» Datenschutzerklärung
» wbb-FAQ

Mitglieder
» Liste / Suche
» Stadt / Anleitung dazu
» Wer ist wo online?

Angebote
» ASP.NET Webspace
» Bücher
» Zeitschriften
   » dot.net magazin

Ressourcen
» guide to C#
» openbook: Visual C#
» openbook: OO
» MSDN Webcasts
» Search.Net

Team
» Kontakt
» Übersicht
» Wir über uns
» Impressum

» Unsere MiniCity
MiniCity
» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » Rund um die Programmierung » Die ideale Architektur für Businessapplikationen?
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Seiten (2): [1] 2 nächste » Antwort erstellen
Zum Ende der Seite springen  

Die ideale Architektur für Businessapplikationen?

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
Golo Roden Golo Roden ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2167.png


Dabei seit: 04.10.2003
Beiträge: 4.207
Entwicklungsumgebung: Visual Studio 2010
Herkunft: Riegel am Kaiserstuhl


Golo Roden ist offline

Die ideale Architektur für Businessapplikationen?

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

obwohl es ja einige Ansätze gibt, wie man Businessanwendungen aufbauen sollte (3-Tier, MVC, ...), ist es in der Praxis ja doch immer noch eine andere Sache, eine wirklich skalierbare, durchdachte Architektur aufzusetzen.

Deshalb würde ich hier gerne mal diskutieren, wie man so etwas idealerweise aufbauen würde. Mir ist klar, dass es nicht DIE ideale Architektur gibt, aber ich denke, es lassen sich doch etliche Best Practices finden, die man verwenden kann.

Um mal den Anfang ganz unten zu machen: In der Regel hat man ganz unten ja so etwas wie eine Datenzugriffsschicht, sei es auf eine Datenbank, einen Webservice, eine XML-Datei oder sonstwas ... in der Regel wird hier mit Entities gearbeitet, wobei üblicherweise ein Entitiy einem Datensatz einer Tabelle entspricht. Im Prinzip sollte man jedoch hier bereits mehrere Schichten einziehen, nämlich:

Nach oben: Ein einheitliches Interface, das NUR mit Entities arbeitet, und abstrahiert, aus welcher Datenquelle die Entities kommen.
Nach unten: Je nach Datenquelle einen Provider, der halt auf XML, SQL oder sonstwas zugreift, und ein Entitiy zurückliefert.
Dazwischen: Einen Microkernel, um der oberen Schicht verschiedene Provider unterschieben zu können, ohne dass sie davon etwas mitbekommt.

Bereits hier sollte mit Transaktionen gearbeitet werden, zudem bietet sich in der unteren Schicht evtl der Einsatz eines O/R-Mappers an. Auch Locking sollte hier in den grundlegenden Funktionen verfügbar sein, sprich Datensatz sperren, Datensatz entsperren, usw ...

Die Entities sind zunächst auch noch sehr eng am DB-Modell, und daher nicht applikationsbezogen modelliert.

Eine Schicht darüber werden die Entities zu Businessobjekten zusammengesetzt, die dann konkret und applikationsbezogen sind. Beispielsweise könnten hier aus einem Rechnungs-Entitiy und mehreren Rechnungspositionen-Entities ein Rechnungs-BO gemacht werden, das eher aus der OOP-Sicht als aus der DB-Sicht auf eine Rechnung schaut.

Das bietet den Vorteil, dass die Entities sich ändern können, ohne dass sich die Applikationen notgedrungen mit ändern müssen. BOs sind dennoch reine Datencontainer, damit sie problemlos serialisierbar und versionierbar sind, Funktionalität würde ich hiervon in einen BO-Service entkoppeln, der nur die Workflows zur Verfügung stellt.

Das heißt auch, dass sich die Workflows ändern können, ohne dass man jedes Mal an die BOs dran muss.

Darüber liegt schließlich eine Applikations-Service-Schicht, die quasi die Applikation ohne UI darstellt, und erst darauf setzt die UI auf (im Endeffekt meine ich hier das MVVM-Pattern).

Parallel dazu gibt es einige funktionale, applikationsübergreifende Kerne, die allgemeine Sachen wie zB Drucken, Reporting, ... zur Verfügung stellen.

Und nun zu meinen Fragen:

- Was haltet Ihr von dieser Aufteilung?
- Wo würdet Ihr RPC-Grenzen ziehen? Wo würdet Ihr Stack-Grenzen ziehen?
- Wie würdet Ihr die Kommunikation über RPC aufbauen, insbesondere Events, die Rückmeldungen liefern?
- Was fehlt bei dem ganzen Ansatz?
- Wo habe ich etwas grundlegendes vergessen?

Wichtige Aspekte bei der ganzen Geschichte wären mir Multiuser, Multithreading, Skalierbarkeit, Verwendbarkeit des ganzen Grundgerüsts im Web und auf dem Desktop, und generell Flexibilität.

Viele Grüße,


Golo
01.10.2008 20:37 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
norman_timo norman_timo ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-1775.jpeg


Dabei seit: 13.07.2004
Beiträge: 4.506
Entwicklungsumgebung: .NET 2.0/3.5 und VS2005/VS2008
Herkunft: Wald-Michelbach (Odw)


norman_timo ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Golo,

wenn man das immer nur so pauschal sagen könnte ;-))

Also ich habe schon einige Ansätze gesehen und auch diverse Richtungen verfolgt. Von einer Mini-Applikation, die quasi nur eine 2-Schichtenarchitektur beinhaltet hatte (Programm inkl. GUI plus DB) bis hin zu einer Serverlandschaft und extrem verteilte Anwendung. Dort war das GUI so weit weg, dass Daten über einen extra Provider zum Rechenzentrum geschickt wurden, diese dann zunächst vereinheitlicht und danach verarbeitet wurden, um dann wieder weiter weg über einen Provider zu so genannten Umsystemen zu schicken.

Das wohl krasseste Szenario das ich kenne ist wohl folgender Aufbau (im groben könnte man das mit einem SOA Ansatz vergleichen):

- GUI: .NET Anwendung, Daten via XML in Journalen zu
- Datenprovider: Ein spezialisierter Provider, der es schafft riesige Datenmengen über eine riesige Bandbreite zu diversesten Empfänger zu verteilen (sozusagen ein Router)
- Middleware/Businesslogik: Verarbeiter und Analysierer der Daten, hier eingesetzt BizTalk und MS-SQl Server Cluster über
- Datendateien zu Umsystemen

Grundsätzlich geht es doch immer darum: Was ist der Zweck der Software, was für Mittel stehen zur Verfügung und was ist am Effizientesten. Ich würde das wohl damit vergleichen, was für ein Warenwirtschaftssystem soll in einem Unternehmen eingeführt werden. Ein SAP System für einen Einzelunternehmen ist wohl Quatsch, genauso wie Excel für ein 10.000 Mann Unternehmen wohl nicht ausreichend sein wird.

Also da es hier sehr starke Schwankungen der Anforderungen gibt, gerade was Businessapplikationen angeht, kann man das überhaupt nicht festlegen. Wichtig für einen Software-Entwickler finde ich, ist es so viele verschiedene Ansätze zu kennen, und nicht so verbohrt zu sein, immer das Gleiche in jedem Umfeld einsetzen zu wollen.

Grüße
Norman-Timo
01.10.2008 20:55 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
GMLOD
myCSharp.de-Mitglied

images/avatars/avatar-2654.jpg


Dabei seit: 30.11.2007
Beiträge: 1.200


GMLOD ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Warum nur muss ich bei deinem Ansatz die ganze Zeit an Enterprise Java denken?
01.10.2008 20:59 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
JuyJuka JuyJuka ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2316.jpg


Dabei seit: 30.11.2005
Beiträge: 2.187
Entwicklungsumgebung: VS2015
Herkunft: Deutschland


JuyJuka ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo @All,

Eine gute Grundstruktur zu haben finde ich nicht verkehrt.
Aber mann muss eben alles Anpassen können und flexiebel sein. smile

Meine Strucktur besteht aus:
- O/R Mapper (als Generische DAL, mit austauschbarer Datenquelle)
- Business-Objekte
- UI

Wobei die Business-Objekte im zweifelsfall aus weiteren Schichten bestehen können und ich noch an einer Remoting-Schicht für den O/R Mapper arbeite. Augenzwinkern

Gruß
Juy Juka
01.10.2008 21:39 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
svenson svenson ist männlich
myCSharp.de-Poweruser/ Experte

Dabei seit: 15.04.2005
Beiträge: 8.746
Entwicklungsumgebung: Visual Studio .NET 2003
Herkunft: Berlin


svenson ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Grunsätzlich glaube ich, dass Architektur weniger von Patterns, sondern eher von der Vermeidung von Anti-Patterns getrieben ist. Für Business-Anwendungen mag das weniger gelten, weil "Businessanwendung" einfach einen bestimmten Typ von Anwendung definiert, der durch Nutzerfrontend, zentraler Datenverarbeitung und -haltung definiert ist. In diesem engen Rahmen lassen sich gut Patterns definieren.

Aber die sehen bei Services schon anders aus, ebenso wie z.B. bei Steuerungen.

Dieser Beitrag wurde 3 mal editiert, zum letzten Mal von svenson am 02.10.2008 13:41.

02.10.2008 13:35 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
JuyJuka JuyJuka ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2316.jpg


Dabei seit: 30.11.2005
Beiträge: 2.187
Entwicklungsumgebung: VS2015
Herkunft: Deutschland


JuyJuka ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo svenson,

Dass Software-Architektur nicht von Patterns getrieben wird, ist hoffentlich nicht korrekt und wenn doch sehr schade. Ich glaube es nicht (dass es nicht durch Patterns getrieben wird), hab aber weder Beweise dafür noch dagegen.

Aber für die Software-Architektur gibt es ein zusätzliches Set von Patterns (oder sogar mehrer), die jedoch noch unbekannter sind als die Designe-Patterns.
z.B.: Layer-Architektur-Pattern, Pipes-and-Filter-Architektur-Pattern, Broker-Architektur-Pattern.

Gruß
Juy Juka
02.10.2008 15:30 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
svenson svenson ist männlich
myCSharp.de-Poweruser/ Experte

Dabei seit: 15.04.2005
Beiträge: 8.746
Entwicklungsumgebung: Visual Studio .NET 2003
Herkunft: Berlin


svenson ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Was ich sagen wollte: Pattern sind Muster. Muster eigenen sich für Software von der Stange, für die Wiederholung. Stell dir vor, du musst auf einmal eine Anwendung bauen, die eine Million Transaktionen pro Sekunde verarbeiten muss. Dann kann du dein klassisches Schichten-Modell sofort in die Tonne treten und du fängst an, zuerst zu denken: Was geht auf keinen Fall: Datenbanken für Transaktionssicherung, klassische Middleware, etc.. Dann beginnt die Suche nach den Fallstricken, den No-Gos. Deine Architektur beginnt sich nicht an erfolgreichen Modellen auszurichten, sondern an den Mißerfolgen, die du gesammelt hast. Auf einmal suchst du danach, welche Muster du unbedingt vermeiden musst. Du musst deine Erfahrung in inverser Weise ins Spiel bringen.

Ansonsten lautet die Antwort auf die Frage, welche Architektur in bekanntem Umfeld die beste ist: Die alte und die bekannte. Die die andere schon 100 mal beschritten haben. Hier lauert keine Gefahr. Oder anders: Die Frage ist unspannend.

M.E. sind Musterarchitekturen - bzw. das was man als solche bezeichnet - nur Zeiterscheinungen, die den Stand der Technik bzw. der Anwendungen wiederspiegeln. "Ideal" ist ein Wort für ein Snapshot. Gestern war es das 3-Schicht-Modell, morgen die Zelle, übermorgen der Service-Ansatz. Das Pattern "Krawatte bis zum Gürtel" mag heute gültig sein. Morgen vielleicht nicht mehr. Aber das Pattern "Eine Krawatte über die man stolpert ist Scheisse" hat universelle Gültigkeit. smile
03.10.2008 00:16 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Rainbird Rainbird ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2834.jpg


Dabei seit: 28.05.2005
Beiträge: 3.720
Entwicklungsumgebung: Visual Studio 2012
Herkunft: Mauer


Rainbird ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Golo,

eine interessante Diskussion.

Zitat von Golo Roden:
Im Prinzip sollte man jedoch hier bereits mehrere Schichten einziehen, nämlich:

Nach oben: Ein einheitliches Interface, das NUR mit Entities arbeitet, und abstrahiert, aus welcher Datenquelle die Entities kommen.
Nach unten: Je nach Datenquelle einen Provider, der halt auf XML, SQL oder sonstwas zugreift, und ein Entitiy zurückliefert.
Dazwischen: Einen Microkernel, um der oberen Schicht verschiedene Provider unterschieben zu können, ohne dass sie davon etwas mitbekommt.

Es gibt doch mittlerweile für jeden die passende Datenzugriffstechnologie. Das .NET Framework 3.5 SP1 liefert bereits drei Stück:
  • ADO.NET (Der schnelle Klassiker)
  • LINQ2SQL (Der schlanke OR-Mapper für treue MSSQL-Entwickler)
  • ADO.NET Entity Framework (Der Mega-OR-Mapper mit vielen Stellschrauben, eigenem DB unabhängigen SQL-Dialekt und noch LINQ obendrauf)
Deiner obigen Aussage entsprechend, ist das ADO.NET Entity Framework genau das was Du suchst: Komfortabler und Tool gestützter OR-Mapper mit völliger Abstraktion von der eigentlichen Datenquelle und auch deren API bzw. SQL-Dialekt. Volle Flexibilität, da Abfragen via LINQ (stark typisiert) oder via ESQL abgesetzt werden können. Aber da erzähle ich Dir bestimmt nichts Neues.

Ich wollte eigentlich damit sagen, dass ich das Thema Datenzugriff nicht zu hoch bewerten würde. Datenzugriff ist immer wieder das Lieblingsthema der Entwickler. Statt über Sinn und Unsinn von Mapping-Konzepten zu philosophieren, wäre es Sinnvoller, der eigentlichen Geschäftslogik einen viel größeren Stellenwert beim Entwurf einer Software-Architektur einzuräumen.

Zitat von Golo Roden:
Bereits hier sollte mit Transaktionen gearbeitet werden, zudem bietet sich in der unteren Schicht evtl der Einsatz eines O/R-Mappers an. Auch Locking sollte hier in den grundlegenden Funktionen verfügbar sein, sprich Datensatz sperren, Datensatz entsperren, usw ...

Transaktionen müssen ja erst aufgespannt werden. Verschiedene Komponenten können an einer Transaktion beteiligt sein. Die Datenzugriffsschicht kann das nicht leisten, da es vom Geschäftsprozess abhängig ist, welche Operationen zusammen in einer Transaktion ausgeführt werden müssen. Deshalb haben Transaktion in der Datenzugriffsschicht eigentlich nix verloren. Aber auch das ist bereits mit System.Transactions gelöst. ADO.NET, LINQ2SQL und Entity Framework unterstützen System.Transactions-Transaktionen.
Da bleibt dann eigentlich nur die Frage, wie man seine Transaktionsklammern setzt. Etweder deklarativ im Code mit TransactionScope oder, im Falle einer verteilten Anwendung auf WCF-Basis, mit TransactionFlow-Attributen.

Du hattest noch Locking erwähnt. Beim Locking ist es selbst innerhalb einer abgeschlossenen Business Anwendung schwer, eine einheitliche Implementierung zu finden. Es gibt verschiedene Ressourcen, die unterschiedlich oft (5 pro Trag oder 200 pro Sekunde) und unterschiedlich lange (10 Sekunden oder 2 Stunden) gesperrt werden müssen. Auch der Zeitpunkt der Sperrung ist selten bei allen Ressourcen gleich. Manche müssen beim Anzeigen und andere vielleicht erst bei Beginn einer Änderung gesperrt werden. Ich würde das Locking deshalb nicht automatisch durchführen lassen, da man sonst die geforderte Flexibilität nie erreichen kann. Wenn die Infrastruktur automatisch sperrt, tut sie das immer auf die selbe Weise. In verteilten Anwendungen wird das noch wesentlich komplexer, da Clients Sperren anfordern (Im Falle eines Windows.Forms-Cients weiss z.B. auch nur diese, wann der Benutzer den Knopf "Bearbeiten" auf der Symbolleiste anklickt), aber auch serverseitige Geschäftslogik, die automatische Änderungen durchführt. Stapelverarbeitung sollte man beim Locking-Konzept auch nicht vergessen. Wie soll sich das System verhlaten, wenn z.B. ein Server-Job 1000 Buchungen ausführen soll, von denen zwei gerade durch Sperren von Clients betroffen sind, die abhängige Ressourcen gerade in Ihrer GUI bearbeiten? Letzten Stand nehmen, Erneut versuchen, Überspringen?
Ich habe gute Erfahrungen damit gemacht, einen Satz von Locking-Funktionen über eine Locking-Komponente zur Verfügung zu stellen und dem Entwickler die Verantwortung für setzen, prüfen, behandeln und freigeben von Sperren zu übertragen. Wenn eine schlanke Locking-Komponente/Dienst (Ich weiss nie, wie ich da sagen soll) zur Verfügung steht, die über ein API einfach verwendet werden kann, tut sich keiner im Team schwer mit dem Locking.

Zitat von Golo Roden:
Eine Schicht darüber werden die Entities zu Businessobjekten zusammengesetzt, die dann konkret und applikationsbezogen sind. Beispielsweise könnten hier aus einem Rechnungs-Entitiy und mehreren Rechnungspositionen-Entities ein Rechnungs-BO gemacht werden, das eher aus der OOP-Sicht als aus der DB-Sicht auf eine Rechnung schaut.
Das bietet den Vorteil, dass die Entities sich ändern können, ohne dass sich die Applikationen notgedrungen mit ändern müssen. BOs sind dennoch reine Datencontainer, damit sie problemlos serialisierbar und versionierbar sind, Funktionalität würde ich hiervon in einen BO-Service entkoppeln, der nur die Workflows zur Verfügung stellt.

Meistens ergeben sich eigene Datenstrukturen zur Bearbeitung und Anzeige von ganzen Datensätzen (Weitestgehed DB-Struktur=BO-Struktur) und welche die bestimmte Sichten auf Teilaspekte einer Entität oder mehrerer Entitäten in Abhängigkeit voneinander (z.B. Trefferlisten von Suchanfragen oder Datensammlungen für Berichte).

Zitat von Golo Roden:
Das heißt auch, dass sich die Workflows ändern können, ohne dass man jedes Mal an die BOs dran muss.

Das ist auch meine Meinung.

Zitat von Golo Roden:
Darüber liegt schließlich eine Applikations-Service-Schicht, die quasi die Applikation ohne UI darstellt, und erst darauf setzt die UI auf ...

Diese Schicht ist der eigentliche Kern jeder Business-Anwendung. Dort spielt die Musik. Dort werden Transaktionen aufgespannt, Daten validiert, die eigentlichen Berechnungen gemacht, usw.. Trotzdem taucht diese Schicht in Architekturkonzepten oft eher als Black Box auf. Das ist dann Komponente xy, die macht das. Trotzdem geben sich viele lieber der Jagt nach dem heiligen Gral des Datenzugriffs hin, statt ihre Geschäftslogik sauber in Komponenten zu packen und deren Abhängigkeiten klar festzulegen. Das ist zugegeben auch nicht ganz einfach, da sich Geschäftslogik gerne in kleine Ritzen verdrückt. Ein bisschen wandert in SQL-Code, ein ordentlicher Happen versteckt sich in der Benutzeroberfläche und manches bleibt unauffällig in JavaScripts kleben. Deshalb sollte bei jedem Programmteil sorgfälig überlegt werden, welchee Teile der Geschäftslogik bewusst im GUI-Code, was im Code der Geschäftslogik-Komponenten/Diensten und was in der Datenbank implementiert wird.

Zitat von Golo Roden:
- Was haltet Ihr von dieser Aufteilung?

Ich habe ja schon einiges direkt kommentiert. Du beschreibst eigentlich eine klassische 3-Tier Architektur. Damit habe ich gute Erfahrungen gemacht.

Zitat von Golo Roden:
- Wo würdet Ihr RPC-Grenzen ziehen? Wo würdet Ihr Stack-Grenzen ziehen?

Ich würde die Anwendung in einzelne Komponenten/Dienste aufteilen, die möglichst unabhängig voneinander sind. Abhängigkeiten lassen sich natürlich nie vermeiden. Deshalb müssen sie klar geregelt werden. Mein Ansatz ist dabei, die Komponenten/Dienste in Kategorieen (nicht mit den Schichten verwechseln) einzuteilen. Diese Kategorieen könnten für eine ERP-Anwendung z.B. so aussehen:
  • Infrastruktur-Dienste (Authentifizierung, Authorisierung, Sitzungsverwaltung, Server-Jobs, ...)
  • Basis-Dienste (Mandanten-Verwaltung, Verwaltung von Grunddaten wie Einheiten, Währungen, Zahlungsbedingungen, Textbausteinen ...)
  • Stammdaten-Dienste (Artikelstamm, Geschäftspartner, Preise, Lagerverwaltung)
  • Prozess-Dienste (Angebotswesen, Einkauf, Verkauf)
  • Kontroll-Dienste (Disposition, Auswertungen/Reporting)
Alle Komponenten/Dienste werden genau einer dieser Kategorieen zugewiesen. Komponenten/Dienste dürfen nur auf andere Komponenten/Dienste zugreifen, wenn diese in einer niedrigeren Kategorie sind. Von Komponenten des Artikelstamms darf z.B. auf die Mandanten-Verwaltung oder die Server-Jobs zugegriffen werden, aber nicht auf Geschäftspartner, Einkauf oder Disposition. Zugegriffe müssen über RPC erfolgen. Greift eine Komponente/Dienst auf eine andere Komponente/Dienst zu, wird die abgewickelt, als würde z.B. ein Windows.Forms-GUI-Client auf die Komponente/Dienst zugreifen. Die Identität bzw die Sitzungsinformationen werden dabei mitgeschleift. Verkettete Dienstaufrufe verwendenalso normalerweise immer die Sitzung des ersten RPC-Aufrufers (Meistens ein GUI-Client). Dienste dürfen nür über definieirte Schnittstellen aufgerufen werden.
Komponenten/Dienste, die in der selben Assembly liegen, dürfen sich direkt aufrufen und müssen nicht über RPC gehen. Das ist wichtig, damit man Strukturierungsmöglichkeiten innerhalb der Geschäftslogik-Komponenten hat. Es ist auch von Vorteil, die eigentliche Implementierung der Geschäftslogik von der Kommunikations-Infrastruktur zu trennen. Mit Remoting geht das sehr gut. Die Dienst-Implementierung kümmert sich um Kommunikation und Aspekte wie Authentifizierung und delegiert den Aufruf anschließend an die eigentliche Logik-Implementierung. Diese muss dann auch nicht von MarshalByRef ableiten und kann bequem in einer separten Assembly untergebracht werden. Ich habe ein Architekturbeispiel gemacht, welches diese Konzept sehr schön zeigt:  .NET Applikationsserver
Mit WCF kann man es genauso machen.
GUI-Clients jeder Art (also auch ASP.NET Seiten auf Webservern etc.) greifen immer über RCP zu. Bei Web ist das sogar besonders wichtig, da man das Web-Front-End so besser absichern kann.

Zitat von Golo Roden:
- Wie würdet Ihr die Kommunikation über RPC aufbauen, insbesondere Events, die Rückmeldungen liefern?

So statuslos wie möglich! Je weniger statusbehaftet, desto skalierbarer. Wenn Du Serverfarmen unterstützen willst/musst, solltest Du die Sitzungen zwischen den Servern replizieren oder in der DB halten. Welche Metode die bessere ist, hängt vom Einzelfall ab. Eine Sitzung sollte so wenig Daten wie möglich enthalten. Bei mir ist das z.B. nur folgendes:
  • Sitzungsschlüssel (Guid)
  • Benutzeridentität (IIdentity)
  • Kultureinstellungen des Benutzers (CultureInfo x 2; 1 x UI; 1 x Env.)
  • Zeitstempel (Datetime)
Events würde ich vermeiden. Zur Beanchrichtigung für freigegebene Sperren, wenn ein Client darauf wartet und der Benutzer die schnellsmögliche Rückmeldung braucht, sind Events allerings fein. Ansonsten würde ich immer versuchen es ohne Events zu lösen.
Asynchrone Verarbeitung ist das Zauberwort für Automatisierbarkeit. Man sollte dem Server Aufträge (Jobs) in Warteschlangen stellen können, die er im Hintergrund abarbeitet. Asynchrone Verarbeiten ermöglicht auch den Einsatz einer Workflow-Engine wie z.B. WF.

Zitat von Golo Roden:
- Was fehlt bei dem ganzen Ansatz?

Der bzw. die GUI-Client(s)! 80% des Aufwandes einer Geschäftsanwendung entfallen auf die Benutzeroberfläche. Der temporäre Status sollte beim GUI-Client liegen. Im Falle eines Web-Clients ist das der ASP.NET Sitzungsstatus bzw. Javascript im Browser. Besonders wenn Du verschiedene GUI-Clients anbieten willst/musst, solltest Du das in Deinem Entwurf berücksichtigen. Wenn Du z.B. einen GUI-Client für Windows Mobile oder für Handys (evtl. in Java geschrieben) haben willst, musst Du Dir bereits beim Entwurf Gedanken machen, wie solch ein Client mit der Geschäftslogik redet. Das Compact Framework kann z.B. kein Remoting und Java natürlich auch nicht. Die Frage, ob Du Deine Geschäftskomponenten/Dienste über unterschiedliche Endpunkte (z.B. binär TCP und HTTP SOAP) anbieten musst, hängt nicht zuletzt von der GUI-Client-Frage ab.

Zitat von Golo Roden:
- Wo habe ich etwas grundlegendes vergessen?

Bei den folgenden Überlegungen gehe ich davon aus, dass Du eine Software schreibst und an Kunden im kompilierten Zustand auslieferst. Bei einer Inhouse-Anwendung treffen einige der Überlegungen nicht zu.
Wie kann die Anwendung später vom sachverständigen Endanwender erweitert und angepasst werden? Wie sieht es mit Add-Ins aus? Geschäftsprozesse ändern sich oft schneller, als ein Software-Anbieter reagieren kann. Deshalb sollte eine moderne Business-Anwendung Erweiterungsmöglichkeiten haben. Wenn nun bei jeder Lagerbuchung plötzlich eine Webservice einer Drittanwendung aufgerufen werden soll, muss das machbar sein, ohne den Lagerverwaltungsdienst anfassen zu müssen. Deshalb muss es Punkte in der Anwendung geben, die es einem Customizer oder Entwickler erlauben sich einzuhängen. Office ist ein gutes Beispiel. In Outlook oder Work kann ich Add-Ins und Makros schreiben. Das sollte auch für die Geschäftskomponenten/Dienste Deiner Anwendung möglich sein. Auch deshalb ist es ratsam Implementierung von Dienst und eigentlicher Geschäftslgik zu trennen. Die Dienst-Implementierung kann bei Bedarf konfigurierte Add-Ins oder sogar VB.NET/C#-Code laden und diesen an festgelegten Punkten die Kontrolle übertragen.
Deployment und Updates fallen mir da noch ein. Für mich ist das Teil der Architektur. Auch PlugIns etc. müssen auf Client- und ggf. auch auf die Server-Maschine(n) verteilt werden.
Wie werden Schnittstellen versioniert? Werden Client- und Server-Komponenten getrennt versioniert, oder eine Version für alle Assemblies des Anwendung? Ist ein Versionierung überhaupt nötig?
Wie wird die Datenbank bzw. deren Struktur versioniert? Wie können Anwender die DB erweitern, ohne die Updatefähigkeit zu verlieren?
10.10.2008 02:25 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Khalid Khalid ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2534.gif


Dabei seit: 19.07.2005
Beiträge: 3.466
Entwicklungsumgebung: Visual Studio 15/17
Herkunft: Hannover


Khalid ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Rainbird

Sehr schöne detailierte Antwort.

Eine Frage dazu

Zitat:
  • Infrastruktur-Dienste (Authentifizierung, Authorisierung, Sitzungsverwaltung, Server-Jobs, ...)
  • Basis-Dienste (Mandanten-Verwaltung, Verwaltung von Grunddaten wie Einheiten, Währungen, Zahlungsbedingungen, Textbausteinen ...)
  • Stammdaten-Dienste (Artikelstamm, Geschäftspartner, Preise, Lagerverwaltung)
  • Prozess-Dienste (Angebotswesen, Einkauf, Verkauf)
  • Kontroll-Dienste (Disposition, Auswertungen/Reporting)

Welche Dienste würden in diesen Falle direkt auf die Datenbank zugreifen? So wie ich es sehe wären es ja die ersten Drei, die direkt zugreifen, oder?

Ist jetzt nur rein aus Verständnis, weil ich es bei meinen Anwendungsserver zurzeit strikt einhalte, das nur ein einziger Dienst auf die DB zugreifen darf.
10.10.2008 09:51 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Rainbird Rainbird ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2834.jpg


Dabei seit: 28.05.2005
Beiträge: 3.720
Entwicklungsumgebung: Visual Studio 2012
Herkunft: Mauer


Rainbird ist offline

Nicht mit den Schichten verwechseln

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von Khalid:
Welche Dienste würden in diesen Falle direkt auf die Datenbank zugreifen? So wie ich es sehe wären es ja die ersten Drei, die direkt zugreifen, oder?

Die Kategorieen haben nichts mit den Schichten zu tun! Es ist nicht so, dass die einzelnen Kategorieen bestimmten Schichten zugeordnet werden. Alle Dienste, dieser Kategorieen liegen in der Mittelschicht (Geschäftslogik).

Jeder Dienst greift direkt auf die Datenbank. Natürlich tut er das nicht unbedingt über ein direktes SqlCommand, sondern - wenn Abstraktion vom RDBMS für das Projekt wichtig ist - über eine Datenzugriffsschicht (Das könnte eine einfache Hilfsklasse sein, oder ein komplexes ADO.NET Entity Model mit Mappings und allem drum und dran).
Da verschiedene Dienste auch verschiedene Datenquellen haben können (Je größer das Projekt desto höher die Wahrscheinlichkeit, dass die Daten an verschiedenen Quellen liegen), würde ich den Datenzugriff nicht über einen zentralen Dienst schleusen, sondern die Datenzugriffsschicht direkt (also ohne RPC) innerhalb jedes Dienstes konsumieren.
Ich fasse außerdem Dienstschnittstellen und Datenstrukturen (in WCF würde man sagen DataContracts) pro Programmmodul in einer Contract-Assembly zusammen. Diese würde auch das ADO.NET Entity Model, die DataSets oder die Linq2SQL Klassen enthalten (Je nach eingesetzter Datenzugriffs-Technologie). Für die Architektur spielt das aber keine Rolle.
10.10.2008 10:21 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Khalid Khalid ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2534.gif


Dabei seit: 19.07.2005
Beiträge: 3.466
Entwicklungsumgebung: Visual Studio 15/17
Herkunft: Hannover


Khalid ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat:
Die Kategorieen haben nichts mit den Schichten zu tun! Es ist nicht so, dass die einzelnen Kategorieen bestimmten Schichten zugeordnet werden. Alle Dienste, dieser Kategorieen liegen in der Mittelschicht (Geschäftslogik).

Ah OK. Dann ergibt das für mich jetzt alles wieder mehr Sinn smile
Ich habe das irgendwie anders interpretiert.

Zitat:
Ich fasse außerdem Dienstschnittstellen und Datenstrukturen (in WCF würde man sagen DataContracts) pro Programmmodul in einer Contract-Assembly zusammen

So mach ich das auch.
10.10.2008 11:05 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Sebi Sebi ist männlich
myCSharp.de-Mitglied

Dabei seit: 31.08.2008
Beiträge: 167


Sebi ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Rainbird,
in deiner Ausführung hast du Artikelstamm und Lagerverwaltung auf gleicher Ebene. Braucht aber nicht die Lagerverwaltung zugriff auf den Artikelstamm?
10.10.2008 14:04 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Rainbird Rainbird ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2834.jpg


Dabei seit: 28.05.2005
Beiträge: 3.720
Entwicklungsumgebung: Visual Studio 2012
Herkunft: Mauer


Rainbird ist offline

Artikelstamm und Lager

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Sebi,

das kann man so und so implementieren. Wenn in den Bestandsdatensätzen und damit auch für Buchungen nur die ArticleID benötigt wird, muss die Lagerverwaltung auch nicht auf den Artikelstamm zugreifen. Allerdings muss die GUI der Lagerverwaltung den Artikelstamm-Dienst konsumieren. Der Benutzer möchte natürlich detailierte Daten sehen.

Die Geschäftsdienste sind zwar autonom, aber sie werden von höheren Kategorieen aus und von Clients konsumiert und damit kombiniert. In diesem Modell muss man sich von der Vorstellung lösen, dass GUI-Client und Geschäftsdienste symmetrisch sind.

Die Anwendung besteht aus einer Sammlung von Diensten. Aus Hosting Sicht leben diese alle nebeneinander. Um die Abhängigkeiten im Griff zu haben, teilt man die Dieste in eine gedachte Hierarchie von Kategorien ein. GUI-Clients stehen ganz oben und dürfen theoretisch sämtliche Dienste Kreuz und Quer konsumieren. Die Dieste sind sozusagen das API der Business-Anwendung. Welche Dienste ein GUI-Client-Modul konsumieren darf ist eher eine Frage des Deployments und der Lizenzierung (Im Falle einer kommerziellen Anwendung)

Es wäre aber auch nicht falsch, fuer die Lagerverwaltung eine eigene Kategorie einzuschieben. Die Kategorieen sind ja nur gedacht und verursachen an sich keinen Aufwand.
10.10.2008 23:55 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Sebi Sebi ist männlich
myCSharp.de-Mitglied

Dabei seit: 31.08.2008
Beiträge: 167


Sebi ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,
das heißt dann arbeiten die Dienste mit den weiter oben erwähnten Entities welche dann in ner höheren Ebene die Zugriff auf die entsprechenden Dienste hat zu Business Objekten zusammengebaut werden?
14.10.2008 19:43 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Rainbird Rainbird ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2834.jpg


Dabei seit: 28.05.2005
Beiträge: 3.720
Entwicklungsumgebung: Visual Studio 2012
Herkunft: Mauer


Rainbird ist offline

Kontrakte

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Sebi,

was meinst Du genau mit Business Objekten? Der Begriff ist ein wenig schwammig.

Nicht in Schichten denken! Geschäftslogik, Dienste, Dienstschnittstellen und Datenstrukturen liegen alle zusammen in der Mittelschicht. Die Datenstrukturen werden von Geschäftslogik und Diensten gemeinsam genutzt. Im WCF-Jargon würde man Datenstrukturen DataContracts bzw. MessageContracts nennen. Vom ADO.NET Entity Framework erzeugte Objekte sind übrigens automatisch DataContracts.
Es könnten aber auch beliebige serialisierbare Objekte sein (z.B. DataSets/DataTables). Das spielt aber nicht wirklich eine Rolle.
14.10.2008 22:43 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Omit Omit ist männlich
myCSharp.de-Mitglied

images/avatars/avatar-2748.jpg


Dabei seit: 20.10.2008
Beiträge: 143


Omit ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hi Leute,

Zitat von Golo:
Bereits hier sollte mit Transaktionen gearbeitet werden, zudem bietet sich in der unteren Schicht evtl der Einsatz eines O/R-Mappers an. Auch Locking sollte hier in den grundlegenden Funktionen verfügbar sein, sprich Datensatz sperren, Datensatz entsperren, usw ...

Zitat von Rainbird:
Transaktionen müssen ja erst aufgespannt werden. Verschiedene Komponenten können an einer Transaktion beteiligt sein. Die Datenzugriffsschicht kann das nicht leisten, da es vom Geschäftsprozess abhängig ist, welche Operationen zusammen in einer Transaktion ausgeführt werden müssen. Deshalb haben Transaktion in der Datenzugriffsschicht eigentlich nix verloren. Aber auch das ist bereits mit System.Transactions gelöst. ADO.NET, LINQ2SQL und Entity Framework unterstützen System.Transactions-Transaktionen.

korrigiert mich, wenn ich falsch liege...

Ich würde sagen, irgendwie habt ihr beide recht und ihr widerlegt euch ja auch nicht gegenseitig.
Wie es schon Golo sagt, wäre auch meine Intention, in den Datenzugriffslogiken Transaktionen aufzuspannen. Denn die Aufgabe von diesen ist es ja, auch aus (möglichen) mehreren Datenquellen, die Entities zusammen zu setzten und wieder abzuspeichern. Da dies auch über mehrere Abfragen geschehen kann, müssen klar auch schon hier Transaktionen zum Einsatz kommen.

Rainbird du hast zwar Recht, dass Geschäftsprozesse Transaktionen über mehrer Entities aufspannen müssen, aber es spricht ja nichts dagegen besetehende Transaktionen nochmals zu verpacken.

Ansonsten finde ich beide Ausführungen sehr interessant!

Gruß Timo
22.10.2008 15:09 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Rainbird Rainbird ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2834.jpg


Dabei seit: 28.05.2005
Beiträge: 3.720
Entwicklungsumgebung: Visual Studio 2012
Herkunft: Mauer


Rainbird ist offline

Transaktionen

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Omit,

natürlich kann man Transaktionen schachteln. Wenn die Datenzugriffsschicht allerdings generell alles in Transaktionen packt, hat man z.B. ein Problem, wenn eine bestimmte Operation nicht in einer Transaktion ablaufen soll. Wenn die Datenzugriffsschicht die Transaktionen nicht automatisch macht und man sie manuell aufrufen muss, kann man auch gleich alles in der Geschäftslogik mit System.Transactions machen.

Bei langlaufenden oder anwendungsübergreifenden Geschäftsprozessen müssen statt atomarer Transaktionen eh Sagas ( http://www.serviceoriented.org/long_runn...ansactions.html) zum Einsatz kommen. Spätestens bei solchen Sachen (die bei jeder größeren Business-Anwendung früher oder später auftreten) ist es nicht mehr sinnvoll, die Transaktionslogik auf Geschäfts- und Datenzugriffsschicht zu versteuen.

Trotzdem kann es natürlich Projekte geben, bei denen es Sinn macht, Transaktionen auch direkt in der Datenzugriffsschicht aufzuspannen (Pauschalaussagen sind nämlich generell mit vorsicht zu genießen). Nach meiner Erfahrung ist es aber - zumindest für Business-Applikationen - nicht optimal.

WF-Workflows eignen sich übrigens auch sehr gut, um Transaktionen in Geschäftsprozessen einzubringen. Mit den Workflow Services (WF über WCF) können so auch gut externe Anwendungen angekoppelt werden.
23.10.2008 21:35 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Omit Omit ist männlich
myCSharp.de-Mitglied

images/avatars/avatar-2748.jpg


Dabei seit: 20.10.2008
Beiträge: 143


Omit ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Mit Long Running Transactions hab ich mich noch nicht beschäftigt. Deshalb habe ich eine Frage:

Zitat:
Long Running Transactions (LRT, also known as Sagas) are transactions that may take minutes, days or weeks before the outcome of the transaction is known.

Verstehe ich das richtig, dann sind alle Ressourcen solang gesperrt, oder wie realisiert man so eine Transaktion? Oder muss man dann alles einzeln wieder zurück aufdröseln?

Ach danke für  http://www.serviceoriented.org/ , kannte ich noch nicht und scheint wirklich sehr gut zu sein. Nach meiner Klausur, werde ich mich da durchackern *freu*, kann mich kaum zurück halten(Timo NACH der Klausur *g)!

Gruß TimoW

Dieser Beitrag wurde 3 mal editiert, zum letzten Mal von Omit am 23.10.2008 21:59.

23.10.2008 21:46 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
herbivore
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2627.gif


Dabei seit: 11.01.2005
Beiträge: 49.353
Entwicklungsumgebung: csc/nmake (nothing is faster)
Herkunft: Berlin


herbivore ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Omit,

Zitat:
Verstehe ich das richtig, dann sind alle Ressourcen solang gesperrt, oder wie realisiert man so eine Transaktion?

typischerweise würde man dann nicht pessimistisch sperren, sondern ein ==> optimistisches Sperrverfahren verwenden.

herbivore
24.10.2008 08:05 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Omit Omit ist männlich
myCSharp.de-Mitglied

images/avatars/avatar-2748.jpg


Dabei seit: 20.10.2008
Beiträge: 143


Omit ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

OK danke, war mir jetzt ganz entfallen. Aber klar. Muss mich damit nochmal auseinandersetzten!

Gruß Timo
24.10.2008 11:24 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
_daniel_
myCSharp.de-Mitglied

Dabei seit: 31.05.2006
Beiträge: 227


_daniel_ ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo
wo würdet ihr in einer solchen SOA Umgebung die Prüfung einordnen die das löschen eines Mandanten verbietet wenn noch offene Aufträge existieren?
31.10.2008 14:45 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Rainbird Rainbird ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2834.jpg


Dabei seit: 28.05.2005
Beiträge: 3.720
Entwicklungsumgebung: Visual Studio 2012
Herkunft: Mauer


Rainbird ist offline

Dienstekategorieen

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo _daniel_,

ausgehend davon, dass die Dienste der Applikation in Kategorieen eingeteilt wurden und in einer gedachten Hierarchie angeordnet sind, kannst Du die Prüfung nicht direkt im Mandantenverwaltungsdienst machen, da der Mandantenverwaltungsdienst vermutlich in einer niedrigeren Kategorie ist als der Dienst zur Auftragsabwicklung.
Also muss man auf höherer Ebene einen Dienst einziehen, der solche Workflows kapselt (ich nenne den jetzt einfach mal Workflow-Dienst). Den Löschbefehl willst Du zwar über den Mandantenverwaltungsdienst geben, aber die Prüfung darf nicht direkt in diesem Dienst gemacht werden. Der Workflow-Dienst muss also irgendwie mitbekommen, dass jemand einen Mandanten löschen will. Damit das geht, muss der Mandantenverwaltungsdienst die Möglichkeit bieten, dass man per Konfiguration andere Dienste als Empfänger von Nachrichten bei bestimmten Ereignissen konfigurieren kann. Es funktioniert dann vom Prinzip her, wie bei einem FormClosing-Ereignis in Windows.Forms. Bei diesem Ereignis kann man mittels e.Cancel=true dem FOrmular mitteilen, dass das Schließen abgebrochen wird. Genauso könnte der Workflowdienst per Abo vom Mandantenverwaltungsdienst benachrichtigt werden, dass ein Mandant gelöscht werden soll. Der Workflow-Dienst führt die Prüfung durch (konsumiert dazu den Dienst zur Auftragsabwicklung) und sendet dem Mandantenverwaltungsdienst eine Nachricht zurück, ob Abgebrochen werden soll, oder nicht. Wichtig dabei ist, dass die Kommunikation entkoppelt abläuft. Der Mandantenverwaltungsdienst darf weder die Schnittstelle noch die Implementierung des Workflow-Dienstes kennen.

Man sollte sich bei so einer Situation auch Gedanken machen, ob das alles synchron oder asynchron ablaufen soll. Je größer die Anwendung, desto eher würde ich alles asynchron machen.

So ein lose gekoppeltes Ereignissystem ist auch bei vielen anderen Dingen nützlich, da man die Abgebildeten Geschäftsprozesse so ändern und beeinflussen kann, ohne laufende fertige Dienste anzufassen. Das macht unterm Strich eine schnellere Reaktionszeit auf Änderungen am Geschäftsprozess.
01.11.2008 13:46 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
_daniel_
myCSharp.de-Mitglied

Dabei seit: 31.05.2006
Beiträge: 227


_daniel_ ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,
das heißt der Client arbeitet nur mit den Workflows welche dann wiederrum mit den Diensten kommunizieren oder die Workflows "überwachen" praktisch die Arbeit der Dienste?
01.11.2008 15:47 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Rainbird Rainbird ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2834.jpg


Dabei seit: 28.05.2005
Beiträge: 3.720
Entwicklungsumgebung: Visual Studio 2012
Herkunft: Mauer


Rainbird ist offline

Keine Schichten

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo _daniel_,

Der Workflowdienst überwacht den Mandantenverwaltungsdienst in diesem Fall. Wenn der Client einen Mandanten löschen will, dann tut er das über den Mandantenverwaltungsdienst. Der Mandantenverwaltungsdienst stellt seinerseits einen Publish-Subscribe-Mechanismus zur Verfügung, damit andere Dienste/Komponenten "Ereignisse" abonnieren und sich in die Verarbeitung einschalten können. Der Workflowdienst wird nicht direkt vom Client aufgerufen, sondern vom Mandantenverwaltungsdienst benachrichtigt, dass ein Mandant gelöscht werden soll. Der Mandantenverwaltungsdienst kennt den Workflowdienst aber nicht! Genauso wie ein Button nicht das Form kennt, welches sein Click-Ereignis behandelt.

Wenn der Client den Mandnatenlöschbefehl direkt über den Workflowdienst laufen würde, müsste dieser alle Operationen des Mandantenverwaltungsdienstes kapseln. Das ist ein Schichtendenken, das an dieser Stelle nur Nachteile bringt. Die API der Applikation wäre dadurch nicht mehr intuitiv. Wenn ich einen Mandanten löschen will, liegt es nahe, dies über den gleichnahmigen Dienst zu tun.
03.11.2008 07:01 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
_daniel_
myCSharp.de-Mitglied

Dabei seit: 31.05.2006
Beiträge: 227


_daniel_ ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,
danke für die Erläuterungen.

Wie würden Workflows der Workflow Foundation in das Konzept passen?
04.11.2008 00:28 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Rainbird Rainbird ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2834.jpg


Dabei seit: 28.05.2005
Beiträge: 3.720
Entwicklungsumgebung: Visual Studio 2012
Herkunft: Mauer


Rainbird ist offline

Wf

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo _daniel_,

die würden sehr gut passen. Im .NET Framework 3.5 gint es die sog. Workflow Services. Das ist eine Technologie, die es realtiv einfach ermöglicht, WF-Workflows direkt als WCF-Dienste zu hosten. Für den Aufrufer sehen die Workflows aus, wie ganz gewöhnliche WCF-Dienste. Für Diese, die längerandauernde Abläufe abbilden, sind WF-Workflows ideal. Besonders langlaufende Transaktionen (Sagas) lassen sich mit WF grafisch entwerfen. Die wichtigsten Activities bringt WF schon mit.
Man sollte den Aufwand WF-Workflows zu erstellen und diue Einarbeitungszeit allerdings nicht unterschätzen. WF ist komplex und aufwändig! Auch über das Deployment muss man sich Gedanken machen. Für gewöhnlich möchte man Workflows kurzfristig anpassen können, ohne eine komplett neue Programmversion ausrollen zu müssen. Geänderte Workflows müssen ihren Weg auf den Applikationsserver finden.
Wenn die Infrastruktur für das Hosting von WF-Workflows in den eigenen Anwendungen mal steht, hat man sich mit Sicherheit jede Menge Vorteile eingekauft. Man sollte es - wie mit allem - auch mit den Workflows nicht übertreiben. Einsetzen, wo sinnvoll, ansonsten lassen.
04.11.2008 08:17 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
_daniel_
myCSharp.de-Mitglied

Dabei seit: 31.05.2006
Beiträge: 227


_daniel_ ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,
zumal die neue Version mit den alten wohl nicht ganz kompatibel ist.

Heißt es in diesem fall dann dass der Client mit den Workflows abeitet? Oder auch hier nur indirekt über Events der Services?
04.11.2008 09:19 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Rainbird Rainbird ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2834.jpg


Dabei seit: 28.05.2005
Beiträge: 3.720
Entwicklungsumgebung: Visual Studio 2012
Herkunft: Mauer


Rainbird ist offline

Workflows

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo _daniel_,

Workflows sind ein weites Feld und sehr vielseitig einsetzbar. Es ging ursprünglich ja um den konkreten Fall, dass vor der Löschung eines Mandanten geprüft werden muss, ob noch Aufträge unter diesem Mandanten existieren. Die Prüfung darf die Mandantenverwaltung allerdings nicht direkt durchführen, da dies zu einer zirkulären Abhängigkeit zwischen Mandanten- und Auftragsverwaltung führen würde. In diesem konkreten Fall könnte man das sehr elegant lösen, in dem ein als Workflow implementierter Dienst die Mandantenverwaltung überwacht (bzw. von dieser informiert wird).

Das heißt nicht, dass das immer der beste Weg ist. Mit WF können sowohl langlaufende (also z.B. über Stunden, Tage, Wochen oder sogar Jahre) als auch kurzlaufende Workflows abgewickelt werden. Man könnte einen WF-Workflow durchaus innerhalb eines Windows.Forms-Clients einsetzen, um zu steuern wann welche Knöpfe auf Menü- und Symbolleisten ausgegraut werden und wann nicht. Man kann aber auch ein großes Geschäft - welches über Monate läuft - inklusive Beschaffung, Terminierung, Auslieferung, Zahlung, Reklamation etc. über einen komplexen Workflow steuern.

Wenn Menschen in einen Workflow direkt eingebunden sind (um z.B. Eingaben zu machen oder etwas zu genehmigen bzw. abzulehnen) ist es sinnvoll, dass Clients direkt mit einzelnen Workflow-Instanzen kommunizieren. Mittels Hosting in Workflow Services und SOAP-Kommunikation lassen sich so vor allem auch fremde Applikationen in Workflows einbinden (man denke z.B. an InfoPath).

Es kommt auf die konkreten Geschäftsprozesse an, die abgebildet werden sollen, ob und in welcher Form Workflows vorteilhaft sein. Eine pauschale Aussage gibt es da nicht. Wichtig ist, dass man die Geschäftsprozesse , die man als Software umsetzen möchte selbst sehr gut kennt auch versteht. Mangelndes Wissen und Verständnis über die Problemdomäne ist bei Software-Entwicklen generell ein Problem. Es scheint of viel interessanter zu sein, an der perfekten OR-Mapping-Implementierung zu feilen, statt sich mit den Problemen der Fachabteilungen rumzuärgern. Die Software-Architektur muss aufgrund der abzubildenden Geschäftsprozesse festgelegt werden.

Was für Geschäftsprozesse willst/musst Du denn umsetzen?
04.11.2008 21:46 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
_daniel_
myCSharp.de-Mitglied

Dabei seit: 31.05.2006
Beiträge: 227


_daniel_ ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,
bei mir geht es in die Richtung die ich angeschnitten habe mit Mandant, Angebot,Auftrag, Bestellung, Lager usw.

Das verstehen der Prozesse sehe ich auch als enorm wichtig.
Überlegt hatte ich zwei Richtungen
1. ein Workflow geht vom Erstellen eines Angebots über die Komplettierung bis zum "Ausgabe"
und (oder)
2. ein Workflow geht vom Angebot über den Auftrag zur Lieferung. Wobei hier in regelmäßigen Abständen alle die bei Angebot hängen rausfliegen.


Allgemein habe ich mich für eine Servcie-orientierte Architektur entschieden weil verschiedene Services noch an anderen Stellen benötigt werden z.b. Kontaktdaten für die Telefonanlage und Exchange, kleinere Anwendungen in der Produktion sowie Lager.
Wobei ich hier noch nicht ganz sicher bin wie ich die Services am besten hoste. Erste überlegungen gehen wohl richtung Windows Service da ich hier zentrale dinge wie logging und caching habe. Alternativ könnte jeder Service sein eigenes Caching haben.


Haupt-Client seitig ist es eine modularen Anwendung die das Composite WPF von p&p nutzt.
05.11.2008 00:01 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Rainbird Rainbird ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2834.jpg


Dabei seit: 28.05.2005
Beiträge: 3.720
Entwicklungsumgebung: Visual Studio 2012
Herkunft: Mauer


Rainbird ist offline

Angebote & Lieferung/Rechnung

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo _daniel_,

ich würde den Lead/Anfrage/Angebots-Workflow vom Auftrags-Workflow trennen. In Auftragserfassung/Lieferung und Rechnungswesen ändert sich der Ablauf eher selten. Bei Vetriebs-Ablufen, wie Angeboten, ist damit zu rechnen, dass sich häufiger etwas am Ablauf ändert oder neue Geschäftsregeln zusätzlich installiert werden.

Was meist Du mit Caching? Was sollen die Dienste denn genau cachen?
11.11.2008 22:10 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
_daniel_
myCSharp.de-Mitglied

Dabei seit: 31.05.2006
Beiträge: 227


_daniel_ ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,
dabei dachte ich beispielsweise daran, dass irgendwelche Textbausteine oder ähnliches.

Nochmal rekapituliert:
Workflows Services, welche die Geschäftsprozesse abbilden abonnieren Events der Services um sich dort "einzuschalten".
Hab ich das soweit richtig verstanden?
12.11.2008 13:56 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Rainbird Rainbird ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2834.jpg


Dabei seit: 28.05.2005
Beiträge: 3.720
Entwicklungsumgebung: Visual Studio 2012
Herkunft: Mauer


Rainbird ist offline

Verständnisfrage

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat:
Workflows Services, welche die Geschäftsprozesse abbilden abonnieren Events der Services um sich dort "einzuschalten".
Hab ich das soweit richtig verstanden?

Grundsätzlich ja.

Allerdings sind mit Events nicht unbedingt C#-Events im Sinne von Button.Click zu verstehen. Eine allgemeinere Bezeichnung wäre: Publish/Subscribe-Mechanismus.

Mit Caching wäre ich vorsichtig. Der SQL Server bringt ein sehr gutes Caching bereits automatisch mit. In den meisten Fällen ist es besser, solchen Kleinkram wie Textbausteine dann vom RDBMS abzurufen, wenn man es braucht. Es im Hauptspeicher des Applikationsservers herumgemmeln zu lassen, obwohl mehr als 99% der Laufzeit des Systems niemand auf Textbausteine zugreift, bringt denke ich, wenig. Im Gegenteil. Es vergeudet den kostbaren Arbeitsspeicher des Servers. Am Ende kostet der Abgleich zwischen Cache und DB mehr als das Caching brint, denn Textbausteine können ja auch geändert werden. Der Cache sollte dann ungültig werden und neu aufgefüllt werden bzw. aktualisiert werden.
12.11.2008 21:45 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
_daniel_
myCSharp.de-Mitglied

Dabei seit: 31.05.2006
Beiträge: 227


_daniel_ ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,
ja so einen Publish/Subscribe Menachnismus war gemeint.

Wie ist sowas denkbar?
Jeder Service veröffentlicht direkt oder die Services veröffentlichen ihre Events im Host und die Publisher fragen im Host nach den Events?
Oder wie kann sowas aussehen?


/edit:
Vielleicht etwas blöd formuliert oben. Konkret meine ich ob das Events Publishing/Subscribing auch über WCF oder über den Host laufen sollte.

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von _daniel_ am 19.11.2008 17:54.

18.11.2008 22:33 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Rainbird Rainbird ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2834.jpg


Dabei seit: 28.05.2005
Beiträge: 3.720
Entwicklungsumgebung: Visual Studio 2012
Herkunft: Mauer


Rainbird ist offline

Beispiel von Dienst-Ereignissen

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von _daniel_:
Wie ist sowas denkbar?

Es gibt verschiedene Möglichkeiten, so einen Mechanismus zu implementieren. Ich will eine davon kurz vorstellen. Ich nenne das Konzept mal Pre-Action/Action/Post-Action. Dabei können für jede Dienst-Operationen beliebig viele Pre- und Post-Aktionen registriert werden. Die Aktionen werden in EventAdapter-Klassen implementiert. Diese Adapter werden über eine XML-Konfigurationsdatei als Pre- oder Post-Aktionen bestimmter Dienst-Operationen konfiguriert und mittels Microkernel geladen.
Damit das Ganze etwas besser nachvollziehbar ist, gehe ich als Basis von meinem N-Tier-Architekturbeispiel aus. Dort gibt es einen Dienst zur Verwaltung des Artikelstammes. Angenommen beim Anlegen eines neuen Artikels soll ein Workflow angestossen werden, der über die Veröffentlichung des neuen Artikels im firmeneigenen Webshop entscheidet. Die Implementierung der Geschäftslogik (ProductManager) soll dazu nicht angerührt werden. Damit der Workflow getriggert werden kann, muss die Dienst-Operation zum Speichern von Artikeln (SaveProducts-Methode) der Infrastruktur mitteilen, dass vor bzw. nach der Ausführung der eigentlichen Geschäftslogik-Implementierung ggf. registrierte Ereignisempfänger aufgerufen werden sollen. Das könnte in der Praxis so aussehen:

C#-Code:
/// <summary>
/// Speichert Produkt-Datensätze innerhlb einer Transaktion.
/// </summary>
/// <param name="products">Produktdatensätze</param>
/// <param name="transaction">Transaktion (Optional)</param>
/// <returns>Tabelle mit gespeicherten Produktdatensätzen</returns>
public ArticleMasterDataSet.ProductsDataTable SaveProducts(ArticleMasterDataSet.ProductsDataTable products, Transaction transaction)
{
    // Ländereinstellungen vom Aufrufer annehmen
    ApplicationServer.AssumeCultureFromSession();

    // Wenn der Aufrufer in der Rolle "Product Writer" ist ...
    if (ApplicationServer.IsInRole("Product Writer"))
    {
        // Variable für Rückgabe-Tabelle
        ArticleMasterDataSet.ProductsDataTable result = null;

        // Ggf. an Transaktion des Aufrufers teilnehmen
        Transaction.Current = transaction;

        // Automatische Transaktion erzwingen
        using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
        {
            // Parameterliste erzeugen
            Dictionary<string,object> parameters=new Dictionary<string,object>();
            parameters.Add("products",products);
            parameters.Add("transaction",Transaction.Current);

            // Kontextinformationen dieses Dienst-Operations-Aufrufs zusammenstellen
            ServiceOperationContext context = new ServiceOperationContext(typeof(IArticleMasterService), "SaveProducts", parameters);

            // Ggf. registrierte Pre-Actions ausführen ...
            ApplicationServer.ExecuteRegisteredServiceEventPreActions(context);

            // Aufruf an Geschäftslogik delegieren
            result = new ProductManager().SaveProducts(products, Transaction.Current);

            // Ggf. registrierte Post-Actions ausführen ...
            ApplicationServer.ExecuteRegisteredServiceEventPostActions(context);

            // Transaktion(steil) erfolgreich abschließen
            scope.Complete();
        }
        // Tabelle zurückgeben
        return result;
    }
    else
        // Ausnahme werfen
        throw new SecurityException(ApplicationServer.LocalizedAccessDeniedMessage);
}

Die Infrastruktur (in meinem Beispiel im Host implementiert) verwendet folgende XML-Konfigurationsdatei, um Abonnenten für Dienst-Ereignisse zu konfigurieren:

XML-Code:
<?xml version="1.0" encoding="utf-8" ?>
<serviceevents xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:xsd="http://www.w3.org/2001/XMLSchema"
               xmlns="urn:Rainbird.AppServer.EventSubscriptions.2008"
>
  <!-- Dienst -->
  <service name="Rainbird.Examples.NTier.ArticleMaster.Contracts.IArticleMasterService">

    <!-- Dienst-Operation, die als Ereignis veröfentlicht werden soll -->
    <event name="SaveProducts">

      <!-- Post-Action Abonnement des Dienst-Ereignisses -->
      <subscription mode="post-action"
                    assembly="Rainbird.Examples.NTier.WebshopPublishWorkflow.Adapter.dll"
                    class="SaveProductsPostActionEventAdapter"
/>
    </event>

  </service>
</serviceevents>

Die Schnittstelle für Ereignis-Adapter sieht so aus:

C#-Code:
using System;
using System.Collections.Generic;
using System.Text;

namespace Rainbird.AppServer.API
{
    /// <summary>
    /// Schnittstelle für Adapter-Implementierungen zur Behandlug von Dienst-Ereignissen.
    /// </summary>
    public interface IServiceEventAdapter
    {
        /// <summary>
        /// Implementierung dieser Methode wird ausgeführt, wenn ein abonniertes Dienst-Ereignis gefeuert wurde (vor Ausführung der Geschäftslogik).
        /// </summary>
        /// <param name="operationContext">Operations-Kontext</param>
        /// <returns>Schalter für erfolgreiche Ausführung</returns>
        bool PreAction(ServiceOperationContext operationContext);

        /// <summary>
        /// Implementierung dieser Methode wird ausgeführt, wenn ein abonniertes Dienst-Ereignis gefeuert wurde (Nach Ausführung der Geschäftslogik).
        /// </summary>
        /// <param name="operationContext">Operations-Kontext</param>
        /// <returns>Schalter für erfolgreiche Ausführung</returns>
        bool PostAction(ServiceOperationContext operationContext);
    }
}

Wenn Interesse besteht, kann ich eine, um Dienst-Ereignisse erweitere, Version meines Beispiels hier hochladen.

Der Ansatz hat den Vorteil, dass er relativ einfach anzuwenden ist, die Abonnenten via Microkernel entkoppelt sind und so ein Business-System erweitert werden kann, ohne dass es neu kompiliert werden muss. Außerdem lässt sich das Konzept auch nachträglich gut in Systeme einbauen, die von Grund auf synchron aufgebaut sind.
Nachteilig ist, dass die Ausführung der Pre- und Post-Aktionen synchron erfolgt. Die Ausführungszeit von, auf diese Art Ereignis aktivierten, Dienst-Operationen verlängert sich mit jedem zusätzlichen Abonnement. Natürlich kann man in der Ereignis-Adapter-Implementierung asynchron weiterarbeiten, aber diese Verantwotung obliegt dem Entwickler des jeweiligen Adapters.

Besser wäre es, die Mittelschicht grundsätzlich asychron aufzubauen (z.B. über ein Bus-System). Dafür gibt es auch fertige Produkte, wie z.B. den BizTalk Server. Der ist allerdings wieder so allgemein und zudem komplex, dass er für viele Entwickler eher abschreckend ist.

Zitat von _daniel_:
Jeder Service veröffentlicht direkt oder die Services veröffentlichen ihre Events im Host und die Publisher fragen im Host nach den Events?

In meinem kleinen Beispiel ist der Publish-Subscribe-Mechanismus genauso wie andere Infrastrukturdienste direkt im Host implementiert. Man könnte ihn aber auch als separaten Dienst/Komponente aufsetzen. Das lässt sich pauschal nicht sagen.
20.11.2008 00:19 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
JuyJuka JuyJuka ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2316.jpg


Dabei seit: 30.11.2005
Beiträge: 2.187
Entwicklungsumgebung: VS2015
Herkunft: Deutschland


JuyJuka ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Rainbird,

Zitat:
Pre-Action/Action/Post-Action

Das ganze nennt sich auch einfach Aspektorientierung (definiert aber noch ein Paar weitere "Action's").

Gruß
Juy Juka
20.11.2008 09:08 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Rainbird Rainbird ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2834.jpg


Dabei seit: 28.05.2005
Beiträge: 3.720
Entwicklungsumgebung: Visual Studio 2012
Herkunft: Mauer


Rainbird ist offline

Aspekte

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von JuyJuka:
Das ganze nennt sich auch einfach Aspektorientierung (definiert aber noch ein Paar weitere "Action's").

Das ist so nicht ganz richtig. Es geht ja nicht darum technische bzw. Infrastruktur-Aspekte von der Geschäftslogik zu trennen, sondern die Geschäftslogik selbst zu strukturieren. Vor allem soll die Geschäftslogik ohne Neukompilierung nachträglich erweitert werden können. Die Erweiterung/Änderung einer Geschäftsprozess-Implementierung ist kein Aspekt. Aspekte wären z.B. Logging, Sicherheit, Transaktionen, etc..

Okay, man kann die Erweiterungsfähigkeit und was an Infrastruktur dazu benötigt wird auch als Aspekt betrachten. Die Pre- und Post-Aktionen könnte man auch sehr elegant mit AOP-Frameworks wie PostSharp technisch umsetzen. Das ist aber nur "Kosmetik". Ich wollte bei .NET Bordmitteln bleiben.

Wie Workflows bzw. sonstige Erweiterungen der Geschäftslogik aktiviert/getriggert werden ist im Detail gar nicht so wichtig. Ich hatte ja Eingangs erwähnt, dass ich nur Eine von Vielen Möglichkeiten vorstelle, wie man sowas machen kann. Mir kommt es auch gar nicht so auf die Konkrete Publish/Subscribe-Implementierung an, sondern darauf, dass Dienste einer Lösung nach bestimmten Regeln miteinander kommunizieren.

Wenn man die "Actions" via Aspekt aufruft, könnte der Code z.B. so aussehen:

C#-Code:
/// <summary>
/// Speichert Produkt-Datensätze innerhlb einer Transaktion.
/// </summary>
/// <param name="products">Produktdatensätze</param>
/// <param name="transaction">Transaktion (Optional)</param>
/// <returns>Tabelle mit gespeicherten Produktdatensätzen</returns>
[PublishAsServiceEvent]
[Transaction(TransactionParameterName="transaction",TransactionRequired=true)]
public ArticleMasterDataSet.ProductsDataTable SaveProducts(ArticleMasterDataSet.ProductsDataTable products, Transaction transaction)
{
    // Ländereinstellungen vom Aufrufer annehmen
    ApplicationServer.AssumeCultureFromSession();

    // Wenn der Aufrufer in der Rolle "Product Writer" ist ...
    if (ApplicationServer.IsInRole("Product Writer"))
    {
        // Aufruf an Geschäftslogik delegieren
        return new ProductManager().SaveProducts(products, Transaction.Current);
    }
    else
        // Ausnahme werfen
        throw new SecurityException(ApplicationServer.LocalizedAccessDeniedMessage);
}

Leute die sich nicht gerne wiederholen und sehr viel Wert auf schlanken Code legen, haben an einer Implementierung im AOP-Stil mit Sicherheit mehr Freude, als an meinem Imperativen Prozeduralen Ansatz. Trotzdem mag ich persönlich mich nicht so recht mit AOP anfreunden.
20.11.2008 16:42 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
_daniel_
myCSharp.de-Mitglied

Dabei seit: 31.05.2006
Beiträge: 227


_daniel_ ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,
der Ansatz sieht interesant aus. Ähnliches habe ich mir auch vorgestellt allerdings ohne die "Konfiguration" über die XML Datei.

Asyncron kann das ganze ja aber nur dann ablaufen wenn die eigentliche Aktion
(

Zitat:
C#-Code:
// Aufruf an Geschäftslogik delegieren
result = new ProductManager().SaveProducts(products, Transaction.Current);

)
nicht von Pre-Events abhängig ist wie z.B. das verhindern der Mandanten Löschung (was ich weiter oben mal als Beispiel erwähnte)

Oder wie meinst du das mit dem Bus-System bzw asyncronen?
22.11.2008 16:36 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Rainbird Rainbird ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2834.jpg


Dabei seit: 28.05.2005
Beiträge: 3.720
Entwicklungsumgebung: Visual Studio 2012
Herkunft: Mauer


Rainbird ist offline

Erweiterbarkeit ohne Abhängigkeit

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von _daniel_:
Ähnliches habe ich mir auch vorgestellt allerdings ohne die "Konfiguration" über die XML Datei.

Wie sollte es aber ohne einen Microkernel mit Konfiguration funktionieren? Die Anwendung soll ja erweiterbar sein, ohne neu kompilieren zu müssen.

Zitat von _daniel_:
Asyncron kann das ganze ja aber nur dann ablaufen wenn die eigentliche Aktion
...
nicht von Pre-Events abhängig ist wie z.B. das verhindern der Mandanten Löschung

Die eigentliche Aktion weiss nichts von irgendwelchen Pre- oder Post-Aktionen. Sie ist auch nicht abhängig von diesen. Trotzdem kann eine Pre- oder Post-Aktion dafür sorgen, dass die Mandantenlöschung abgebrochen wird, wenn noch Aufträge vorhanden sind.
Wenn Du Dir nochmal meinen Beispiel-Code weiter oben anschaust (den ohne Aspektorientierung), wird Dir auffallen, dass Pre-Aktionen, die eigentliche Aktion und auch die Post-Aktionen alle innerhalb des selben TransactionScopes ausgeführt werden. Eine Pre- oder Post-Aktion muss deshalb nur eine Ausnahme werfen, um die Mandantenlöschung zu verhindern. Wenn innerhalb eines TransactionScopes eine Ausnahme geworfen wird, führt das automatisch zu einem Rollback der Umbegungstransaktion. Natürlich wird damit auch das ggf. schon abgesetzte "DELETE FROM Mandators WHERE [email protected]" Statement rückgängig gemacht.
Es würde sogar gehen, wenn man keine Datenbank, sondern z.B. nur eine CSV-Datei hätte. Man müsste dann eben einen kompensierenden Ressourcen-Manager schreiben, der Transaktionsverhalten für CSV-Dateien implementiert.

Zitat von _daniel_:
Oder wie meinst du das mit dem Bus-System bzw asyncronen?

Wenn man die Abgängigkeiten zwischen Diensten und auch ggf. zwischen ganzen Anwendungen (Stichwort EAI) komplett eliminieren möchte, sollte man über den Einsatz eines Enterprise Service Bus nachdenken. Das Prinzip dabei ist einfach: Statt dass alle Dienste und Anwendungen direkt miteinander reden, reden sie mit einer zentralen Infrastruktur, dem Bus. Damit sit kein Dienst mehr vom anderen abhängig, sondern alle sind nur noch vom Bus abhängig. Folgende Skizze zeigt, wie ein Enterprise Service Bus gedacht ist:  http://www.tecchannel.de/_misc/img/detai...296967492666493

Allerdings ist es alles andere als trivial, so eine Bus-Infrastruktur zu schreiben. Deshalb lohnt sich ein Blick auf fertige Produkte. Im Microsoft-Umfeld wäre das der Microsoft BizTalk Server. Der BizTalk Server funktioniert folgendermaßen:  MSDN: The BizTalk Server 2006 Messaging Engine

Solche fertigen Infrastruktur-Produkte für SOA sind allerdings nicht billig. Die Einsteiger-Version des BizTalk Servers liegt bei ca. 8000 EUR. Mit Produkten anderer Hersteller sieht es ähnlich aus. Die Frage ist, ob man es für die Lohnkosten von 8000 EUR selber so hinbekommt, einen Enterprise Service Bus zu implementieren.
27.11.2008 08:23 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Omit Omit ist männlich
myCSharp.de-Mitglied

images/avatars/avatar-2748.jpg


Dabei seit: 20.10.2008
Beiträge: 143


Omit ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

@Rainbird: Kennst du Berichte über die Verbreitung solcher Servicebusse? Wenn man einen Software entwickelt, die man an die Frau/Mann(Firma) bringen will, kann man ja nur schlecht sagen: "Ja bevor Sie die Software einsetzten können, müssen Sie sich erstmal einen Service Bus für 10-30t € kaufen".
Sind die ESB alle so standardisiert, dass man nicht für jeden ESB, eine eigene "Anbindung" schreiben muss?

Zitat von Rainbird:
Solche fertigen Infrastruktur-Produkte für SOA sind allerdings nicht billig. Die Einsteiger-Version des BizTalk Servers liegt bei ca. 8000 EUR. Mit Produkten anderer Hersteller sieht es ähnlich aus. Die Frage ist, ob man es für die Lohnkosten von 8000 EUR selber so hinbekommt, einen Enterprise Service Bus zu implementieren.

Wenn den so hinbekommen würdest, dürften die Lohnkosten auch "etwas" höher sein! *g

Gruß Timo

p.S. Ich stehe jetzt nicht unmittelbar davor eine Software zu entwickeln, die einen ESB einsetzt. Ich frage nur auch gerne mal prophylaktisch.
27.11.2008 10:19 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
FZelle
myCSharp.de-Poweruser/ Experte

Dabei seit: 23.04.2004
Beiträge: 9.712


FZelle ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Witzige Vorstellung, das die verscheidenen ESB zueinander Kompatible sein sollten.

Natürlich sind sie es nicht.
Du musst dich für einen entscheiden, oder sehr viel Zeit investieren um
eine generische anbindung zu schaffen.
27.11.2008 12:54 Beiträge des Benutzers | zu Buddylist hinzufügen
Seiten (2): [1] 2 nächste » Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 8 Jahre.
Der letzte Beitrag ist älter als 8 Jahre.
Antwort erstellen


© Copyright 2003-2017 myCSharp.de-Team. Alle Rechte vorbehalten. 22.09.2017 17:19