Я читаю шаблон учета и довольно любопытно о его внедрении в CQRS.
Я думаю, что AccountingTransaction является совокупным корнем, поскольку он защищает инвариант:
Нет утечек денег, это должен быть переход от одной учетной записи к другой.
public class AccountingTransaction {
private String sequence;
private AccountId from;
private AccountId to;
private MonetaryAmount quantity;
private DateTime whenCharged;
public AccountingTransaction(...) {
raise(new AccountingEntryBookedEvent(sequence, from, quantity.negate(),...);
raise(new AccountingEntryBookedEvent(sequence, to, quantity,...);
}
}
Когда AccountingTransaction добавляется в его репозиторий. Он публикует несколько AccountingEntryBookedEvent, которые используются для обновления баланса соответствующих учетных записей на стороне запроса.
Один агрегированный корень обновлен на транзакцию db, возможная согласованность, настолько хорошая.
Но что делать, если некоторые учетные записи применяют ограничения передачи, например, не могут передать количество больше текущего баланса? Я могу использовать сторону запроса, чтобы получить баланс аккаунта, но я беспокоюсь, что данные со стороны запроса устарели.
public class TransferApplication {
public void transfer(...) {
AccountReadModel from = accountQuery.findBy(fromId);
AccountReadModel to = accountQuery.findBy(toId);
if (from.balance() > quantity) {
//create txn
}
}
}
Должен ли я моделировать учетную запись в командной строке? Я должен обновить не менее трех совокупных корней на транзакцию db (от/до учетной записи и учетной записи txn).
public class TransferApplication {
public void transfer(...) {
Account from = accountRepository.findBy(fromId);
Account to = accountRepository.findBy(toId);
Transaction txn = new Transaction(from, to, quantity);
//unit or work locks and updates all three aggregates
}
}
public class AccountingTransaction {
public AccountingTransaction(...) {
if (from.permit(quantity) {
from.debit(quantity);
to.credit(quantity);
raise(new TransactionCreatedEvent(sequence, from, to, quantity,...);
}
}
}