2016-07-18 4 views
0

Ich habe zwei ältere Enterprise-Anwendung, die ein paar ähnliche Funktionen haben. Ich muss ein System erstellen, das auf Datenänderungsereignisse von diesen Systemen reagiert, diese Daten verarbeitet und die kombinierten Ergebnisse über eine API in mehreren Formaten verfügbar macht. Ich würde gerne eine Event Source/DDD-Architektur verwenden, aber ich bin mir nicht sicher, ob das Sinn macht. Wie könnte ich das System nach dem untenstehenden vereinfachten Modell gestalten?Ereignisquelle, Anti-Corruption Layer-Design mit NEventStore

Hinweis - Die folgenden wurde bearbeitet, die Frage zu klären:

Beide Systeme haben Produkte, die unterschiedliche Preise basieren auf dem Datum enthalten. Wenn sich der Preis ändert, kann jedes System ein Ereignis ausgeben, PriceChanged, das die Kennung des Altsystems, den Primärschlüssel dieses Systems, ein Datum und den neuen Preis enthält. Die Produkt-ID ist einzigartig für das System, aber möglicherweise nicht eindeutig zwischen beiden Systemen, sodass auch eine System-ID enthalten ist.

PriceUpdated { 
     int systemId, 
     int productId, 
     Date date, 
     Float amount 
    } 

Im begrenzten Rahmen meines neuen Systems würde einen Dienst sein, der dieses Ereignis empfängt und müssen mein Aggregat von systemId, productId und Datum suchen und dann einen Befehl aussenden den entsprechenden Preis in der aktualisieren Aggregat. Mein Aggregat würde definiert werden als:

class ProductPriceAggregate 
{ 
    Guid Id, 
    int systemId, 
    int productId, 
    Date date, 
    Float amount 

    Apply(CreateProductPriceCommand e){ 
    Id = e.Id; 
    systemId = e.systemId; 
    productId = e.productId; 
    date = e.date; 
    RaiseEvent(new ProductPriceCreatedEvent(this)) 
    } 

    Apply(UpdateProductPriceCommand d){ 
    amount = e.amount; 
    RaiseEvent(new ProductPriceUpdatedEvent(this)); 
    } 
} 

Wenn ich NEventStore verwende die Ströme mit einer GUID speichert, dann wird jeder aggreateId durch eine GUID dargestellt werden. Mein Dienst müsste nach der GUID fragen, indem er systemId, productId und date verwendet, um einen Befehl mit der richtigen ID auszugeben.

Der Service könnte wie folgt aussehen:

class PriceUpdateService : ISubscribeTo<PriceUpdated>{ 
    Handle<PriceUpdated>(PriceUpdated e) 
    { 
    var aggregateId = RetrieveId(e.systemId, e.productId, e.date); 
     if (aggregateId == null) 
     Raise(new CreateProductPriceCommand(e)) 
     else 
     Raise(new UpdateProductPriceCommand(aggregateId, e.amount); 
    } 

    RetrieveId(int systemId, int productId, DateTime date) 
    { 
     // ??? 
    } 
} 

Die Frage ist, was der beste Weg, um die Summe der ID zu sehen ist? Die Legacy-Systeme, die das PriceUpdated-Ereignis ausgeben, haben keine Kenntnis von diesem neuen System. Kann ich ein Lesemodell verwenden, das als Antwort auf ProductPriceCreatedEvent aktualisiert wird und genügend Informationen zum Abfragen der ID enthält? Benötige ich ein anderes Aggregat, das ProductPrices indexieren soll? Wie von VoiceOfUnreason als Antwort gepostet, könnte ich eine wiederholbare Konvention verwenden, um die ID mit systemId, productId und date zu generieren. Ist dies die empfohlene Option aus DDD-Sicht?

+0

"Würde ich dann haben" - meinst du ich hätte * stattdessen *?Denn es gibt einen klaren Unterschied zwischen dem sofortigen Auslösen eines Ereignisses und dem Ausgeben eines Befehls. Der Wortlaut macht es unklar, ob Sie sich dessen bewusst sind. – guillaume31

+0

Mögliches Duplikat von [Event Sourcing Befehl oder Ereignis von externem System?] (Http://stackoverflow.com/questions/11888028/event-sourcing-command-or-event-from-external-system) – guillaume31

+0

Danke für den Kommentar guillaume31 Ich habe den Beitrag aktualisiert, um meine Frage zu klären. Mein Hauptanliegen ist, wie die Aggregat-ID abgerufen wird, damit mein Dienst, der die Ereignisse von den externen Systemen behandelt, wiederum Befehle an das richtige Aggregat ausgeben kann. – Jeremy

Antwort

2

Steuern Sie Ihre eigenen IDs?

Eine Alternative zum Versuch, eine aggregateId zu suchen, ist zu berechnen, was diese aggregateId sein muss. Die Grundidee besteht darin, dass die verschiedenen Punkte, die ein Aggregat aus diesem Ereignis finden müssen, eine Instanz eines Domänen-Service teilen, der die Berechnung einkapselt.

Die Signatur sieht aus wie die Abfrage, die Sie in Ihrer Frage schrieb

// Just a query, we aren't changing state anywhere. 
var aggregateId = idGenerator.getId(e.systemId, e.productId, e.date); 

Jede gegebene Implementierung nimmt seine eigene Salz, die Argumente, die Sie an es übergeben, und erzeugt einen Hash, der die gemeinsame ID überall verwendet wird, ist zur Karte Diese Kombination von Argumenten zu einem Aggregat.

Sie können natürlich Identifikatoren für verschiedene Aggregate mit denselben Ereignisdaten erzeugen, indem Sie einen idGenerator mit einem anderen Salz übergeben.

Für den speziellen Fall, in dem Ihre IDs UUID sind, können Sie Name-Based UUID verwenden.

Verwandte Themen