你把DDD中的常用数据设置器放在哪里进行更新/插入


Where do you put common data setters in DDD for update/insert?

我有一个关于领域驱动设计的问题。让我们想象一个简单的场景。

我有一个名为"用户"的实体,它有一些属性。其中一个属性是"date_created"、"date_modified"answers"last_login_ip"。

假设我们有一个创建用户的表单,如果创建成功,它将对用户进行身份验证。

  1. 控制器获取POST数据
  2. 通过方法"createAndAuthenticateUser"将发布数据发送到UsersService
  3. 服务接收数据,对其进行验证(在这里进行,而不是在实体中进行,因为验证与存储库绑定,例如验证电子邮件是否已经存在,等等)
  4. 如果验证正常,它会创建一个新的实体,将数据分配给它,然后将实体发送到存储库进行保存。然后存储库将此用户保存在数据源中

到目前为止还不错。这里的问题是,必须在该服务方法中设置date_created/date_modified/last_login_ip。

如果我想在用户对象更新时设置date_modified ANYTIME(例如,在登录时我想更新date_modified,在用户更新时我想再次修改,在用户创建时我想重新修改),该怎么办?

从逻辑上讲,我自己的答案是把它放在存储库中,就像。。。

(这里的元代码有点,语法无关紧要)

function save($User) {
if (!$User->id) $User->date_created = 'YYYY-MM-DD HH:II:SS';
$User->date_modified = 'YYYY-MM-DD HH:II:SS';
$DataSource->Save($User);
return $User;
}

然而,从我所读到的内容来看,存储库应该总是在调用者和数据源之间映射数据(反之亦然),就这样。它不应该设置数据或类似的东西。

当然,你可以告诉我这是一种行为,所以我可以有一种行为说$User->markAsUpdated(),它只会设置date_modified属性。但是,这意味着这个方法必须从多个地方调用,而不是有一个集中的地方来调用。我看不出在存储库中没有这个代码的好处。

有什么想法吗?

如果由于某种原因,上次登录ip的概念实际上是用户的核心,那么在登录时更新用户是有效的。事实上,您对执行更新以保存最后一个登录IP表示担忧,这意味着它实际上不是一个用户概念,而是一个安全、审计或其他外部用户概念。

至于设置修改和创建日期,我会提出同样的论点。如果系统要求用户同时维护和公开这些信息,那么在用户上创建一个私有方法,每个公共方法在修改状态时都会调用该方法,这将设置修改日期。如果不是,那么您几乎有两种选择——要么创建一个收到更新通知并保留自己的审核记录的审核服务,要么让存储库在更新记录时设置字段。