如何解决创建值对象的最佳方法是什么?
我想知道如何以最好的方式创建值对象。
例如:
我有值对象密码
class Password
{
private string $password;
public function __construct(string $password)
{
$this->password = $password;
}
public function __toString(): string
{
return $this->password;
}
}
现在我想知道如何正确验证这一点。
VO 应该始终具有正确的值。由于创建对象,我应该验证传递的值吗?
例如:
class Password
{
private string $password;
public function __construct(string $password)
{
$this->validate($password);
$this->password = $password;
}
public function __toString(): string
{
return $this->password;
}
private function validate(string $password): void
{
if(!validation_rule)
{
throw new InvalidPasswordException();
}
}
}
还是我应该使用工厂?
class PasswordFactory implements PasswordFactoryInterface
{
private PasswordValidatorInterface $validator;
public function __construct(PasswordValidatorInterface $validator)
{
$this->validator = $validator;
}
public function createFromString(string $password): Password
{
$this->validator->validate($password);
return new Password(password_hash($password,PASSWORD_BCRYPT_DEFAULT_COST));
}
}
我的结论:
验证到期构造:
优势
- 我不会创建无效对象。
- 更少的代码。
缺点
- 我不能对外部验证器使用依赖注入。
工厂验证:
优势
缺点
- 如果有人不使用工厂,我允许创建无效对象。
- 更多代码。
我也考虑过将验证器传递给命名构造函数
class Password
{
private string $password;
private function __construct(string $password)
{
$this->password = $password;
}
public static function createValidated(string $password,PasswordValidatorInterface $validator): self
{
$validator->validate($password);
return new self($password);
}
}
解决方法
值对象应始终在有效状态下实例化。无论验证是什么,您都应该在构造函数内部进行验证。
现在,什么构成有效性完全取决于您的域以及您打算如何使用这些对象。
也许不是专注于完全验证的 Password
对象,而是创建一个 UnvalidatedPassword
对象。它可以在内部设置诸如“必须是字符串,至少 8 个字符”等基本验证规则。并将此对象传递给服务进行进一步检查。
另一个选项是您的 Password
对象持有一个标志,表明它是否已经过外部验证。同样,对象应该处于有效的状态,不必经过域逻辑的全面审查。 (两种选择都是可行的!)
而且,有时值对象只是包装值并为它们提供上下文的好方法。他们并不总是需要完美的内部验证。将您的 UnvalidatedPassword
发送到最终返回 ValidPassword
对象的服务是另一个完全可以接受的选项。
社区将其关闭为基于意见的做法是正确的;所有这些都是我的意见。但这是一个很酷的话题。 ?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。