Ещё вопрос друзья: куда положить бизнес логику приложения? Стоит ли

ее пихать в сами классы моделей? Или это должно быть в сервис провайдерах, а объекты только выполняли функцию dto?

31 ответов

32 просмотра
Dmitriy-Gritsenko Автор вопроса

Мерси! Пошёл качать 🙂

Ну и постарайся не создавать божественные сервисы по 5000 строк кода.

Но тогда нужно вырезать валидацию, которая по сути бизнес-логика, и ты остаёшься с каким-то странным DataMapper.

Валидация валидации рознь. 1. Валидация на уровне полей БД. Например поле NOT NULL, всё что сгенерировал gii по схеме таблицы. Её можно оставить в модели AR, она там никому не мешает. 2. Правила бизнеса. Правила, нарушение которых говорит о том, что кто-то из разработчиков ошибся в коде. Например, мы пытаемся создать второй счёт для пользователя, а разрешено только один. Такие правила должны проверяться во всех юзкейсах. Пока всё лежит в сервисах, можно делать это в сервисах. При ошибке такие правила должны прерывать выполнение кода - бросать исключение. 3. Проверка пользовательского ввода. Мы должны проверить что данные введённые пользователем разрешены системой. Например, что пользователь ввёл корректный Email, что этот Email не занят другим пользователем. Подобные проверки нужны не для целостности, а для того чтобы дать полезную обратную связь пользователю. Поэтому их допустимо располагать в контроллерах. Проверяем поля формы, по полям с ошибками собираем массив сообщений и отдаём пользователю. Чтобы не захламлять контроллер, можно вынести код валидации в отдельные классы валидаторов, или сделать объекты команд, или упростить валидацию с помощью хелперов, в общем тут по вкусу, кому что нравится. В контроллере останется вызов валидатора. Поэтому не надо говорить что "валидация по сути бизнес-логика", это разные понятия и служат они разным целям.

Божественный сервис, кстати, обычно хорошо рефакторится. Вот когда часть намешана в контроллере, часть в AR, часть вообще во вьюхах, тогда приходится попотеть.

Dmitriy-Gritsenko Автор вопроса

Вот смотри, если например у меня есть Entity котоя называется условно Customer. И есть от бизнеса правило, что скажем у Customer должно быть минимум 1 контактный адрес (почтовый), и 1 номер телефона. Не будет ли дурным тоном, если у Entity я сделаю публичный метод validate() который будет делать именно валидацию с точки зрения бизнес правил? Или же делать все эти проверки в сервисе, перед тем как сделать $repository->persist($customer)?

new Customer(Email $email, Phone $phone) - и не нужны методы

сущность не должна давать возможности удалять последний адрес и телефон, должна кидать исключение

Dmitriy-Gritsenko Автор вопроса

это если уже существующая запись. А если новую добавляешь - нужно провалидировать что соблюдена вся логика бизнеса

ну так сущность невозможно создать без телефона и адреса. в конструкторе должно быть исключение, если такое произошло

Например, уникальность почты пользователя - это бизнес-требование, которое подкрепляется в коде и на уровне базы. Сложно отказаться от защиты от дурака, ведь надёжнее поставить проверку там, где её сложнее обойти. А это обычно либо валидация AR, либо сама база. А вот третий пункт довольно легко отделить и тут у тебя и код резко упрощается, и дополнительных рисков не появляется.

Dmitriy-Gritsenko Автор вопроса

а поля приватные это must have? или можно использовать публичные, если не требуется над ними никакой магии?

уникальность тоже можно проверить, делаем метод в интерфейсе репозитория и проверяем

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

Тут лучше делать как дедушка Вирт: у него на уровне языка всё непубличное и ненаследуемое пока сам не опубликуешь )

+ по умолчанию всё финальное и приватное, если не требуется иное

Если кратко, то поля публичные должны становиться тогда, когда это необходимо. В чистых сущностях, если инфраструктура отделена от бизнес-логики и есть модели для чтения и для записи, то эти поля не придётся делать публичными. В модели записи они будут приватными, а в модели чтения можно будет всё прочитать. Но это сложно для понимания новичку ) Если проще публичными делать, можно публичными, главное следить за тем чтобы сущность не выродилась в анемичную модель.

1. Тот кто закрепляет бизнес-правила "на уровне базы", тот сам себе роет яму. Просто ещё не знает об этом. 2. Если у тебя всё взаимодействие идёт через сервисы, и в контроллерах напрямую нет обращения к базе, то все проверки в сервисах вызовутся. Если какой-то разработчик это пытается нарушить, то для этого существует код ревью, либо проверка стат. анализатором.

Dmitriy-Gritsenko Автор вопроса

Если я эту Entity буду отдавать клиенту в REST API - приватные поля же не сериализуются в XML или JSON

Для чтения просто делать Read Model простой, можно на AR или даже ещё проще что-то взять.

вот тут мы приходим к разделению моделей на чтение и запись

потом ты все равно столкнешься с форматированием дат, циклическими зависимостями etc, так что это не решение

1. Базючники ратуют за обратное: максимум ограничений целостности, начиная с внешних ключей и заканчивая check. Вред вседозволенности уже осознали и MongoDB, и PHP. Пресловутая проверка уникальности адекватно может работать только на уровне базы.

Это их просто никто не разносил в пух и прах аргументами )))) Да, я тоже когда-то был за такой подход. Но спустя 15 лет и кучу проектов уже понимаешь что это только мешает выполнять работу. На эту тему могу отдельную лекцию прочитать, но к сожалению в чате всё расписать времени нет.

Не стоит сущность отдавать как результат запроса. Сделай новый data class, куда закинешь нужные данные из этой сущности.

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

Речь о другом, целостность данных по-хорошему должен гарантирован код. Не зная как надёжно гарантировать её в коде, многие разработчики спихивают эту задачу на базу, а потом рано или поздно огребают последствия.

база - тоже своего рода код 😅

Data-driven проектирование конечно накладывает отпечаток на мышление веб-разработчиков, но надо это перерастать )

Звучит как "не юзайте внешние ключи"

Похожие вопросы

Обсуждают сегодня

Добрый вечер, Пока не совсем понимаю как наладить общение между телеграм ботом и ПО для работы с сим боксом. По самому боту так понял: - Нужен некий баланс, который можно поп...
Magic
6
сделал сайт, прикрутил в боте сайт, и виджет логина. как автоматически логинить пользователя в аккаунт(телеграм), при входе с бота?
Александра Чернивецкая
5
Объясните, пожалуйста, почему компилятор ругается на использование в условии неинициализированной переменной: int x; Task.Run(async () => { x = await somefunc(); }).Wait...
Александр
5
Ребят, подскажите, пожалуйста, почему в префиксе к ассетам, которые генерируются через фильтр | theme в шаблоне, стал вдруг появляться index.php? Вот так выглядит ссылка на а...
Виталий
1
Всем привет. Ребята, подскажите, пожалуйста. у ботов есть ограничение на отправку сообщений - 30 сообщений в секунду, эти ограничения накладываются на все сообщения? или на со...
Artem Stormageddon
4
Блин, ребята, сори за тупые вопросы. А можно ли как-то открыть вебапку по нажатию на кнопку в меню(которое появляется слева, команды)?
Artem Stormageddon
3
а плаксы из-под питона умеют только в комфортных условиях что-то выдавить из себя?)
Lencore
9
Но, может, есть уже проверенная? Наши требования такие: 1. Сообщения должны приходить из Инста в CRM оду 2. Должна быть возможность подключить несколько экаунтов Инстаграм. Р...
Alexander Sharoiko MSE / Александр Шаройко
13
Это может быть все-таки не флудвейт? у меня ботфазер принимает изменения и отображает даже что они изменились, на видео видно что он прислал якобы уже измененное описание, н...
OVERLINK
13
Коллеги, может знает кто, можно ли цвет бейджа счётчика в BackendMenu менять без бубнов?
Alex Blaze
3
Карта сайта