I client possono chiamare metodi su entità diverse dalla radice aggregata?

7

Evans introduce nel suo libro "Domain Driven Design" nel capitolo 6 "Aggregates" il concetto di Aggregates. Definisce inoltre le regole per tradurre tale concetto in un'implementazione (Evans 2009, pp. 128-129):

The root ENTITY can hand references to the internal ENTITIES to other objects, but those objects can use them only transiently, and they may not hold on to the reference.

Dopo aver elaborato altre regole, le riassume in questo paragrafo:

Cluster the Entities and Value Objects into Aggregates and define boundaries around each. Choose one Entity to be the root of each Aggregate, and control all access to the objects inside the boundary through the root. Allow external objects to hold references to the root only. Transient references to internal members can be passed out for use within a single operation only. Because the root controls access, it cannot be blindsided by changes to the internals. This arrangement makes it practical to enforce all invariants for objects in the Aggregate and for the Aggregate as a whole in any state change.

Quindi cosa significa esattamente l'uso transitorio?

Il mio collega comprende che solo la radice aggregata espone un'interfaccia pubblica per i client. I clienti non avranno la possibilità di chiamare alcuna operazione su un'entità diversa dalla radice aggregata.

La mia comprensione delle frasi citate è diversa. Capisco che in effetti consenta esplicitamente ai client di chiamare operazioni su entità interne. Tuttavia solo dopo averli ricevuti dalla radice.

Quindi diamo un esempio concreto:

Diciamo che Cart è composta da molti Items . Ogni Item ha un Quantity . Il modello deve supportare il caso d'uso "Aumentare la quantità di un articolo specifico". Non è possibile violare alcuna invariante che influisce su qualcosa al di fuori dell'Articolo.

Un modello sta violando le regole citate sopra, quando un client può farlo chiamando cart.item(itemId).increaseQuantity() o un client può solo chiamare un cart.increaseItemQuantity(itemId) ? Quale sarebbe il vantaggio di quest'ultimo?

    
posta Markus Malkusch 18.08.2016 - 21:26
fonte

1 risposta

2

Finché Item non può esistere senza Cart essendo presente, non c'è differenza tra le due opzioni. È possibile mantenere gli invarianti in entrambi i casi.

Nel caso in cui il metodo sia su Item , Item può "notificare" il suo carrello genitore per verificare l'invariante quando ha bisogno di cambiare il proprio stato. Questo rende le cose un po 'più complicate, perché poi c'è una dipendenza ciclica tra Item e Cart (che presumo non sia un problema grazie all'assunzione nella prima frase e qualcosa che IMO deve esistere in entrambi i casi).

Nel caso in cui il metodo sia su Cart , lo rende più semplice, perché non è necessario che Item faccia riferimento a Cart . Ma lo rende complicato perché ora il metodo non verifica solo invarianti e cambia lo stato. Ma deve anche garantire che l'oggetto (o il suo ID) sia valido per questo Cart . Nell'altro caso, questo è già gestito dal metodo che richiede l'articolo dal carrello.

tl; dr; Entrambe le opzioni hanno chiari vantaggi e svantaggi e nessuna delle due sembra ovviamente migliore o peggiore di altre.

    
risposta data 19.08.2016 - 12:20
fonte

Leggi altre domande sui tag