たとえば、フォーマット規則を持つユーザー名の値オブジェクトがあるとします。
_class Username
{
private $username;
public function __construct(string $username)
{
// thrown an exception if invalid regex ^[a-zA-Z0-9]+$
// ...
$this->username = $username;
}
}
_
上記のように、通常は「外部」から生の文字列を渡してユーザー名を検証します。
私の質問は、値オブジェクトは、たとえば、ユーザー名を生成するなど、独自の値を生成するような「追加機能」を持つことができるかということです。例えば。、
_class Username
{
private $username;
// original __constuct() remains here
// ...
public function generateUsername(UserRepository $userRepository): self
{
$username = $this->generateRandomUsername();
if (!$userRepository->userExist($username))
return new self($username);
}
}
_
例はアイデアの簡単な疑似コードですが、アイデアはgenerateUsername()
で、クラス内から新しく生成されたユーザー名がまだデータベースに存在しないかどうかを検証するためにUserRepository
を使用します。
値オブジェクトは、このような機能を持つことができますか、それとも、「外部」からの入力を受け入れて検証する最初の例のように動作する必要がありますか?
値オブジェクトは独自の値を作成できますか?
はい、特に以前のモデルとの下位互換性が必要な複合値の場合は、そうすることは珍しくありません。
public function generateUsername(UserRepository $userRepository): self
{
$username = $this->generateRandomUsername();
if (!$userRepository->userExist($username))
return new self($username);
}
それは少し変です。最も注目すべきは、通常はリポジトリをドメインモデルに渡さないことと、乱数が通常は入力(時間など)であることです。
さらに、一意性は「セット検証」の特殊なケースです。リポジトリがリレーショナルデータベースによってサポートされている場合は管理できますが、一般的には、集約の検索に使用されるキー以外の一意性を適用しようとすると複雑になります。