创建值对象的最佳方法是什么?



我想知道如何以最好的方式创建值对象。

例如:

我有值对象Password

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));
}
}

我的结论:

结构验证:

  1. 我不会创建无效的对象。
  2. 更少的代码。

缺点

  1. 我不能对外部验证器使用依赖注入。

工厂验证:

  1. 我可以使用外部库来验证依赖注入。
  2. Imho易于测试。
  3. Hermetized操作。如果我必须更改构造函数,我将只更改工厂中的调用。

缺点

  1. 我允许创建一个无效的对象,如果有人不使用工厂。
  2. 更多代码。

我还考虑过将验证器传递给命名构造函数

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对象的服务是另一个完全可以接受的选项。

社区将此关闭为基于意见是正确的;所有这些都是我的观点。但这是一个很酷的话题。😎

相关内容

  • 没有找到相关文章

最新更新