1 回答

TA貢獻(xiàn)1846條經(jīng)驗(yàn) 獲得超7個(gè)贊
這將取決于具體情況。我將嘗試解釋幾個(gè)不同的問(wèn)題及其解決方案。
您有一個(gè)系統(tǒng),其中審計(jì)信息自然是域的一部分。
讓我們舉一個(gè)簡(jiǎn)單的例子:
在Bank和Person之間簽訂合同的銀行系統(tǒng)。銀行由BankEmployee代表。簽署或修改合同時(shí),您需要在合同中包含有關(guān)誰(shuí)做的信息。
public class Contract {
public void AddAdditionalClause(BankEmployee employee, Clause clause) {
AddEvent(new AdditionalClauseAdded(employee, clause));
}
}
您有一個(gè)系統(tǒng),其中審計(jì)信息不是域的自然組成部分。
這里有幾件事需要解決。例如,用戶可以只向您的系統(tǒng)發(fā)出命令嗎?有時(shí)另一個(gè)系統(tǒng)可以調(diào)用命令。
解決方案:記錄所有的傳入命令及其處理后的狀態(tài):成功、失敗、拒絕等。
包括命令發(fā)布者的信息。
記錄命令發(fā)生的時(shí)間。您可以在命令中包含有關(guān)發(fā)行者的信息,也可以不包含。
public interface ICommand {
public Datetime Timestamp { get; private set; }
}
public class CommandIssuer {
public CommandIssuerType Type { get; pivate set; }
public CommandIssuerInfo Issuer {get; private set; }
}
public class CommandContext {
public ICommand cmd { get; private set; }
public CommandIssuer CommandIssuer { get; private set; }
}
public class CommandDispatcher {
public void Dispatch(ICommand cmd, CommandIssuer issuer){
LogCommandStarted(issuer, cmd);
try {
DispatchCommand(cmd);
LogCommandSuccessful(issuer, cmd);
}
catch(Exception ex){
LogCommandFailed(issuer, cmd, ex);
}
}
// or
public void Dispatch(CommandContext ctx) {
// rest is the same
}
}
優(yōu)點(diǎn):這將從有人發(fā)出命令的知識(shí)中刪除您的域
缺點(diǎn):如果您需要有關(guān)事件更改和匹配命令的更多詳細(xì)信息,您將需要匹配時(shí)間戳和其他信息。根據(jù)系統(tǒng)的復(fù)雜性,這可能會(huì)變得很難看
解決方案:記錄entity/aggregate中的所有incomming命令和相應(yīng)的事件。查看本文以獲取詳細(xì)示例。CommandIssuer您可以在事件中包含。
public class SomethingAggregate {
public void Handle(CommandCtx ctx) {
RecordCommandIssued(ctx);
Process(ctc.cmd);
}
}
你確實(shí)將一些來(lái)自外部的信息包含到你的聚合中,但至少它是抽象的,所以聚合只是記錄它??雌饋?lái)還不錯(cuò),是嗎?
解決方案:使用將包含有關(guān)您正在使用的操作的所有信息的傳奇。在分布式系統(tǒng)中,大多數(shù)時(shí)候你需要這樣做,所以它會(huì)是一個(gè)很好的解決方案。在另一個(gè)系統(tǒng)中,它會(huì)增加您可能不想擁有的復(fù)雜性和開(kāi)銷 :)
public void DoSomethingSagaCoordinator {
public void Handle(CommandContext cmdCtx) {
var saga = new DoSomethingSaga(cmdCtx);
sagaRepository.Save(saga);
saga.Process();
sagaRepository.Update(saga);
}
}
我已經(jīng)使用了此處描述的所有方法以及您的Option 2的變體。在我處理請(qǐng)求時(shí)的版本中,他們Repositoires可以訪問(wèn)context包含用戶信息的對(duì)象,因此當(dāng)他們保存事件時(shí),此信息包含在EventRecord同時(shí)具有事件數(shù)據(jù)和用戶信息的對(duì)象中。它是自動(dòng)化的,因此其余代碼與它分離。我確實(shí)使用 DI 將上下文注入存儲(chǔ)庫(kù)。在這種情況下,我只是將事件記錄到事件日志中。我的聚合不是事件來(lái)源的。
我使用這些準(zhǔn)則來(lái)選擇一種方法:
如果它是一個(gè)分布式系統(tǒng) -> 去 Saga
如果不是:
我是否需要將詳細(xì)信息與命令相關(guān)聯(lián)?
是:傳遞
Commands
和/或CommandIssuer
信息到聚合
如果沒(méi)有那么:
數(shù)據(jù)庫(kù)是否具有良好的事務(wù)支持?
是:保存
Commands
在CommandIssuer
聚合之外。否:保存
Commands
并CommandIssuer
匯總。
- 1 回答
- 0 關(guān)注
- 192 瀏覽
添加回答
舉報(bào)