ее пихать в сами классы моделей? Или это должно быть в сервис провайдерах, а объекты только выполняли функцию dto?
Мерси! Пошёл качать 🙂
Ну и постарайся не создавать божественные сервисы по 5000 строк кода.
Но тогда нужно вырезать валидацию, которая по сути бизнес-логика, и ты остаёшься с каким-то странным DataMapper.
Валидация валидации рознь. 1. Валидация на уровне полей БД. Например поле NOT NULL, всё что сгенерировал gii по схеме таблицы. Её можно оставить в модели AR, она там никому не мешает. 2. Правила бизнеса. Правила, нарушение которых говорит о том, что кто-то из разработчиков ошибся в коде. Например, мы пытаемся создать второй счёт для пользователя, а разрешено только один. Такие правила должны проверяться во всех юзкейсах. Пока всё лежит в сервисах, можно делать это в сервисах. При ошибке такие правила должны прерывать выполнение кода - бросать исключение. 3. Проверка пользовательского ввода. Мы должны проверить что данные введённые пользователем разрешены системой. Например, что пользователь ввёл корректный Email, что этот Email не занят другим пользователем. Подобные проверки нужны не для целостности, а для того чтобы дать полезную обратную связь пользователю. Поэтому их допустимо располагать в контроллерах. Проверяем поля формы, по полям с ошибками собираем массив сообщений и отдаём пользователю. Чтобы не захламлять контроллер, можно вынести код валидации в отдельные классы валидаторов, или сделать объекты команд, или упростить валидацию с помощью хелперов, в общем тут по вкусу, кому что нравится. В контроллере останется вызов валидатора. Поэтому не надо говорить что "валидация по сути бизнес-логика", это разные понятия и служат они разным целям.
Божественный сервис, кстати, обычно хорошо рефакторится. Вот когда часть намешана в контроллере, часть в AR, часть вообще во вьюхах, тогда приходится попотеть.
Вот смотри, если например у меня есть Entity котоя называется условно Customer. И есть от бизнеса правило, что скажем у Customer должно быть минимум 1 контактный адрес (почтовый), и 1 номер телефона. Не будет ли дурным тоном, если у Entity я сделаю публичный метод validate() который будет делать именно валидацию с точки зрения бизнес правил? Или же делать все эти проверки в сервисе, перед тем как сделать $repository->persist($customer)?
new Customer(Email $email, Phone $phone) - и не нужны методы
сущность не должна давать возможности удалять последний адрес и телефон, должна кидать исключение
это если уже существующая запись. А если новую добавляешь - нужно провалидировать что соблюдена вся логика бизнеса
ну так сущность невозможно создать без телефона и адреса. в конструкторе должно быть исключение, если такое произошло
Например, уникальность почты пользователя - это бизнес-требование, которое подкрепляется в коде и на уровне базы. Сложно отказаться от защиты от дурака, ведь надёжнее поставить проверку там, где её сложнее обойти. А это обычно либо валидация AR, либо сама база. А вот третий пункт довольно легко отделить и тут у тебя и код резко упрощается, и дополнительных рисков не появляется.
а поля приватные это must have? или можно использовать публичные, если не требуется над ними никакой магии?
уникальность тоже можно проверить, делаем метод в интерфейсе репозитория и проверяем
лучше геттеры/сеттеры пользовать. рефакторинг сильно проще делать. завтра могут появится какие-то условия для геттера или сеттера, а с публичным методом их уже не добавишь
Тут лучше делать как дедушка Вирт: у него на уровне языка всё непубличное и ненаследуемое пока сам не опубликуешь )
+ по умолчанию всё финальное и приватное, если не требуется иное
Если кратко, то поля публичные должны становиться тогда, когда это необходимо. В чистых сущностях, если инфраструктура отделена от бизнес-логики и есть модели для чтения и для записи, то эти поля не придётся делать публичными. В модели записи они будут приватными, а в модели чтения можно будет всё прочитать. Но это сложно для понимания новичку ) Если проще публичными делать, можно публичными, главное следить за тем чтобы сущность не выродилась в анемичную модель.
1. Тот кто закрепляет бизнес-правила "на уровне базы", тот сам себе роет яму. Просто ещё не знает об этом. 2. Если у тебя всё взаимодействие идёт через сервисы, и в контроллерах напрямую нет обращения к базе, то все проверки в сервисах вызовутся. Если какой-то разработчик это пытается нарушить, то для этого существует код ревью, либо проверка стат. анализатором.
Если я эту Entity буду отдавать клиенту в REST API - приватные поля же не сериализуются в XML или JSON
Для чтения просто делать Read Model простой, можно на AR или даже ещё проще что-то взять.
вот тут мы приходим к разделению моделей на чтение и запись
потом ты все равно столкнешься с форматированием дат, циклическими зависимостями etc, так что это не решение
1. Базючники ратуют за обратное: максимум ограничений целостности, начиная с внешних ключей и заканчивая check. Вред вседозволенности уже осознали и MongoDB, и PHP. Пресловутая проверка уникальности адекватно может работать только на уровне базы.
Это их просто никто не разносил в пух и прах аргументами )))) Да, я тоже когда-то был за такой подход. Но спустя 15 лет и кучу проектов уже понимаешь что это только мешает выполнять работу. На эту тему могу отдельную лекцию прочитать, но к сожалению в чате всё расписать времени нет.
Не стоит сущность отдавать как результат запроса. Сделай новый data class, куда закинешь нужные данные из этой сущности.
Надо разносить модель данных и бизнес-модель. Модель данных ясен пень, строится на основе бизнес-модели, но в отличие от нее не может быть изменена так легко. Если игнорировать вопрос консистентности модели данных, то посыпется бизнес-модель, основаннная на ней. Тут такая же история, как с обратно-совместимыми изменениями апишек. Если вдруг в качестве айдишника будет приходить нулл - мало никому не покажется.
Речь о другом, целостность данных по-хорошему должен гарантирован код. Не зная как надёжно гарантировать её в коде, многие разработчики спихивают эту задачу на базу, а потом рано или поздно огребают последствия.
база - тоже своего рода код 😅
Data-driven проектирование конечно накладывает отпечаток на мышление веб-разработчиков, но надо это перерастать )
Звучит как "не юзайте внешние ключи"
Обсуждают сегодня