Domanda

Sto cercando qualche consiglio su quanto dovrei preoccuparmi intorno evitando il modello di dominio anemico. Stiamo solo iniziando a DDD e sono alle prese con l'analisi paralisi per quanto riguarda le decisioni di progettazione semplici. L'ultimo punto ci atteniamo a cui è certa logica di business appartiene, per esempio abbiamo un oggetto Order, che ha proprietà come Status ecc Ora dire che ho per eseguire un comando come UndoLastStatus perché qualcuno ha fatto un errore con un ordine, questo è non così semplice come cambiando il Status altre informazioni deve essere registrato e proprietà modificate. Ora nel mondo reale questo è un compito pura amministrazione. Così il mio modo di vedere ho due opzioni mi viene in mente:

  • Opzione 1: Aggiungere il metodo di ordine in modo qualcosa come Order.UndoLastStatus(), mentre questo genere di senso, non riflette davvero il dominio. Anche Order è l'oggetto primario nel sistema e se tutto che coinvolge l'ordine viene inserito nelle cose di classe ordine potrebbe sfuggire di mano.

  • Opzione 2: Creare un oggetto Shop, e con che hanno diversi servizi che rappresentano ruoli differant. Così potrei avere Shop.AdminService, Shop.DispatchService e Shop.InventoryService. Quindi in questo caso avrei Shop.AdminService.UndoLastStatus(Order).

Ora la seconda opzione che abbiamo qualcosa che riflette il dominio molto di più, e permetterebbe agli sviluppatori di parlare con esperti di business sui ruoli simili che esiste realmente. Ma la sua voce anche verso un modello anemico. Quale sarebbe il modo migliore per andare in generale?

È stato utile?

Soluzione

L'opzione 2 porterebbe a codice procedurale di sicuro.
Potrebbe essere più facile da sviluppare, ma molto più difficile da mantenere.

Ora, nel mondo reale, questo è un compito pura amministrazione

compiti "amministrazione" dovrebbe essere privata e invocato attraverso pubblico, completamente azioni "domain`ish". Preferibilmente -. Ancora scritto in facile da capire il codice che è guidato dal dominio

Come la vedo io - problema è che UndoLastStatus ha molto senso esperto di dominio
. Più probabilmente stanno parlando di fare, l'annullamento e gli ordini di riempimento.

Qualcosa in questo senso potrebbe adattarsi meglio:

class Order{
  void CancelOrder(){
    Status=Status.Canceled;
  }
  void FillOrder(){
    if(Status==Status.Canceled)
      throw Exception();
    Status=Status.Filled;
  }
  static void Make(){
    return new Order();
  }
  void Order(){
    Status=Status.Pending;
  }
}

Io personalmente piace l'utilizzo di "status", sono condivisi automaticamente a tutto ciò che li utilizza - Vedo che come accoppiamento inutili .

Quindi mi sento di avere qualcosa di simile:

class Order{
  void CancelOrder(){
    IsCanceled=true;
  }
  void FillOrder(){
    if(IsCanceled) throw Exception();
    IsFilled=true;
  }
  static Order Make(){
    return new Order();
  }
  void Order(){
    IsPending=true;
  }
}

Per cambiare le cose correlate quando lo stato dell'ordine, cosa migliore da fare è quella di utilizzare i cosiddetti eventi dominio .
Il mio codice sarà lungo queste linee:

class Order{
  void CancelOrder(){
    IsCanceled=true;
    Raise(new Canceled(this));
  }
  //usage of nested classes for events is my homemade convention
  class Canceled:Event<Order>{
    void Canceled(Order order):base(order){}
  }     
}

class Customer{
  private void BeHappy(){
    Console.WriteLine("hooraay!");
  }
  //nb: nested class can see privates of Customer
  class OnOrderCanceled:IEventHandler<Order.Canceled>{
   void Handle(Order.Canceled e){
    //caveat: this approach needs order->customer association
    var order=e.Source;
    order.Customer.BeHappy();
   }
  }
}

Se l'ordine diventa troppo grande, si potrebbe voler verificare che cosa noreferrer contesti delimitate sono (come dice Eric Evans - se avesse avuto la possibilità di scrisse di nuovo il suo libro, si sarebbe mosso delimitata contesti per fin dall'inizio).

In breve - è una forma di decomposizione guidata da dominio.

L'idea è relativamente semplice - è bene avere più ordini provenienti da diversi punti di vista aka contesti.

es. -. Ordine dal contesto commerciale, Ordine dal contabile contesto

namespace Shopping{
 class Order{
  //association with shopping cart
  //might be vital for shopping but completely irrelevant for accounting
  ShoppingCart Cart;
 }
}
namespace Accounting{
 class Order{
  //something specific only to accounting
 }
}

Ma di solito abbastanza dominio stesso evita la complessità ed è facilmente decomponibili se si ascolta abbastanza da vicino. Per esempio. Si potrebbe sentire da termini esperti come OrderLifeCycle, OrderHistory, OrderDescription che è possibile sfruttare come ancore per la decomposizione.

NB: Tenere a mente - ho avuto a zero comprensione Il tuo dominio
. E 'molto probabile che questi verbi sto usando sono completamente strano ad esso.

Altri suggerimenti

sarei stato guidato dal GRASP principi. Applicare il Information Expert principio di progettazione, che è si dovrebbe assegnare la responsabilità alla classe che, naturalmente, ha la maggior parte delle informazioni necessarie per compiere la modifica.

In questo caso, dal momento che la modifica dello stato dell'ordine coinvolge altri enti, mi farebbe ognuno di questi oggetti di dominio a basso livello supportare un metodo per applicare la variazione rispetto a se stesso. Poi anche utilizzare un livello di servizio di dominio come lei in opzione 2, che astrae l'intera operazione, che coprono più oggetti del dominio, se necessario.

Vedere anche la Facciata modello.

Penso che avere un metodo come UndoLastStatus sulla classe Order si sente un po 'male perché le ragioni per la sua esistenza sono in un certo senso al di fuori del campo di applicazione di un ordine. D'altra parte, con un metodo che è responsabile per la modifica dello stato di un ordine, Order.ChangeStatus, si adatta bene come un modello di dominio. Lo stato di un ordine è un concetto di dominio corretto e la modifica di tale status deve essere fatto attraverso la classe Order, dal momento che possiede i dati associati con lo stato dell'ordine - è responsabilità della classe Ordine di tenere per sé coerente e in uno stato corretto .

Un altro modo di pensare è che l'oggetto ordine è ciò che è persistito nel database ed è l' 'ultima fermata' per tutte le modifiche applicate a un ordine. E 'più facile ragionare su quello che uno stato valido per un acquisto potrebbe essere dal punto di vista di un Ordine, piuttosto che dalla prospettiva di un componente esterno. Questo è ciò che DDD e OOP sono tutti circa, rendendo più facile per gli esseri umani a motivo di codice. Inoltre, l'accesso ai membri privati ??o protetti può essere richiesto di eseguire un cambiamento di stato, nel qual caso il metodo avendo sia sulla classe ordine è una soluzione migliore. Questo è uno dei motivi per cui i modelli di dominio anemici sono disapprovate -. Spostano la responsabilità di mantenere lo stato di distanza costante dalla classe possedere, così rompendo l'incapsulamento tra le altre cose

Un modo di attuare un funzionamento più specifico come UndoLastStatus sarebbe quella di creare un OrderService che espone il dominio ed è come componenti esterni funzionano sul dominio. Quindi è possibile creare un oggetto semplice comando in questo modo:

class UndoLastStatusCommand {
  public Guid OrderId { get; set; }
}

Una l'OrderService avrebbe un metodo per elaborare questo comando:

public void Process(UndoLastStatusCommand command) {
  using (var unitOfWork = UowManager.Start()) {
    var order = this.orderRepository.Get(command.OrderId);
    if (order == null)
      throw some exception

    // operate on domain to undo last status

    unitOfWork.Commit();
  }
}

Così ora il modello di dominio per l'Ordine espone tutti i dati e comportamenti che corrispondono a un ordine, ma l'OrderService, e il livello di servizio in generale, dichiarano i diversi tipi di operazioni che vengono eseguite su un ordine ed esporre il dominio per l'utilizzo con componenti esterni, come ad esempio il livello di presentazione.

anche prendere in considerazione esaminando il concetto di eventi dominio che considera modelli di dominio anemici e modi di migliorarle.

Sembra che non si guida questo dominio da prove. Date un'occhiata al lavoro di Rob Vens , in particolare il suo lavoro sulla modellazione esplorativo , tempo di inversione e attivo-passivo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top