Dipendenza circolare radice aggregata quando i dati sono necessari per il calcolo

0

Il mio progetto originale ha un servizio di dominio che ha fatto un sacco di lavoro che ha portato ad un modello di dominio anemico (concetti come BalanceCalculators, AccountServices, ecc.). Ho rifattorizzato il mio disegno che ha portato a Conti che calcolano il saldo (che è un concetto di dominio).

Tuttavia, ciò mi ha indotto a dover mantenere un riferimento alle Transactions che ha portato a una dipendenza circolare tra le Roots aggregate. Così ho introdotto un altro concetto chiamato Entry. L'idea è che quando viene creata una transazione, verrà generato un evento TransactionCreatedEvent . Da questo posso generare un Entry dalla transazione e aggiungerlo a Account . La classe Entry contiene solo un TransactionID e alcuni metadati che possono essere utilizzati per calcolare i saldi degli account (alla fine avrò bisogno di estendere questo account dei conti di investimento).

Tuttavia, tutto quello che vedo su DDD ha solo eventi di dominio utilizzati dal livello dell'applicazione. Sto andando in questo modo nel modo sbagliato con l'aspettativa che Domain Events sia cablato & usato SOLO nel livello di dominio? Inoltre, dove e come collegherò un gestore di eventi nel livello dominio? Penso di aver bisogno di collegare un account e una transazione specifici.

Ad esempio, supponiamo che Transaction_1 colleghi Account_1 e Account_2 con un valore di $ 100,00. Le voci vengono create in entrambi Account_1 e Account_2. Tuttavia, alla fine l'utente modifica il valore di Transazione_1 a $ 1.000,00. Devo consentire a Account_1 e Account_2 che i valori della voce siano cambiati.

Use Cases

Add/remove an account
Add/remove an account to another account (i.e. subaccounts)
Edit account details such as name
Retreive balance of account
Create transaction
Modify transaction amount, credited account, debited account, date, etc.

Need concept of an investment account as well...

Account.cs

public class Account
{
    public int Id { get; }
    public string Name { get; private set; }

    public enum AccountingType
    {
        Asset,
        Liability,
        Income,
        Expense,
        Equity
    };

    public AccountingType Type { get; private set; }

    public IEnumerable<Account> SubAccounts => _subAccounts;
    public decimal Value => ComputeValue();

    public Account(int id, string name, AccountingType type)
    {
        Id = id;
        Name = name;
        Type = type;
    }

    public void Rename(string newName)
    {
        var oldName = Name;
        Name = newName;
        DomainEvents<AccountRenamedEvent>.Publish(new AccountRenamedEvent(oldName, Name));
    }

    public void ChangeType(AccountingType newType)
    {
        Type = newType;
    }

    public void AddSubAccount(Account account)
    {
        _subAccounts.Add(account);
    }

    public void RemoveSubAccount(Account account)
    {
        _subAccounts.Remove(account);
    }

    public void PostEntry(Entry entry)
    {
        _entries.Add(entry);
    }

    public void RemoveEntry(Entry entry)
    {
        _entries.Remove(entry);
    }

    private decimal ComputeValue()
    {
        var value = 0m;

        foreach (var entry in _entries)
        {
            value += entry.Value;
        }

        foreach (var account in _subAccounts)
        {
            value += account.Value;
        }

        return value;
    }

    private readonly List<Account> _subAccounts = new List<Account>();
    private readonly List<Entry> _entries = new List<Entry>();
}

Entry.cs

public class Entry
{
    public int TransactionId;
    public decimal Value;

    public Entry(int transactionId, decimal value)
    {
        TransactionId = transactionId;
        Value = value;
    }
}

Transaction.cs

public class Transaction
{
    public Transaction(int transactionId, DateTime date, string description, decimal amount, int debitAccountId, int creditAccountId)
    {
        TransactionId = transactionId;
        Date = date;
        Description = description;
        Amount = amount;
        DebitAccountId = debitAccountId;
        CreditAccountId = creditAccountId;

        DomainEvents<TransactionCreatedEvent>.Publish(new TransactionCreatedEvent(TransactionId, Date, Description, Amount, DebitAccountId, CreditAccountId));
    }

    public void ChangeDate(DateTime newDate)
    {
        Date = newDate;

        DomainEvents<TransactionDateChangedEvent>.Publish(new TransactionDateChangedEvent(TransactionId, newDate));
    }

    public void ChangeDescription(string description)
    {
        Description = description;
    }

    public void ChangeAmount(decimal amount)
    {
        Amount = amount;
    }

    public void ChangeDebitAccountId(int newAccountId)
    {
        DebitAccountId = newAccountId;
    }

    public void ChangeCreditAccountId(int newAccountId)
    {
        CreditAccountId = newAccountId;
    }

    public int TransactionId { get; }
    public DateTime Date { get; private set; }
    public string Description { get; private set; }
    public decimal Amount { get; private set; }
    public int DebitAccountId { get; private set; }
    public int CreditAccountId { get; private set; }
}
    
posta keelerjr12 24.10.2018 - 02:36
fonte

0 risposte

Leggi altre domande sui tag