DDD e modifica dei discendenti di Aggregate

2

In un approccio DDD, supponiamo di avere un Order (questa è la mia radice aggregata) e un Line (un discendente di Order ). In entrambi gli oggetti ho un setter privato per le proprietà e un builder che gestisce le creazioni del cluster di oggetto.

Per quanto ne so, ogni azione sul cluster passa attraverso la radice aggregata. È giusto? Ad esempio, se ho bisogno di un comando per nascondere una riga non posso avere semplicemente un metodo hide() sull'oggetto Line , ma invece dovrei avere un metodo hideLine() nell'aggregato root che attraversa il cluster di oggetti fino a Line .

A questo punto immagino uno scenario del genere:

// in the aggregate root
public void HideLine(Line line){
    line.Hide();
}

// in the Line class
public void Hide(){
   this.Hidden = true;
}

ma in questo modo qualcuno potrebbe fare qualcosa di simile:

Order orderA = _repo.getById(id_A);
Order orderB = _repo.GetById(id_B);

orderB.HideLine(orderA.Lines.First());

con effetti collaterali sconosciuti (in questo momento l'effetto collaterale è chiaro, ma in uno scenario più complesso questo potrebbe creare mal di testa).

Quindi potrei prendere queste contromisure:

  • Accetta un id come parametro per HideLine mehtd (cioè pubblico pubblico HideLine(Guid lineId) )
  • Verifica in HideLine(Line line) metodo che line è effettivamente in Order.Lines raccolta

Come gestisco i problemi di coerenza? Le mie soluzioni sono significative o mi manca il punto?

Post scriptum dopo i commenti

@Songo: l'aggregato Order (nota: nel mio scenario reale non è un Ordine ma un cluster più complesso) avvia un gestore di saga / processo durante la sua vita che sovrintende al processo di pubblicazione Order (prova a immagina che in uno scenario reale sia necessario pubblicare un ordine). Appena viene catturato OrderPublishingRequestEvent , inizia la saga e prova a convalidare il Order controllando se ogni Line è valido, e in caso contrario la linea verrà nascosta. Quindi il mio gestore di comandi è qualcosa del tipo:

public void Handle(OrderValidationCommand message)
{
    // get the aggregate
    Order order = _repository.GetById(message.OrderId);

    // call a service to make validation
    foreach (Line line in order.Lines)
    {
        var result = validator.Validate(line);

        if (result.IsValid)
            order.HideLine(line);
        else
            // do something else
    }

    order.Validate(); // raise event ValidatedOrderEvent
    _repository.Update(fornitura);
}
    
posta BAD_SEED 11.11.2014 - 17:49
fonte

1 risposta

1

Il Command Handler non sembra il posto migliore dove mettere la logica di occultamento della linea. Dovrebbe contenere l'orchestrazione ma non le regole del dominio.

C'è un modo per dare il validatore a Order e farlo validare da solo, come una singola azione eseguita in una transazione? Ciò risolverebbe il problema di accesso Line allo stesso tempo.

Forse questo sarebbe più in linea con il dominio, dal momento che dubito che tu abbia "nascosto una linea" come parte del tuo linguaggio onnipresente. Mi sembra più un effetto collaterale di convalida delle righe d'ordine, non un requisito di dominio.

    
risposta data 12.11.2014 - 12:31
fonte

Leggi altre domande sui tag