2011-08-25 21 views
6

Stavo leggendo una domanda simile su SO: How update an entity inside Aggregate, ma non sono ancora sicuro di come un'interfaccia utente dovrebbe interagire con le entità all'interno di un aggregato.Aggiornamento di un'entità all'interno di un aggregato

Diciamo che ho uno User, con un gruppo di Address es. L'utente è la radice aggregata, mentre l'indirizzo esiste solo all'interno dell'aggregato.

In un interfaccia web, un utente può modificare i suoi indirizzi. In sostanza, ciò che accade è:

  • L'utente vede un elenco di indirizzi sulla sua interfaccia web
  • Si fa clic su un indirizzo, e viene reindirizzato a questa pagina: edit-address?user=1&address=2
  • In questa pagina, ottiene un forma in cui può modificare questo indirizzo.

ho abbiamo deciso di bypassare la radice di aggregazione, questo sarebbe semplice:

  • Vorremmo caricare direttamente il Address con la sua Id
  • Vorremmo aggiornarlo, quindi salvarlo

Perché vogliamo farlo in modo DDD, abbiamo diverse soluzioni:

  1. O noi chiedere all'utente di ottenere questo Discorso di Id:

    address = user.getAddress(id);
    address.setPostCode("12345");
    address.setCity("New York");
    em.persist(user);

    Il problema di questo approccio è, IMO, che la radice di aggregazione ancora non ha molto più controllo su ciò che viene fatto con l'indirizzo. Restituisce solo un riferimento ad esso, quindi non è molto diverso dall'esclusione dell'aggregato.

  2. Oppure si diciamo l'aggregato per aggiornare un indirizzo esistente:

    user.updateAddress(id, "12345", "New York");
    em.persist(user);

    Ora l'aggregato ha il controllo su ciò che è fatto con questo indirizzo, e può prendere le misure necessarie che va con l'aggiornamento di un indirizzo.

  3. O trattiamo l'indirizzo come un oggetto valore, e non ci aggiorniamo il nostro Address, ma piuttosto eliminarlo e ricrearlo:

    user.removeAddress(id);
    address = new Address();
    address.setPostCode("12345");
    address.setCity("New York");
    user.addAddress(address);
    em.persist(user);

    Quest'ultima soluzione sembra elegante, ma indica che un indirizzo non può essere un'entità. Quindi, cosa succede se deve essere trattata come un'entità, ad esempio perché un altro oggetto business all'interno dell'aggregazione ha un riferimento ad esso?

Sono abbastanza sicuro che mi manca qualcosa qui per comprendere correttamente il concetto di aggregazione e come è usato in esempi di vita reale, quindi per favore non esitate a dare i vostri commenti!

risposta

4

No, non ti manca nulla - nella maggior parte dei casi l'opzione migliore sarebbe numero 2 (anche se io chiamerei quel metodo changeAddress poi updateAdress - aggiornamento sembra quindi non-DDD) e questo è a prescindere se un indirizzo è un oggetto entità o valore. Con Ubiquitous Language preferisci dire che l'utente ha cambiato il suo indirizzo, quindi è esattamente come dovresti modellarlo: è il metodo changeAddress che decide se aggiornare le proprietà (se Indirizzo è un'entità) o assegnare un oggetto completamente nuovo (quando è VO).

Il seguente codice di esempio presuppone lo scenario più comune - Indirizzo come VO:

public void ChangeAddress(AddressParams addressParams) 
    { 
     // here we might include some validation 

     address = new Address(addressParams); 

     // here we might include additional actions related with changing address 
     // for example marking user as required to confirm address before 
     // next billing 
    } 

Ciò che è importante in questo esempio, è che una volta che è stato creato Indirizzo, viene considerata valida - non ci può essere indirizzo non valido oggetto nel tuo aggregato. Ricorda però che se dovresti seguire questo esempio o meno dipende dal tuo dominio attuale - non c'è un percorso da seguire. Questo è il più comune però.

E sì, dovresti sempre eseguire operazioni sulle tue entità attraversando la radice aggregata - il motivo per questo è stato dato in molte risposte su SO (per esempio in questo Basic Aggregate Question).

Se qualcosa è un'entità o VO dipende dai requisiti e dal dominio. La maggior parte delle volte l'indirizzo è solo un oggetto valore, perché non c'è differenza tra due indirizzi con gli stessi valori e gli indirizzi tendono a non cambiare durante la loro vita. Ma di nuovo, questa è la maggior parte del tempo e dipende dal dominio che stai modellando.

Un altro esempio: per la maggior parte dei domini uno Money sarebbe un oggetto valore - 10 $ è 10 $, non ha identità oltre all'ammontare. Tuttavia, se si modellasse un dominio che si occupa di denaro su un livello di fatture, ogni fattura avrebbe la propria identità (espressa con un numero univoco di qualche tipo), quindi sarebbe un'entità.

+0

Grazie. Questo ha davvero senso, anche se non sono sicuro di come implementare un metodo 'changeAddress()'. L'esempio sopra è una semplificazione eccessiva e un indirizzo potrebbe essere composto da una dozzina di campi, tra cui il nome della via, il numero dell'edificio, il punto 'LatLng' per la posizione esatta sulla mappa, ecc.Cosa suggerisci allora, metti tutti questi parametri negli argomenti del metodo, o crea una sorta di oggetto transitorio dal form (sarebbe anche un oggetto 'Address'?), E passalo come argomento a questo metodo? – Benjamin

+0

Ho aggiunto codice di esempio per lo scenario più comune. Non mi preoccuperei del numero di campi - DDD in realtà non riguarda i dati, riguarda le relazioni e la gestione della complessità. – kstaruch