我有一个会议对象:
Meeting{id, name, time, CreatedBy, UpdatedBy}
和
MeetingAssignee{id, MeetingID, EmployeeId, CreatedBy, UpdatedBy)
Meeting,作为Aggregate root,有一个方法AssignEmployee。
当我调用AssignEmployee时,我正要将当前用户传递给Meeting对象,以便它可以相应地更新其审计字段。
但这似乎不对 - 是吗?显然,我可以公开审计字段并在以后更改它们 - 也许是在服务级别?
每个人都更喜欢更新这些字段的方法是什么?
请注意:我们没有使用Nhibernate,而是自定义ORM,它没有自动生成任何内容。
感谢。
答案 0 :(得分:4)
审计和日志记录很有趣,因为它们通常在应用程序的任何地方都需要,并且它们都是要求(记录 是OPs人员的要求)。
在不了解您的模型的情况下,由于审核必须是一项要求,我会将当前用户传递给AssignEmployee
而不是在那里写一行AuditBlahBlahBlah
,我会添加一个事件(可能是MeetingUpdated或AssigneeAdded ...你会找到一个好名字)并且该事件将被分派到执行审核的类中。通过这种方式,Meeting类没有关于审计和调度业务事件的线索以供审计(在我看来,这是非常DDDish)。
我想知道其他人会怎么说(希望我能学到新的东西!)
答案 1 :(得分:4)
考虑使用域事件。
您的域名模型中的所有有趣内容都应该引发一个事件,大声喊出刚刚发生的事情。从外部,只需附加日志处理程序,将其转储到db或其他地方。
那样 - 你不需要用某种IAuditService搞乱你的域名。
更好 - 域模型可以使用事件作为内部通信的一种方式 为了说明为什么这是一个好主意 - 想象我们正在描述早晨,日出和鲜花的领域模型。
太阳的责任是告诉所有鲜花他们应该打开吗?并不是的。太阳只需要足够明亮(提升事件),光必须传播到地球(必须有某种基础设施使事件成为可能)并且花朵必须在接收光时做出反应(其他领域模型应该处理事件)。
另一个类比 - 驾驶员有责任了解交通信号灯的颜色。
答案 2 :(得分:0)
在持久化或更新实体时,您可以从服务层调用审计服务,并将审计服务注入到需要审计功能的任何服务中,并尽快保留新创建的实体。
我看到如何很难弄清楚审核的方式和时间,特别是如果您的实体在被保留之前的某个时间作为系统中的可用实体存在。即使它们在被持久化之前存在一段时间,也许您可以创建内存中的审计数据,包含其创建的详细信息,然后在实体最终持久化时继续存在。或者将创建者,创建者,修改者,修改者等数据集设置为实体中的私有字段,并在实体持久化时将其写入审核日志?
我会对权衡取舍感兴趣。
答案 3 :(得分:0)
我认为审核属性不是域模型的关注点。如果应用程序服务层中可用的所有用例都使用域模型在系统中进行更改,并且聚合根发布了以后发生的任何事件,则可以为任何事件实现处理程序,并将其保存在您需要的审核日志格式。