User Tools

Site Tools


technology:domainmodel:domainservice

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

technology:domainmodel:domainservice [2013/01/27 22:30]
rtavassoli
technology:domainmodel:domainservice [2013/01/28 12:11] (current)
rtavassoli
Line 64: Line 64:
 Das Problem ist, dass der Status des Zeitdatensatzes geprüft werden muss. Wenn er nicht editierbar ist, sollte der Zeitdatensatz im Kalender auch nicht verschoben werden können. Das Read Model des Zeitdatensatzes zu prüfen reicht auch nicht aus, weil das keine Sicherheit bringt. Angenommen ein Zeitdatensatz ist editierbar und läuft von 08:00-10:00. User 1 setzt ihn auf nicht editierbar, User 2 ändert die Zeit auf 09:00-11:00. Das betrifft zwei unterschiedliche Aggregates, im ersten Fall die ServiceAction, im Zweiten den EmployeeCalendar. Ohne Domain Service würde beide Aktionen erfolgreich durch laufen. Das ist nicht was User 1 wollte((er wollte den Zeitdatensatz von 08:00-10:00 sperren)), und auch nicht was User 2 wollte((er hat jetzt einen gesperrten Zeitdatensatz von 09:00-11:00, kann ihn nicht weiter verarbeiten, und hat ihn nicht gesperrt)). Das Problem ist, dass der Status des Zeitdatensatzes geprüft werden muss. Wenn er nicht editierbar ist, sollte der Zeitdatensatz im Kalender auch nicht verschoben werden können. Das Read Model des Zeitdatensatzes zu prüfen reicht auch nicht aus, weil das keine Sicherheit bringt. Angenommen ein Zeitdatensatz ist editierbar und läuft von 08:00-10:00. User 1 setzt ihn auf nicht editierbar, User 2 ändert die Zeit auf 09:00-11:00. Das betrifft zwei unterschiedliche Aggregates, im ersten Fall die ServiceAction, im Zweiten den EmployeeCalendar. Ohne Domain Service würde beide Aktionen erfolgreich durch laufen. Das ist nicht was User 1 wollte((er wollte den Zeitdatensatz von 08:00-10:00 sperren)), und auch nicht was User 2 wollte((er hat jetzt einen gesperrten Zeitdatensatz von 09:00-11:00, kann ihn nicht weiter verarbeiten, und hat ihn nicht gesperrt)).
 \\ \\ \\ \\
-Alle Aktionen den Terminkalender des Mitarbeiters betreffend((Hinzufügen, Verschieben, Löschen)) müssen also parallel den Zeitdatensatz betreffen. Im Grunde müssen alle Aktionen den Zeitdatensatz durchlaufen, und der Terminkalender sollte //intern// vom Zeitdatensatz verwendet werden - und zwar nur bei Bedarf. Der Client würde in dem Fall lediglich den Zeitdatensatz anfassen, und das Programmiermodell des Clients wäre wesentlich einfacher. Der Zeitdatensatz könnte wie folgt aussehen +Alle Aktionen den Terminkalender des Mitarbeiters betreffend((Hinzufügen, Verschieben, Löschen)) müssen also parallel den Zeitdatensatz betreffen. Im Grunde müssen alle Aktionen den Zeitdatensatz durchlaufen, und der Terminkalender sollte //intern// vom Zeitdatensatz verwendet werden - und zwar nur bei Bedarf.
----- +
-To-Do: Das Ganze über einen [[technology:domainmodel:secondaryindex|Secondary Index]] umsetzen. +
----- +
-<code csharp> +
-public class ServiceAction: AggregateRoot +
-+
-  private IRepository<EmployeeCalendar> EmployeeCalendarRepository; +
-   +
-  public ServiceAction(Guid id, Guid employeeId, DateTime start, DateTime end, IRepository<EmployeeCalendar> repo) // Constructor for adding new ServiceAction +
-  { +
-    // prüfungen - vor dem hinzufügen zum kalender, ist effizienter wenn hier was schief läuft. +
-    EmployeeCalendarRepository = repo; +
-    var calendar = repo.GetOrCreate(employeeId); +
-    calendar.Schedule(id, start, end); +
-    ApplyChange(ServiceActionAdded(id)); +
-    ApplyChanges(calendar); // die Domain Events, die durch calendar.Schedule(id, start, end) erzeugt werden, werden hier erst mal vorgehalten. Diese Methode müsste noch rein ins generische Aggregate. +
-  } +
-+
-</code> +
-Der Client müsste dann nur den Zeitdatensatz erstellen((oder umterminieren, dass würde intern ähnlich ablaufen)) und über das Repository<ServiceAction> speichern. Das Repository für den Zeitdatensatz würde die Domain Events, die es aus der ServiceAction erhält, einach alle speichern, ganz egal ob es Ereignisse des Zeitdatensatzes oder des Terminkalenders sind((die Ereignisse teilen sich den Event Store)). Der Code für die Neuanlage eines Zeitdatensatzes sieht dann so aus: +
-<code csharp> +
-  public void Handle(AddServiceAction command) +
-  { +
-    var action_repo = new Repository<ServiceAction>(); +
-    var action = new ServiceAction.Create(command.ID, command.EmployeeId, command.Start, command.End); // Die Zeiten haben hier nichts zu suchen - oder doch? Für Prüfungen? +
-    action_repo.Save(action); +
-  } +
-</code> +
-Das ist wesentlich einfacher als vorher. Nur handelt es sich hier nicht mehr um einen Domain Service, sondern um ??? Keine Ahnung ob es dieses Muster bereits gibt. Ich halte es aber für sehr sauber. Und dass zwei Ereignisse erzeugt werden, einmal ServiceActionAdded { ID = ID } und dann ServiceActionScheduled { ID = ID, EmployeeID = EmployeeID, Start = Start, End = End }, halte ich nicht für allzu kritisch. Die Event Handler müssen darauf vorbereitet sein, auch darauf, dass sie nicht in dieser Reihenfolge kommen müssen. Die Zeitangaben im ServiceActionAdded Ereignis zu duplizieren wäre denkbar, halte ich aber für viel kritischer, denn dann haben wir dieselbe Information zweimal - welche ist nun die richtige?+
 \\ \\ \\ \\
-Jetzt würde auch eine Umterminierung durch den Zeitdatensatz laufen müssen. Das ist so gewollt, denn der Zeitdatensatz kann eigene Prüfungen ausführenbevor er calendar.Reschedule() aufruft. Der Zeitdatensatz müsste beim Umterminieren aber ebenfalls Ereignisse auslösendamit die Änderung durch ihn gesichert ist. +Dieser Fall sieht also nicht so ausals wäre ein Domain Service dafür am geeignetstenDann doch lieber eine Saga, die die gemeinsamen Änderungen am Zeitdatensatz und am Terminkalender mit dem Reservation Pattern vornimmt. Wenn man aber davon ausgehen kann, dass die Zeitdatensätze und der Terminkalender des Mitarbeiters //nicht partitioniert werden//, ist das meiner Meinung nach ein eindeutiger Fall für einen [[technology:domainmodel:secondaryindex|Sekundärindex]].
-\\ \\ +
-Wenn ich darüber nachdenke, bin ich zu der Überzeugung gekommen, dass die Zeitangaben in den Ereignissen des Zeitdatensatzes enthalten sein sollen! +
technology/domainmodel/domainservice.1359322255.txt.gz · Last modified: 2013/01/27 22:30 by rtavassoli