2010-04-16 2 views
5

Ho una domanda su DDD. Sto costruendo un'applicazione per imparare DDD e ho una domanda sulla stratificazione. Ho un'applicazione che funziona in questo modo:Definizione dei livelli dell'applicazione in Domain-Driven-Design

chiamate strato UI => Application Layer -> Dominio Livello -> Database

Ecco un piccolo esempio di come il codice sembra:

//****************UI LAYER************************ 
//Uses Ioc to get the service from the factory. 
//This factory would be in the MyApp.Infrastructure.dll 
IImplementationFactory factory = new ImplementationFactory(); 

//Interface and implementation for Shopping Cart service would be in MyApp.ApplicationLayer.dll 
    IShoppingCartService service = factory.GetImplementationFactory<IShoppingCartService>(); 

    //This is the UI layer, 
    //Calling into Application Layer 
    //to get the shopping cart for a user. 

    //Interface for IShoppingCart would be in MyApp.ApplicationLayer.dll 
    //and implementation for IShoppingCart would be in MyApp.Model. 
    IShoppingCart shoppingCart = service.GetShoppingCartByUserName(userName); 

    //Show shopping cart information. 
    //For example, items bought, price, taxes..etc 
    ... 

    //Pressed Purchase button, so even for when 
    //button is pressed. 
    //Uses Ioc to get the service from the factory again. 
    IImplementationFactory factory = new ImplementationFactory(); 
    IShoppingCartService service = factory.GetImplementationFactory<IShoppingCartService>(); 
    service.Purchase(shoppingCart); 


    //**********************Application Layer********************** 
    public class ShoppingCartService : IShoppingCartService 
    { 
     public IShoppingCart GetShoppingCartByUserName(string userName) 
     { 
      //Uses Ioc to get the service from the factory. 
      //This factory would be in the MyApp.Infrastructure.dll 
      IImplementationFactory factory = new ImplementationFactory(); 

      //Interface for repository would be in MyApp.Infrastructure.dll 
      //but implementation would by in MyApp.Model.dll 
      IShoppingCartRepository repository = factory.GetImplementationFactory<IShoppingCartRepository>(); 

      IShoppingCart shoppingCart = repository.GetShoppingCartByUserName(username); 
      //Do shopping cart logic like calculating taxes and stuff 
      //I would put these in services but not sure? 
      ... 

      return shoppingCart; 
     } 

     public void Purchase(IShoppingCart shoppingCart) 
     { 
      //Do Purchase logic and calling out to repository 
      ... 
     } 
    } 

Mi sembra di mettere la maggior parte delle mie regole di business nei servizi piuttosto che nei modelli e non sono sicuro che sia corretto? Inoltre, non sono completamente sicuro se la posa è corretta? Ho i pezzi giusti nel posto giusto? Inoltre i miei modelli dovrebbero lasciare il mio modello di dominio? In generale, sto facendo questo corretto secondo DDD?

Grazie!

+0

sembra buono per me !!! –

risposta

2

DDD funziona meglio quando i servizi (livello applicazione) espongono solo i comandi sugli oggetti dominio, non sugli oggetti stessi.

In te esempio vorrei creare un metodo di servizio come acquisto (strng productName, quantità int), che internamente sarebbe ottenere uno ShoppingCart da repository (non c'è bisogno di usare l'interfaccia qui) ottenere un prodotto (dal suo nome) dal deposito e chiamare il carrello.AddProdotto (prodotto, quantità)

no, la logica aziendale dell'aggiunta di prodotti al carrello, il calcolo della quantità totale, del peso totale o di altri elementi aziendali è incapsulata nella modalità.

+0

Grazie per la risposta. Quindi i servizi dovrebbero essere statici e vivere nel livello applicazione? Ho immaginato che i servizi dovessero implementare un'interfaccia perché rende più facile testare. Inoltre, chi è responsabile della chiamata alla logica di business come calcolare l'importo totale? Il repository lo fa? –

+1

Se si chiama AddProduct su un carrello, questo carrello è responsabile del mantenimento della propria coerenza, quindi dovrebbe aggiornare tutte le informazioni che devono essere aggiornate (come l'importo totale). Sì, è bene implementare l'interfaccia nei servizi, ma dal momento che DDD dice che non si deve collocare la logica di business nei servizi, sono dei candidati poveri per i test. Ma le interfacce sono utili quando si esegue la programmazione orientata all'aspetto. Ho usato per intercettare l'invocazione sui miei servizi e, in un consiglio di AOP, iniziare/commettere la transazione sul database, registrare qualsiasi eccezione e così via. –

3

Quando si chiede

caso i miei modelli lasciare il mio modello di dominio?

Direi che, se possibile, dovresti lavorare per evitare di mescolare i dati avanti e indietro tra diversi gruppi di oggetti in un programma. Ciò comporterebbe un sacco di noia scrivendo un sacco di codice noioso e soggetto a errori, si avrà un insieme ridondante di oggetti DTO che devono rispecchiare gli oggetti del dominio, inoltre si ottiene un minor chilometraggio dai metodi scrivere perché funzionano solo su DTO o oggetti di dominio. Tutto sommato è molto doloroso e non realizza molto. Cerco di avere un set di oggetti di dominio che viene passato in giro per tutta l'applicazione.

(Ciò non significa che non vi siano casi in cui si abbia realmente bisogno di spostare i dati tra diversi gruppi di oggetti, come quando si costruisce un livello di anticorruzione. Basta non andare in cerca di guai se non lo è assolutamente necessario.)

per quanto riguarda

IShoppingCart shoppingCart = repository.GetShoppingCartByUserName(username); 
//Do shopping cart logic like calculating taxes and stuff 
//I would put these in services but not sure? 

uno degli obiettivi di Domain-Driven design è cercare di logica di business separata dal codice di infrastruttura. Qualunque cosa tu possa capire come calcolare usando solo gli oggetti del dominio è meglio andare nel modello del dominio, dove puoi scrivere test che non implicano il database. Vorrei che il servizio estraesse un aggregato di oggetti di dominio, quindi eseguissero i calcoli della logica aziendale negli oggetti del dominio, quindi il servizio salvi le modifiche di stato apportate ai calcoli negli oggetti del dominio.

1

Si dovrebbe avere uno strato sottile tra oggetti dominio e servizi da manipolare con oggetti di dominio (consigliato da Eric Evans). Questo nome di oggetto termina di solito su "Manager". Ad esempio, PurchaseManager o simile. Tutta la logica che connette diversi oggetti di dominio (utente, acquisto, indirizzo ...) è in questo oggetto.

  • Servizio chiamata Manager.GetSomething()
  • Direttore ottenere i dati provenienti da diversi repository, fare logica di business e risultato
  • Manger Return risultato restituito, ma non tornare mai oggetti di dominio in sé! Se si dispone di un oggetto dominio chiamato User, è necessario attenersi alla convenzione sui nomi che si inventa e associare User a UserDataContract o simile. Non esporre oggetti di dominio. È un lavoro extra ma non dovresti accoppiare il tuo modello di dominio con l'interfaccia utente.
  • Molte volte oggetto di dominio dispone di metodi per fare un po 'la logica di business
+2

Potresti essere preciso su dove è arrivata la raccomandazione di Eric Evans di cui fai riferimento? Non ricordo nulla del genere nel suo libro (forse mi sono perso qualcosa, ovviamente). –

+0

L'ho trovato come riferimento in uno dei miei documenti (non ho ancora prenotato con me in questo momento): Ci sono operazioni di dominio importanti che non riescono a trovare una casa naturale in un oggetto Entità o Valore. Poiché il nostro paradigma di modellazione è costituito da oggetti, dovremmo cercare di adattarli agli oggetti. A volte forziamo queste operazioni in un oggetto appropriato, scivolando gradualmente verso la programmazione procedurale. Finiamo con oggetti che sollevano nomi che terminano con "Manager". Non hanno uno stato proprio né alcun significato nel dominio oltre l'operazione che ospitano. –

+2

se non sbaglio, Evans sta descrivendo un * anti-pattern * in quella sezione, non lo consiglia. Riconosce che ci sono * occasionalmente * operazioni che non si adattano agli oggetti del dominio, nel qual caso è appropriato mettere tali operazioni in un servizio - ma raccomanda vivamente di cercare di evitarlo e di sforzarci di inserire la logica nel nostro modello di dominio. –

0

quanto riguarda la tua domanda:

"Ho sembra di mettere la maggior parte delle mie regole di business nel settore dei servizi, piuttosto che dei modelli e Non sono sicuro che sia corretto? "

Se una regola aziendale non accede ad altre risorse (database, servizi, oggetti dominio), è possibile avere la regola nell'oggetto dominio stesso. Se accede ad altre risorse, dovresti inserirle nei servizi di dominio.