Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Чим сутність (entity) відрізняється від об'єкта-значення (value object)?

Сутність має ідентичність, що зберігається протягом усього життя: користувач лишається тим самим користувачем, навіть якщо змінив ім'я, email і адресу. Дві сутності з однаковими полями, але різними id - різні об'єкти.

Об'єкт-значення не має ідентичності - він визначається лише своїми значеннями. Дві суми «100 гривень» - одна й та сама сума; немає сенсу питати «яка саме з них».

Сутність Об'єкт-значення
рівність за ідентифікатором за всіма значеннями
зміна змінюється з часом незмінний: «зміна» = новий об'єкт
приклади User, Order, Invoice Money, Email, Address, DateRange

Об'єкт-значення в PHP:

final readonly class Money
{
    public function __construct(
        public int $amount,          // у копійках
        public string $currency,
    ) {
        if ($amount < 0) {
            throw new InvalidArgumentException('Сума не може бути від\'ємною');
        }
    }

    public function add(Money $other): self
    {
        if ($other->currency !== $this->currency) {
            throw new InvalidArgumentException('Різні валюти');
        }

        return new self($this->amount + $other->amount, $this->currency);
    }

    public function equals(Money $other): bool
    {
        return $this->amount === $other->amount && $this->currency === $other->currency;
    }
}

Що дають об'єкти-значення:

  • валідація в одному місці: некоректний Email чи від'ємну суму неможливо створити - не треба перевіряти скрізь, де вони використовуються;
  • поведінка поруч з даними: додавання грошей, перевірка перетину періодів;
  • незмінність (readonly) - об'єкт можна безпечно передавати й кешувати;
  • виразність: function charge(Money $amount) замість function charge(int $amount, string $currency).

У Laravel об'єкти-значення зберігають у моделях через власні касти (CastsAttributes): Money з двох колонок price_amount і price_currency.

Пастка: робити сутністю те, що насправді значення (окрема таблиця addresses з id для адреси, яка ніколи не існує окремо від замовлення), - і навпаки.

Докладніше в документації: Martin Fowler: Value Object

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання