DDD Agregat limite unul pentru unii și nu unu la mulți între entitățile într-un agregat

0

Problema

Am urmarit un tutorial despre DDD în care se spune că, dacă am root agregat SnackMachine care are mai mult de 30 de elemente copil copilul elemente ar trebui să fie separat de agregate. De exemplu, SnackMachine are o mulțime de PurshaseLog (mai mult de 30) și este mai bine pentru PurshaseLog să fie într-o separat de agregate. De ce este asta?

2
2

Motivul pentru limitarea dimensiunea globală a unui agregat este pentru că întotdeauna încărcați complet agregate în memorie și vă păstrați întotdeauna plin agregate transactionally. O foarte mare agregat ar cauza probleme tehnice.

Asta a spus, nu există nici o astfel de "30 de elemente copil" regulă din agregate de proiectare și sunete arbitrare ca o regulă. De exemplu, având mai puține foarte mare de elemente copil ar putea fi din punct de vedere tehnic mai rău decât să ai 30 de foarte ușoare elemente copil. O bună modalitate de stocare a agregatelor este la fel de documente json, având în vedere că mereu vei citi și scrie documente și operații atomice. Dacă credeți că în acest fel, îți vei da seama că un agregat de proiectare care implică o foarte mare sau chiar în continuă creștere copil de colectare în cele din urmă va cauza probleme. Un PurhaseLog sună ca o colecție în continuă creștere.

Cea de-a doua parte a regulii care spune "pune-l într-o separat de agregate" este, de asemenea, nu este corect. Nu crea agregate pentru că aveți nevoie pentru a stoca unele date și nu se încadrează într-o existentă agregate. Creați agregate pentru că aveți nevoie pentru a pune în aplicare unele logica de afaceri și aceasta logica de afaceri va avea nevoie de unele date, deci ai pus ambele lucruri împreună într-un agregat.

Așa că, deși ceea ce explică în cauză sunt lucruri să ia în considerare atunci când proiectarea agregate pentru a evita probleme tehnologice, ți-aș sugera să-ți pui o atenție la responsabilitățile reale ale agregatului.

În exemplul tău, care sunt responsabilitățile SnackMachine? Are într-adevăr nevoie (integral) lista de PurchaseLogs? Ce operațiuni va SnackMachine expune? Să zicem că se expune PurchaseProduct(productId) și LoadProduct(productId, cantitate). Pentru a executa sale de logica de afaceri, acest ansamblu ar avea nevoie de o listă de produse și ține cont de cantitatea disponibilă, dar nu este nevoie pentru a stoca achiziționarea jurnal. În schimb, la fiecare Achiziție, ar putea publica un eveniment ProductPurchased(SnackMachineId, ProductId, Data, AvailableQuantity). Apoi, sisteme externe ar putea abona la acest eveniment. Un abonat poate înregistra PurchaseLog pentru scopuri de raportare și un alt abonat putea trimite pe cineva pentru a reîncărca aparatul atunci când stocul a fost mai mică decât X.

2021-11-17 23:29:06
2

Dacă PurchaseLog nu este propriul agregat, atunci înseamnă că acesta poate fi recuperat sau adăugate ca parte a copilului colecție de SnackMachine.

Prin urmare, de fiecare dată când doriți să adăugați un PurchaseLog, vei prelua SnackMachine cu copilul său PurchaseLogs, se adauga PurchaseLog la colecția sa. Apoi salvați modificările pe unitate de lucru.

Ai într-adevăr nevoie pentru a prelua 30+ cumpărare busteni, care sunt inutile pentru scopul de utilizare cazul de a crea o nouă achiziție log?

Aplicare Strat - Opțiunea 1 (PurchaseLog este o entitate deținută de SnackMachine)

// Retrieve the snack machine from repo, along with child purchase logs
// Assuming 30 logs, this would retrieve 31 entities from the database that
// your unit of work will start tracking.
SnackMachine snackMachine = await _snackMachineRepository.GetByIdAsync(snackMachineId);

// Ask snack machine to add a new purchase log to its collection
snackMachine.AddPurchaseLog(date, quantity);

// Update
await _unitOfWork.SaveChangesAsync();

Aplicare Strat - Opțiunea 2 (PurchaseLog este un agregat rădăcină)

// Get a snackmachine from the repo to make sure that one exists
// for the provided id.  (Only 1 entity retrieved);
SnackMachine snackMachine = await _snackMachineRepository.GetByIdAsync(snackMachineId);

// Create Purhcase log
PurchaseLog purchaseLog = new(
   snackMachine,
   date,
   quantity);

await _purchaseLogRepository.AddAsync(purchaseLog);

await _unitOfWork.SaveChangesAsync()

PurchaseLog - opțiunea 2

class PurchaseLog
{
    int _snackMachineId;
    DateTimne _date;
    int _quantity;

    PurchaseLog(
        SnackMachine snackMachine,
        DateTime date,
        int quantity)
    {
        _snackMachineId = snackMachine?.Id ?? throw new ArgumentNullException(nameof(snackMachine));
        _date = date;
        _quantity = quantity;
    }
}

Cea de-a doua opțiune urmează conturul de cazul dumneavoastră de utilizare mai precis și, de asemenea, rezultatele în mai puțin de i/o cu baza de date.

2021-11-18 13:22:33

În alte limbi

Această pagină este în alte limbi

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................