Doctrine нарушает концепцию DDD?
Смотрела на сайте симфони пример применения доктрины:
/**
* @ORM\Entity(repositoryClass=ProductRepository::class)
*/
class Product {
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $name;
/**
* @ORM\Column(type="integer")
*/
private $price;
public function getId(): ?int {
return $this->id;
}
// ... getter and setter methods
}
В итоге получаем, что мы делаем маппинг сущности. Но ведь сущность в концепции DDD - это класс, который не должен никак зависеть или знать о внешних вещах, таких как фреймворки или БД. DDD специально для code first. А тут, в конечном итоге, получается сущность - отражение строки в БД.
Может быть я что-то не понимаю? Или конкретно эти сущности для маппинга и сущности доменного слоя - это разные вещи и описываются в разных местах? А как и где если например у меня есть такой класс в доменном слое:
Employee(
new Id(25), // value object
new \DateTimeImmutable(),
new Name('Пупкин', 'Василий', 'Петрович'), // value object
new Address('Россия', 'Липецкая обл.', 'г. Пушкин', 'ул. Ленина', 25), //value object
[
new Phone(7, '920', '00000001'), // value object
new Phone(7, '910', '00000002'),
]
);
Employee- одна таблицаAddress- другая таблицаPhone- третья таблица
Ответы (1 шт):
Symfony и Doctrine - универсальные инструменты и не предназначены специально для DDD. Тем не менее, благодаря их гибкости, их можно использовать для реализации DDD.
Что касается примера из документации, то обратите внимание, что привязка к базе указана в комментариях (в новых версиях в атрибутах), а не в коде. Т.е. никак не влияет на функционирование сущности, а лишь подсказывает слою инфраструктуры как ее сохранять. Если же хотите полностью убрать ее из сущности, можете вынести ее в отдельный конфигурационный файл - xml, yaml либо php.
В вашем примере value objects надо объявить как Embedded, вот так:
/**
* @Embeddable
*/
class Name
{
/**
* @ORM\Column(type="string", length=255)
*/
private $firstName;
...
}
class Employee
{
/**
* @var Name
*
* @Embedded(class = "App\ValueObject\Name", columnPrefix = "name_")
*/
private $name;
...
}
При этом все данные будут храниться в одной таблице.
Сложнее дело обстоит со списком телефонов. Для них все же придется использовать отдельную таблицу и связь один ко многим. При этом с точки зрения модели данных, номера телефонов будут выглядеть как сущности, но в модели домена это должны быть объекты-значения с невидимым для клиентов идентификатором.