Iniziamo con una breve discussione su cosa sia Domain Service
e perché dovresti usarne uno. Perché esiterei, dopo un'ispezione iniziale, a chiamare il tuo esempio a Domain Service
.
Domain Services
viene spesso utilizzato per risolvere due problemi: quando si desidera estrarre una sorta di calcolo o altro processo privo di effetti collaterali in un proprio oggetto da utilizzare / riutilizzare da molti pezzi del proprio dominio, o quando esiste una logica di business sul comportamento di un processo che naturalmente si estende su più Entities
. Il primo ha molte manifestazioni ovvie, ma l'esempio per eccellenza di quest'ultimo è per il coordinamento delle transazioni che avvengono tra Entities
. Cioè, l'esecuzione del processo di business richiede l'esecuzione di comandi a più di un Entity
.
Supponiamo che tu abbia un Atm
e un CheckingAccount
. Ritirare denaro da Atm
richiede la conoscenza che CheckingAccount
ha fondi sufficienti per completare la transazione. Poiché Atm.WithdrawCurrency( decimal amount )
è completamente separato da CheckingAccount.Debit( decimal amount )
, ma entrambi devono essere coordinati per completare la transazione, un Domain Service
è una soluzione apt. In questo caso, il AtmService
terrà la conoscenza riguardo al fatto se distribuiremo denaro o meno.
A parte le considerazioni precedenti, Domain Services
servirà solo a rendere il tuo modello più anemico. Può essere incredibilmente allettante abbattere tutto il comportamento del tuo sistema in "servizi" discreti che semplicemente agiscono sul tuo modello, ma questa è l'antitesi del DDD e fa solo male a lungo andare.
Osservando il tuo esempio, contiene la logica di business (arriveremo a quel Event
in un momento)? Non proprio. I tuoi metodi sembrano semplicemente coordinarsi tra il tuo Entities
e il mondo esterno. Non ci sono davvero decisioni prese. Questo è più simile a Application Service
(recupera pezzo di modello - > comando di esecuzione - > save).
Per quanto riguarda Event
, eviterei di aumentare Events
da Application Service
. Se, per qualche motivo, ti occorre una registrazione Event
quando AdministrationAccount
è "aperto", prova a renderlo più esplicito:
// AdministrationAccount
public void Open()
{
this.state = this.state.Open(this);
}
quindi nel suo stato:
// ClosedAdministractionAccountState
public IAdministrationAccountState Open( AdministrationAccount account )
{
DomainEvents.RaiseAsync(new AccountRecordOpenedEvent(this));
return new OpenedAdministrationAccountState(account);
}
L'esempio precedente utilizza un FSM, ma qui potrei concepire altre opzioni. L'importante è che la logica e Event
siano esattamente all'interno del tuo dominio a cui appartengono. Non fluttuare in qualche metodo di Service
in cui saranno inevitabilmente ignorati.
Come per il tuo altro metodo RegisterNewAccount
. È davvero il posto giusto per creare l'account? Quando parli di un nuovo account che viene aperto in ufficio, dici "Il AdministrationAccountService
ha registrato un nuovo account con username
e displayName
"? Oppure dici "Un AdminUser
ha registrato un nuovo account"? Quello che sto ottenendo qui è che il metodo potrebbe facilmente essere refactored per far parte di ciò che è sempre in possesso di username
e displayName
prima della registrazione. Per esempio. %codice%. Gli account (e le loro informazioni) non vengono fuori dal nulla. Puoi controllare questo link per un po 'di più: link
Refactoring verso i precedenti aiuta a purificare e distillare il tuo servizio applicativo.
Per quanto riguarda se una AdminUser.Register()
può anche essere una fabbrica? Direi, in generale, no. È concepibile? Certo, ma starai meglio a rifocalizzare il tuo modello verso una visione più profonda in modo che non sia necessario. Questo tipo di domanda è quasi sempre un segno di un modello carente. Non alcuni dettagli tecnici mancanti.