1 回答
TA贡献1846条经验 获得超7个赞
这将取决于具体情况。我将尝试解释几个不同的问题及其解决方案。
您有一个系统,其中审计信息自然是域的一部分。
让我们举一个简单的例子:
在Bank和Person之间签订合同的银行系统。银行由BankEmployee代表。签署或修改合同时,您需要在合同中包含有关谁做的信息。
public class Contract {
public void AddAdditionalClause(BankEmployee employee, Clause clause) {
AddEvent(new AdditionalClauseAdded(employee, clause));
}
}
您有一个系统,其中审计信息不是域的自然组成部分。
这里有几件事需要解决。例如,用户可以只向您的系统发出命令吗?有时另一个系统可以调用命令。
解决方案:记录所有的传入命令及其处理后的状态:成功、失败、拒绝等。
包括命令发布者的信息。
记录命令发生的时间。您可以在命令中包含有关发行者的信息,也可以不包含。
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
}
}
优点:这将从有人发出命令的知识中删除您的域
缺点:如果您需要有关事件更改和匹配命令的更多详细信息,您将需要匹配时间戳和其他信息。根据系统的复杂性,这可能会变得很难看
解决方案:记录entity/aggregate中的所有incomming命令和相应的事件。查看本文以获取详细示例。CommandIssuer您可以在事件中包含。
public class SomethingAggregate {
public void Handle(CommandCtx ctx) {
RecordCommandIssued(ctx);
Process(ctc.cmd);
}
}
你确实将一些来自外部的信息包含到你的聚合中,但至少它是抽象的,所以聚合只是记录它。看起来还不错,是吗?
解决方案:使用将包含有关您正在使用的操作的所有信息的传奇。在分布式系统中,大多数时候你需要这样做,所以它会是一个很好的解决方案。在另一个系统中,它会增加您可能不想拥有的复杂性和开销 :)
public void DoSomethingSagaCoordinator {
public void Handle(CommandContext cmdCtx) {
var saga = new DoSomethingSaga(cmdCtx);
sagaRepository.Save(saga);
saga.Process();
sagaRepository.Update(saga);
}
}
我已经使用了此处描述的所有方法以及您的Option 2的变体。在我处理请求时的版本中,他们Repositoires可以访问context包含用户信息的对象,因此当他们保存事件时,此信息包含在EventRecord同时具有事件数据和用户信息的对象中。它是自动化的,因此其余代码与它分离。我确实使用 DI 将上下文注入存储库。在这种情况下,我只是将事件记录到事件日志中。我的聚合不是事件来源的。
我使用这些准则来选择一种方法:
如果它是一个分布式系统 -> 去 Saga
如果不是:
我是否需要将详细信息与命令相关联?
是:传递
Commands
和/或CommandIssuer
信息到聚合
如果没有那么:
数据库是否具有良好的事务支持?
是:保存
Commands
在CommandIssuer
聚合之外。否:保存
Commands
并CommandIssuer
汇总。
- 1 回答
- 0 关注
- 130 浏览
添加回答
举报