Comments 5
Опять же, если мы применяем валидацию в контроллере, а в дальнейшем потребуется проводить ее из сервиса (например, не только из контроллера попадают данные, но и из команды), то что делаем? Выносим валидацию в адаптер, а в сервис передаем DTO?
А можно попросить разработчиков ларавеля не релизить так часто. Только переехал с 5 версии на 7, почитал документашку чтобы проапдейтитья на 9, а уже 11 вышла...
Самое интересное, что рекомендации для "Laravel разработчиков" из этой статьи являются вредными советами и признаками плохого кода для всех остальных PHP-разработчиков)))
Они вполне себе уместны, если мы пишем маленький хоумпейдж и действительно могут упростить работу, но тут же, цитата: "Для чистого, тестируемого и масштабируемого кода", т.е. с претензией на что-то более-менее серьёзное, так что...
Выполняйте проверку в классах запросов
Ну по-первых, стоит резделять слой представления (ну или иногда аппликейшн слой, если брать упрощённый вариант) от доменного слоя. При этом валидация должна находиться как в слое представления, специфичная для работы оного, так и в доменном слое, специфичная для работы оного.
Если чуть приближённо к реальности, то проверка запроса на статью должна отвечать за проверку данных запроса, а сервис создания статьи, проверять корректность данных в рамках своей предметной области. В частности, ArticleCreator::create(title, ...)
не должен допускать создания артиклов с пустыми заголовками по очевидным причинам.
Таймаут HTTP-запроса
Вы можете избежать ошибок при отправке HTTP-запросов из вашего контроллера...
Отправка HTTP запросов из контроллеров в принципе не допустимо. Т.к. задача контроллера - делегировать ответственность и просто быть прокладкой в слоях представления и доменным слоем, преобразуя данные из одного в другой и наоборот.
Используйте преимущества массовых назначений
...есть статический метод create из класса модели, который передает массив подтвержденных запросов следующим образом;
Это хорошо для Rapid, но только если мы говорим про, цитата, "чистого, тестируемого и масштабируемого кода", то соприкосновение HTTP с доменом напрямую в принципе невозможно.
Используйте Eloquent вместо Query Builder и необработанных SQL-запросов
Опять же, говоря о хорошем коде, Eloquent - это первое, что следует в принципе выпилить из проекта и забыть про него. Пояснять причины, думаю, не стоит? При этом как раз Query Builder вполне себе можно оставить и использовать, используя его в инфраструктуре (например в репозиториях) БД, возвращая на выходе уже Энтити/Модели.
Избегайте использования блоков комментариев к документации (DocBlocks)
Ээээ... Ну вообще-то статический анализ - вообще первое что ставится после фрейма. Мы же говорим о хорошем коде? А он обычно обмазан типизацией и всякими callable(T, class-string<Y>): ?int<0, max>
типами в докблоках. Так что побуду капитаном и замечу, что избавляться от них нужно когда они не нужны (дублируют код). А стремление удалять всегда и всюду - очередной вредный совет.
Да даже в примере Order
вполне себе может быть дженерик-типом, а сама функция подсчёта стоимости - чистой, так что:
/**
* @param Order<Product> $order
* @psalm-pure
*/
public function calculateTotalOrderCost(Order $order): float
{
Используйте стандартные инструменты Laravel
Увы, в подавляющем большинстве случаев они являются отличным решением для решения задачи "здесь и сейчас". В случае же масштабирования - скорее всего станут основной проблемой. У Laravel детская болезнь из полного игнорирования SOLID (в основном проблемы из-за "О") в угоду удобства использования и "быстрого запиливания Х решения парой кликов".
Используйте более короткий и читабельный синтаксис в коде
А вот за это надо сжигать на костре, тем более с таким примером. Функция-хелпер response
, например, вполне себе допустима, хоть и тоже является таким-себе решением, т.к. хотя бы является чистой и без каких-либо сайд эффектов. Фактически это фектори. Да, помним про буковку "I" из солида, но это не критичная ошибка. А вот session
... Помимо того, что это скрытая зависимость, помимо того, что оно завязано на глобальный контейнер, а ещё завязан на конкретное состояние (момент вызова) в этом контейнере, так ещё и создаёт дополнительные сайд эффекты, мутируя это самое глобальное состояние. Неужели так сложно просто воспользоваться DI? Зачем нужен контейнер, когда им не пользуются?
А как тестировать такое, когда неизвестно вообще где и как в коде оно будет вызываться? А если код вызвать из, например, какого-нибудь события вебсокет соединения? Как внедрить нормально свой сервис, чтобы на уровне HTTP-хендшейка сессия была классической, а в рамках последующего лайфцикла оно писало в память?
Сериализация моделей должна осуществляться с помощью ресурсов API Eloquent
Сериализация должна осуществляться с помощью логики сериализаторов, которые связаны непосредственно с местом представления, где оно используется. А желательно (настоятельно) помещать это всё в DTO, а потом уже сериализовывать.
В любом случае в роуте информации о юзере
GET /user
данные должны быть одни (полная информация), а в роуте получения спискаGET /user/list
- совершенно другие.Более того, отдача в HTTP через вполне себе может быть через json, а в случае какого-нибудь приложения - вполне себе можно использовать msgpack или protobuf для экономии трафика при нестабильном интернете.
Соблюдайте структуру каталогов Laravel. Это позволит вам легко находить и отлаживать ваше приложение.
Структура каталогов в ларке предполагает линейную структуру, которая довольно плохо масштабируется. Это отлично когда это простой круд на пару контроллеров. Для более сложных проектов люди давно придумали гексагональную архитектуру и нарезание проекта по доменам. О чём, собственно и намекают дальше, цитата: "Внедряйте модульность, разбивая большие приложения на более мелкие, управляемые модули, чтобы повысить ремонтопригодность и масштабируемость.".
Как бы тогда стоит определиться, или оставляем как есть или нарезаем? Что делать-то?
Проводите интеграционные тесты для проверки взаимодействия между различными частями вашего приложения, включая операции с базой данных, запросы к API и интеграцию внешних сервисов.
А почему интеграционные? А как же остальные? Функциональные, кажется, дольше всех живут и реже всех меняются. Так что в первую очередь стоит обратить внимание именно на них, будет хотя бы какое-то покрытие тестами. А остальное уже как получится, т.к. их придётся переписывать чаще всего.
Если подытоживать, то Laravel - отличный инструмент для быстрого решения "здесь и сейчас парой строк кода". А так же в принципе будет лучшим выбором для новичков, которые только хотят разобраться в фреймворках.
Однако надеяться на качественный и масштабируемый код в рамках ларки не стоит. Это не тот инструмент, который может его обеспечить. В принципе, пункты из статьи об этом и намекают -- это просто или вредные или очевидные советы, которых можно набрать хоть сотню, хоть тысячу, вида: "кешируйте результаты данных сложных запросов". Ну это же очевидно, кажется... А реально полезных советов для повышения качества в статье, увы, нет.
Лучшие практики Laravel для разработчиков в 2024 году