【发布时间】:2019-02-01 09:47:18
【问题描述】:
早上好,
我有一个模型,其中 用户 AR 具有特定的 UserRole(管理员、经销商或客户)。对于那个 AR,我会实施一些保护措施:
- 管理员不能拥有除自己以外的经理
- 经销商不能有管理员以外的经理
- 客户不能有除经销商或客户以外的经理(子帐户案例)
假设我想注册一个新的用户。流程如下:
RegisterUser 请求处理程序 -> RegisterUser 命令 -> RegisterUser 命令处理程序 -> User->register(...) 方法 ->UserWasRegistered 域事件
我应该如何以及在何处实施保护以准确验证我的用户 AR?现在,我的内容如下所示:
namespace vendor\Domain\Model;
class User
{
public static function register(
UserId $userId,
User $manager,
UserName $name,
UserPassword $password,
UserEmail $email,
UserRole $role
): User
{
switch($role) {
case UserRole::ADMINISTRATOR():
if(!$userId->equals($manager->userId)) {
throw new \InvalidArgumentException('An administrator cannot have a manager other than himself');
}
break;
case UserRole::RESELLER():
if(!$manager->role->equals(UserRole::ADMINISTRATOR())) {
throw new \InvalidArgumentException('A reseller cannot have a manager other than an administrator');
}
break;
case UserRole::CLIENT():
// TODO: This is a bit more complicated as the outer client should have a reseller has manager
if(!$manager->role->equals(UserRole::RESELLER()) && !$manager->role->equals(UserRole::Client())) {
throw new \InvalidArgumentException('A client cannot have a manager other than a reseller or client');
}
}
$newUser = new static();
$newUser->recordThat(UserWasRegistered::withData($userId, $manager, $name, $password, $email, $role, UserStatus::REGISTERED()));
return $newUser;
}
}
正如您在此处看到的,守卫位于 User AR 中,我认为这很糟糕。我想知道是否应该将这些警卫放在外部验证器或命令处理程序中。另一件事是我可能还应该访问读取模型以确保用户的唯一性和管理器的存在。
最后一件事是,我更愿意为 manager 属性传递一个 UserId VO 而不是 User AR,因此我认为不应该放入警卫用户 AR。
非常感谢您的建议。
【问题讨论】:
-
你为什么使用
static方法? -
@Constantin Galbenu 因为我想表达真正的意图(无处不在的语言)。 new() 从域的角度来看没有意义,而 register() 清楚地表达了意图(注册新用户)。
-
当然,创建对象和注册用户是两码事,但为什么要用
static方法呢? -
@Constantin Galbenu 有很多有价值的理由。见verraes.net/2014/06/named-constructors-in-php
-
客户端必须使用 register() 方法创建用户,这清楚地说明了意图。客户端这样做真的更清楚: User::register(...) 比做 $user = new User(....); $user->register() ...但更重要的是:通过使用静态工厂,我不仅限于一个构造函数。我可以有其他工厂以不同的方式创建用户,并发布不同的域事件。你为什么要准确地问?
标签: php domain-driven-design cqrs