[Doctrine] BEST PRACTICES - 1

Замечательный человек Marco Pivetta, который больше известен под ником Ocramius и который участвует в развитии Doctrine ORM, составил презентацию, в которой описал лучшие практики, которых следует придерживаться при работе с Doctrine.

вот ссыль

На официальном сайте Doctrine так же присутствует раздел, под названием Best practices , но он очень мал.

1. Общие правила.

Как правильно при первом знакомстве с Doctrine все сущности, которые мы создаем являются по сути обычными POCO объектами , которые на каждое свойство имеют по get\set методу и не имеют конкретного поведения.

"Сущности должны работать без ORM", означает то, что вы должны абстрагировать ваши сущности от логики ORM, т.е. если вы вдруг захотите сменить Doctrine на Propel, вам не пришлось бы менять код в бизнес-логике. Однако тут возникают ограничения, накладываемые ORM, например коллекции в Doctrine - "ArrayCollection" которые используются внутри сущностей, для работы со связями.

"Сущности должны работать без БД" - пункт, который в принципе и так исполняем, так как вся логика работы с БД у нас инкапсулируется в самой ORM. Исключение составляет разве, что Active Record сущности с sql внутри.

"Сущности являются отображением доменной логики вашего приложения" - доменная логика - это часть подхода в DDD методологии, сформулированной Эвансом. Соответственно, ваши сущности не должны быть пустыми болванками, с двумя методами на свойство. Ваши сущности, в первую очередь, должны обладать поведением.

При проектировании вашего приложения, рекомендуется пользоваться code-first подходом,  когда вы сперва проектируете ваши сущности и взаимодействие между ними, а после уже занимаетесь проектированием хранилища и тем, каким образом помещать в него данные. В ходе работы может появиться необходимость в нескольких базах данных, или в разделении хранилищ с хранением различных кусков данных единой сущности. В итоге ваши сущности не должно волновать, каким образом вы организуете персистентный слой, ваши сущности должны быть заняты бизнес логикой приложения.

2. Придайте Entity осмысленности.

Типичная сущность:

[Doctrine] BEST PRACTICES - 1 PHP, Doctrine, Orm, Длиннопост

При таком подходе наша Entity напоминает больше ассоциативный массив, нежели полноценный объект. Чтобы решить эту проблему, данному классу нужно придать немного больше информативности:

[Doctrine] BEST PRACTICES - 1 PHP, Doctrine, Orm, Длиннопост

Таким образом мы придали сущности более осмысленное, в рамках доменной логики, поведение, а так же защитили его от неконтролируемых изменений. Начинайте проектировать свои сущности на уровне интерфейса, так вы сможете абстрагироваться от детализации и сосредоточиться над общей структурой ваших сущностей и их взаимодействия.

3. Инкапсулируйте взаимодействие с коллекцией внутри Entity.

Если ваша сущность имеет внутри себя коллекцию зависимых объектов, с которыми вы хотите работать, то лучшим образом это будет делать через сам класс сущности, вместо того, чтобы выносить коллекции из сущности куда-то еще.

[Doctrine] BEST PRACTICES - 1 PHP, Doctrine, Orm, Длиннопост

Такой подход является следствием создания сущностей-болванок, по этому оптимальным вариантом будет некоторые операции размещать внутри методов самой сущности. В данном случае - CRUD операции с коллекциями.

[Doctrine] BEST PRACTICES - 1 PHP, Doctrine, Orm, Длиннопост

Конечно в простых примерах взаимодействие с коллекциями кажется таким же простым. Однако в реальном приложении на сцену выходит множество факторов и внешних зависимостей, и данную логику часто приходится размещать, как раз-таки, во внешних сервисах бизнес уровня приложения.

4.Ваши сущности всегда должны находится в валидном состоянии.

Как касательно самих типов данных, чтобы в поле для целого значения не прилетела строка, например, так и касательно самих бизнес-правил, чтобы email был валидным, а пароль не меньше 3 и т.д. Вы должны всегда доверять сущности и быть в ней уверены. Однако не следует помещать в методы сущности комплексные валидационные правила, которые работают с данными пользователя. У вас всегда должны быть слои взаимодействия. Валидацию самой пользовательской формы отдавайте валидаторам - это может быть сервис, или input-фильтры, как в ZF2, или формы, как в SF2, или любые другие инструменты.

5.Используйте конструктор.

Это правильно тоже касается валидации. Ваши сущности не должны существовать без жизненноважных зависимостей. Например: профиль пользователя не может существовать без самого пользователя, по этому нужно запретить создание профиля, без передачи ему в конструктор сущности User. Если посмотреть с другой стороны, то очевидно, что при создании пользователя желательно создавать и профиль для него, это можно сделать в конструкторе сущности User, тем самым обеспечить их связь на этапе создания, без лишних телодвижений с сеттерами и проверками на существование.

6. Не рекомендуется использовать классы из уровня выше, в классах, уровня ниже.

Т.е. не желательно использовать в сущностях - сервисы, репозитории и другие классы, которые для своей работы сами используют сущности и соответственно находятся уровнем выше над ними.

Программирование на PHP

59 постов2K подписчика

Добавить пост

Правила сообщества

- запрещено добавлять посты отличной от мира программирования тематики (так как пикабу - это в первую очередь развлекательный ресурс, то посты с юмором, историями, изображениями и всем, что связано с php - разрешены);

- запрещено добавлять посты с содержанием в виде вопроса, или просьбы о помощи, для этого есть тематические ресурсы;

- запрещено добавлять посты провакационной тематики, нацеленные на бессмысленные споры и оскарбления;

- в копипастах и переводах указывайте источники;

Автор поста оценил этот комментарий

Вопрос. Зачем в User#authenticate вместе с аутентификацией происходит авторизация, что противоречит названию метода?

Автор поста оценил этот комментарий

все отлично, хороший ман, какая сложность, вы о чем?

Автор поста оценил этот комментарий

Автор или противоречит сам себе или незадумываясь копипастит из чужой доки.

"все сущности, которые мы создаем являются по сути обычными POCO объектами , которые на каждое свойство имеют по get\set методу и не имеют конкретного поведения."(с)

""Сущности являются отображением доменной логики вашего приложения" - доменная логика - это часть подхода в DDD методологии, сформулированной Эвансом. Соответственно, ваши сущности не должны быть пустыми болванками, с двумя методами на свойство. Ваши сущности, в первую очередь, должны обладать поведением. "(с)

"$user = $this->repository ..." Во-первых, откуда там repository взялся? А во-вторых, зачем тогда писать такое:

"6. Не рекомендуется использовать классы из уровня выше, в классах, уровня ниже.


Т.е. не желательно использовать в сущностях - сервисы, репозитории и другие классы, которые для своей работы сами используют сущности и соответственно находятся уровнем выше над ними."(с)

Автор поста оценил этот комментарий

ORM говно, тормознутая дополнительная степень абстракции. Нет ничего лучше и быстрее чистых sql запросов, не говоря уже о сложности реализации orm запросов, то что на sql можно в 10 строк сложный запрос записать, через orm это 50 строк.

Автор поста оценил этот комментарий

Чет это как-то для сильно профи. Нужно что-нибудь попроще, я думаю в сообщество очень много новичков.

раскрыть ветку