DDD - Aggregate Roots: gestione dell'efficienza e della concorrenza

6

Prima di tutto, ammetto che sono un novizio di DDD e ho bisogno di leggere il "libro blu".

Sto costruendo un sistema che ha una AggregateRoot di tipo "Match". Ogni partita può avere una raccolta di "Voti" e ha anche una proprietà "VoteCount" di sola lettura che viene incrementata quando un utente up-vota o down-vota una Partita.

Poiché molti utenti potrebbero votare su una partita contemporaneamente, i voti devono essere aggiunti / rimossi dalla partita e il VoteCount deve essere incrementato / decrementato come un'operazione atomica che coinvolge blocchi di scrittura (con blocchi gestiti dal DB ). (Ho bisogno di VoteCount come valore statico nel database per essere interrogato in modo efficiente da altri processi / componenti.)

Mi sembra che se fossi aderente al rigoroso DDD, avrei codificato questa operazione in quanto tale:

  1. Un servizio di applicazione riceverà un oggetto di richiesta di voto
  2. Il servizio recupera quindi l'oggetto Match da un repository delle corrispondenze
  3. Il servizio chiamerebbe quindi una sorta di metodo sull'oggetto Match per aggiungere il voto alla raccolta e aggiornare VoteCount.
  4. Il repository dovrebbe quindi mantenere tale istanza di corrispondenza sul DB

Tuttavia, questo approccio non è fattibile per la mia applicazione per 2 motivi principali, come vedo:

  1. Sto utilizzando MongoDB sul back-end e non posso avvolgere questa operazione di lettura-scrittura in una transazione per impedire letture sporche dei dati di corrispondenza e dei relativi voti e voti associati.

  2. È altamente inefficiente. Sto tirando indietro l'intero grafico degli oggetti solo per aggiungere un voto e incrementare VoteCount. Sebbene questo sia più efficiente in un documento db che in uno relazionale, sto ancora facendo un'operazione di lettura non necessaria.

Problemi 1 & 2 non sono un problema quando si invia un singolo oggetto Vote al repository e si esegue una dichiarazione di aggiornamento atomico contro Mongo.

Potrebbe votare, in questo caso, essere considerato un "aggregato" e meritarsi del proprio repository e dello stato aggregato?

    
posta drogon 01.02.2013 - 00:50
fonte

3 risposte

5

Could Vote, in this case be considered an "aggregate" and be deserving of its own repository and aggregate status?

Penso che questa potrebbe essere la risposta giusta. Un aggregato dovrebbe essere un limite di consistenza transazionale. C'è un requisito di coerenza tra i voti su una partita? I regali di una collezione Vote su un aggregato Match suggerirebbero che esiste. Tuttavia, sembra che un voto non abbia niente a che fare con il prossimo.

Invece, memorizzerei ogni voto individualmente. In questo modo è possibile utilizzare la funzionalità aggregata di MongoDB per ottenere il conteggio, anche se non sono sicuro se sia ancora lento. Se lo è, puoi aggregare utilizzando la funzionalità Mappa / Riduci.

Più in generale, questo potrebbe non essere il più adatto per il DDD. Se il dominio non consiste in un comportamento complesso, non c'è una ragione per provare ad adattare i modelli tattici DDD (entità, aggrappati) a questo dominio.

    
risposta data 01.02.2013 - 02:02
fonte
5

Prima di tutto, DDD è davvero sulla creazione di un modello in cui la lettura del codice è simile a come gli esperti di dominio effettivi parlerebbero del dominio.

In secondo luogo, il modo in cui DDD descrive una radice aggregata, gli oggetti figlio nella radice aggregata sono meramente proprietà sulla radice aggregata stessa e non si dovrebbe essere in grado di accedere direttamente agli elementi figli, solo attraverso la radice aggregata. / p>

Così visto da una prospettiva DDD, se i voti sono figli alla "partita" radice aggregata, allora l'atto di aggiungere un voto a una partita è in realtà un atto di modifica della corrispondenza.

Sebbene tu non abbia dato abbastanza informazioni per farmi comprendere appieno il dominio, non mi sembra che questo sarebbe il modo naturale per vedere le cose, ma immagino che abbia alcune somiglianze con StackExchange?

Su qualsiasi sito StackExchange, se apro la mia pagina utente, posso vedere un elenco di voti che ho lanciato, incluso se è un up- o downvote e il momento in cui lancio il voto. Questa è una domanda diretta sui voti che ho espresso. Pertanto, se dovessi creare un modello DDD di StackExchange, le domande e le risposte NON potrebbero essere considerate come radici aggregate contenenti voti.

In questo caso, i voti sarebbero entità stesse.

Nota che qui sono molto concentrato sul modo in cui "il libro blu" descrive gli aggregati, principalmente perché lo hai menzionato, e ti concentri su DDD nella descrizione della domanda. Ciò non significa che questo sia l'unico / corretto modo di trattare gli aggregati.

P.S. Se non hai ancora letto il libro, questa presentazione tocca molto l'argomento: link (part1) link (part2)

    
risposta data 01.02.2013 - 17:38
fonte
2

Sì, puoi modellare Vota come aggregato a se stesso. Nel mondo reale, spesso le persone votano per diverse cose contemporaneamente. L'aggregato sarebbe quindi chiamato Ballot invece di votare. Hai solo un caso speciale in cui c'è un solo articolo da votare alla volta.

Non posso parlare per MongoDB (forse qualcun altro può farlo) - ma sarebbe molto facile farlo in RavenDB con qualcosa del tipo:

public class Match
{
    public string Id { get; set; }
    public string Name { get; set; } // or whatever
}

public class Vote
{
    public string Id { get; set; }
    public string MatchId { get; set; }
    public string UserId { get; set; }
    public bool YeaOrNay { get; set; } // or whatever
}

Quindi dovresti semplicemente costruire una mappa / ridurre l'indice sopra i tuoi voti per calcolare i risultati.

    
risposta data 01.02.2013 - 01:35
fonte

Leggi altre domande sui tag