2016-07-12 7 views
0

Ich habe eine Rechnung aggregiert Wurzel, die zu einem bestimmten Zeitpunkt an die Buchhaltung externen Web-Service gesendet werden kann, und markieren Sie als gesendet durch persistent einige ID/Nummer von diesem Service erhalten.DDD-Domain-Dienste

Welches ist der richtige Weg, um es in DDD zu tun?

Hier sind meine Ideen:

Erste apprroach:

haben eine Rechnung AggregateRoot mit Funktion SendToAccounting und Domain Service/Schnittstelle injizieren, die Rechnung an das Rechnungswesen senden wird, und rufen einige „id/Code“in der Buchhaltungssoftware und stellen AccountingSoftwareId Eigenschaft

Invoice.SendToAccounting(IInvoiceDomain service) 
{ 
    var accountingSoftwareID = service.getAccountingSoftwareId(this); 
    this.AccountingSoftwareId = accountingSoftwareId; 
} 

///Implementation in the application service 
    var invoice = _invoiceRepository.GetInvoiceById(id); 
    invoice.SendToAccounting(someDomainService); 
    _invoiceRepository.Update(invoice); 
    _unitOfWork.Save(); 

Zweiter Ansatz:

Ähnlich wie erste Ansatz, aber Domain Service sollte für persistierende wie diese verantwortlich:

var invoice = _invoiceRepository.GetInvoiceById(id); 
///unit of work save will be called inside this function 
invoice.SendToAccounting(someDomainService); 

Dritte approcach:

Domain Service wird vollständig rensponsible dieses Verhalten

///Code inside domain service 
public void SendInvoiceToAccounting(int invoiceId) 
{ 
    var invoice = _invoiceRepository.GetInvoiceById(invoiceId); 
    string invoiceAccountingId = _accountingService.GetAccountingSoftwareId(invoice); 
    invoice.SetAsSentToAccounting(invoiceAccountingId); 
    _invoiceRepository.Update(invoice); 
    _unitOfWork.Save(); 
} 
einzukapseln
+0

Ich bin nicht klar, was der Prozess des Sendens an Buchhaltung umfasst - was ist das? – tomliversidge

+0

Wie behandeln Sie Fehler beim Aufruf des externen Dienstes? – tomliversidge

+0

Wie wird die accountingId im Rechnungsaggregat verwendet? – tomliversidge

Antwort

1

Welches ist der richtige Weg, um es in DDD zu tun?

Ihre erste Annäherung ist am nächsten. Die Signatur in Ihrem Domain-Service sollte den Status als Argumente und nicht den gesamten Stamm selbst akzeptieren.

Invoice.SendToAccounting(IInvoiceDomain service) 
{ 
    var accountingSoftwareID = service.getAccountingSoftwareId(this.Id, ...); 
    this.AccountingSoftwareId = accountingSoftwareId; 
} 

Alle Argumente sollen Werttypen übergeben werden - die Domain Service sollte durch die Manipulation seiner Kopie der Argumente nicht in der Lage sein, den Zustand des Aggregats zu ändern, und es sollte auf jeden Fall nicht in der Lage sein zu laufen andere Befehle auf dem Aggregat.

In einer Code-Überprüfung würde ich den zweiten Ansatz, den Sie anbieten, ablehnen; Aus der Sicht des Domänenmodells sollte die Domänen-Service-Schnittstelle nur Abfragen, keine Befehle (im Sinne von CQS) bereitstellen.

In einer Code-Überprüfung würde ich den dritten Ansatz vollständig ablehnen - Setter auf Aggregaten sind ein Code-Geruch; Der springende Punkt ist, den Zustand mit den Regeln für die Aktualisierung zu kapseln.

ABER

Das Design ist etwas beunruhigend, dass Sie schreibt an zwei verschiedenen Orten in der gleichen Transaktion machen. Auf dem glücklichen Weg ist es keine große Sache, aber was sollen Sie tun, wenn der Befehl auf dem Buchhaltungsdienst erfolgreich ausgeführt wird, aber das Speichern der aktualisierten Rechnung fehlschlägt?

Angenommen, dass verteilte Transaktionen nicht ansprechend sind, können Sie überprüfen, was Udi Dahan über reliable messaging zu sagen hat.

0

Mein erster Gedanke war 'Rechnungsstellung Teil der Buchhaltung nicht?' :)

Option 1 ist, was ich in der Vergangenheit tendenziell verwendet habe, wo meine Domain-Objekte Verhalten haben.

Ich mag nicht Option 2 als dann Rechnung benötigt einen privaten Verweis auf das Repository.

Eine allgemeinere Beobachtung ist, dass hier scheint nicht viel Verhalten in der Domäne zu sein - es scheint nur eine ID zu setzen. Option 3 scheint dies zu erfassen. Ich frage mich, ob ein Application Service ausreichen würde und koordinieren, nur folgendes

  1. laden die Rechnung
  2. Holen Sie sich einen AccountingId
  3. speichern sie auf der Rechnung

die so ziemlich Option 3 über. Ich würde versucht sein, das Repository und den Service zu übergeben, aber das ist wirklich nur ein funktionaler Stil - das oben Gesagte würde auch mit privaten Feldern funktionieren.

0

Die Buchhaltung BC sollte immer die gleiche accountingSoftwareId für eine bestimmte Rechnungs-ID zurückgeben.

Wenn in der ersten Runde der Aufruf auf dem BC durchgeführt wird, aber die Rechnungsaktualisierung fehlschlägt, haben Sie einen Status t1 im Konto BC und einen Status t0 im Fakturierungs-BC. Wenn Sie den Befehl wiederholen, führt er den gleichen Aufruf aus und gibt dieselbe ID zurück. Wenn die Aktualisierung erfolgreich ist, befinden Sie sich in jedem BC im Status t1. Im schlimmsten Fall, selbst wenn der Befehl manuell aufgelöst werden muss, wäre die resultierende Konto-ID immer dieselbe für eine gegebene Rechnungs-ID.

Um eine Buchhaltungs-ID für eine bestimmte Rechnung aufzulösen, können Sie die Buchhaltung BC direkt fragen.