Retour au code
PHPDDD

Les objets valeur plutôt que l'obsession primitive

Un string $email peut contenir "not-an-email" jusque dans votre base de données. Le système de types ne ment pas - il ne dit simplement pas la vérité dont vous avez besoin.

Mauvais - l'invariant ne vit nulle part

final class RegisterUser
{
    public function __construct(
        private readonly UserRepository $users,
    ) {}

    public function handle(string $email, string $password): void
    {
        if (!str_contains($email, '@')) {
            throw new InvalidArgumentException('Invalid email');
        }

        $this->users->save(new User($email, $password));
    }
}

Le contrôle est correct aujourd'hui. Il doit aussi être mémorisé, et réimplémenté, partout où une adresse email entre dans le système - un second cas d'usage, un script d'import admin, une commande console. En oublier un et l'invariant disparaît.

Bon - l'invariant est le type

final class EmailAddress
{
    private function __construct(private readonly string $value) {}

    public static function fromString(string $value): self
    {
        if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
            throw new InvalidEmailAddress($value);
        }

        return new self($value);
    }

    public function __toString(): string
    {
        return $this->value;
    }
}

final class RegisterUser
{
    public function __construct(
        private readonly UserRepository $users,
    ) {}

    public function handle(EmailAddress $email, Password $password): void
    {
        $this->users->save(new User($email, $password));
    }
}

EmailAddress ne peut pas exister dans un état invalide - la construction est la validation. Chaque point d'appel en aval, y compris ceux écrits dans six mois par quelqu'un qui n'a pas lu ce fichier, obtient la garantie gratuitement.

Le compromis : plus de classes, plus de cérémonie pour ce qui ressemble à une chaîne de caractères. Ça vaut le coup exactement là où l'invariant est critique pour le métier, pas pour chaque champ de chaque formulaire.