Дмитрий, хочу выразить тебе огромную благодарность. По твоим видео, я научился работать с Laravel, и нашел работу, став разработчиком на Laravel, Vue, прошел после первого собеседования. У тебя лучшие видео на RUclips.
Я к такой архитектуре в голове пришёл с пол года назад и после её внедрения на практике сразу отказался. (для лары) 1. Если ты работаешь с ларой - ты работаешь с ларой. Что такое лара? Быстро поднять приложение легкой и средней сложности. Ключевое слово быстро, т.е. дешево. 2. Большинство ларавель программистов не ахти развиты в архитектуре(имхо). Просто потому что лара не заставляет думать. Это такая фишка фреймворка. И каждый новый прогер на проекте будет страдать. А вместе с ним страдать и ревьюверы, пытаясь донести ему где пахнет. 3. Ларавель такой монолитный фреймворк, что выпилив из него всю магию моделей ты превращаешь его в симфони. Тогда вопрос, почему бы сразу не писать на симфони, который чище на порядок? 4. Пакеты лары жёстко завязаны на модели и писать свои обработчики нарушает п.1 К примеру, аутентификация дергает пользователя, т.е. работает с моделью напрямую. Это уже нарушение архитектуры. Это можно обойти, но тогда юзера надо хранить как ДТО. Окей, храним как дто. Как мы будем писать политики? Никак. Окей, пишем свои политики. Как мы будем слушать события модели? Никак. Окей, пишем свои события, пишем команды и приближаемся к cqrs. И так далее. Суть ясна. 5. Шансы что когда-то проект на ларе дорастет до того чтобы самовыпилит лару невероятно низок. Поэтому закладывать на старте лара проекта то что ты будешь переобувать орм в дальнейшем сильно нарушает п.1 В общем, итого моего решения после всех раздумий: 1. Никогда не писать логику в моделях 2. Использовать модели только для релейшенов 3. Сложные запросы дергать репозиторием, простые в 2 строчки напрямую с модели(т.к. она уже и есть репозиторий и в этом сама ирония паттерна репозиториев для лары) 4. Не имеет никакого смысла создавать дто той же самой структуры что и модель, если ты делаешь с дто тоже самое что и с моделью. 5. Если руки прям горят в архитектуру - ставить симфони. 6. Если когда-то захотелось выпилить из своего проекта лару или симфони - то увы, в реалиях пхп это невозможно. Я больше поверю в то что рядом будет переписаны сервисы на другом языке или фреймворке чем то, что вы сможете безболезненно разобрать фреймворк из приложения. Я пытался. Честно) Чтобы отделить приложуху от фреймворка понадобится невероятно огромное количество прокси классов. И это не имеет никакого смысла для бизнеса. В чём мораль басни: Прежде чем отступать от канонов фреймворка - 10 раз подумайте, а поймёт ли вас коллега, который сядет писать через год. Или другая студия, которая возьмёт проект после вас. Или другая команда. PS чистая архитектура в грязном фреймворке - это очень мило. Как фотка парня в смокинге по пояс в болоте) Отнимите у типового разработчика ларавель возможность дёргать сервис контейнер по любому поводу и он сразу поплывёт. А создавать объекты из сервиса контейнера посреди кода - это лютейший антипаттерн, если что) Единственное место где одобряют его применение - контроллер. Что юзают в симфони. В остальных же местах можно и по рукам получить от ревьюверов.
Архитектура не зависит от фреймворка. То что в видео касается любого фреймворка, лара как деталь для примера. Отвязывать все приложение от фреймворка это сложно всегда и в любом фреймворке и на любом языке. Но стараться избавляться бизнес-логику от фреймворка можно и нужно. Например зачем фреймворку быть в классах расчета зп?
Микросервисы сейчас активно пидалируются разными образовательными центрами (была недавно волна рекламы в инсте). Полагаю мода. Далеко не всегда они нужны. И поддержка их тоже не так проста. Как по мне, так лучше рядовому разработчику порокачиваться в чистом коде и архитектурах, чем умея только писать говнокод лезть в микросервисы. А внутри микросервисов создавать годКлассы, пропускать реквесты в бизнеслогику и тп.
ты прав во многом, но в моделях лучше не писать свою говно логику. Мне кажется создать Репозиторий самое простое что можно сделать а так лично я использую для средних проектов Фасад - Сервис провайдер - Сервис контейнер - Репозиторий. Вообще для мелких проектов можно только репозиторий юзать поверх модели и все так как смысла нет от всей пидантичности
1. Никогда не писать логику в моделях - "сколько еще открытий чудных...". Вы пришли к анемичной модели, осталось обратно вернуться к рич модели. Пару легаси проектов с "Никогда не писать логику в моделях", а с логикой в сервисах изменят ваше мнение.
На последок напишу, что очень комфортно смотреть твой канал)) Чувствуется 100% знание материала и уверенность. Щепотка юмора и харизмы в самую точку)) Смотреть не наскучивает, это как читать интересную книгу. На рабочих проектах использую твои идеи, начиная с паттернов проектирования, заканчивая архитектурой Porto. После этого видео, я предложу тимлиду использовать именно этот способ получения данных. Буду это аргументировать плюсами из видео или просто скину ему этот ролик. Подписан на тебя с курса по Laravel и буду продолжать тебя смотреть даже после возможной блокировки ютуба. Надеюсь ты продолжишь радовать нас новыми видео. PS. На телеграм канал подписался)
тоже хотел увидеть , слышал только про один реальный проект, там тоже от базы до вью было куча слоев ,проект простой но тормозил жутко. И в разработке не все так гладко.
Большое спасибо за видео. Согласен на все 100%. Единственный комментарий, это на счет сложности. При вводе дополнительных прослоек возрастает сложность структуры, а не просто сложность... Сложность, вот просто сложность. Это всетаки сложность решения задачи, которая превращается в сложность разработки и подержки, тоесть в технический долг. И очень часто усложнение структуры в конечном счете уменьшают сложность разработки и сложность поддержки. Частично именно за это мы и любим фреймворки. За некие правила, которые один раз осознав и выучив, ты перестаешь ходить по граблям. Лично я давно живу с дополнительным слоем возвращающем структуры. Т.к. это упращает логику работы с данными на порядок. Всегда удобней в контроллере получить чистые данные, и работать с ними, а не странный объект, который возможно поменяется.
Дмитрий, классный видос. Очень хотелось бы глянуть на практическое применение этих подходов (точнее последний, я думаю, все пользуются первыми двумя 😊), интуитивно понятно, но все же. Очень хотелось бы увидеть применение! В целом, спасибо тебе за твой труд - очень важные вещи рассказываешь!!!
Дмитрий, в случае с Doctrine - это data mapper, взгляни на эту идею с той стороны, что никакой бд нет, сохраняем в памяти или файлах. Придет понимание, что "не писать логику в моделях" - нарушает основной принцип - мы не используем логику там, где хранятся данные. Информационный эксперт (Information Expert) - основной принцип Grasp гласит: информационным экспертомявляется объект, обладающий максимумом информацией, необходимой для выполнения назначенных обязанностей. Логика обработки данных должна находится в в том объекте, где есть максимум данных для ее обработки. Причем тут бд - непонятно. Но сразу видет подход ларавельщика с table gateway.
Не понятен комментарий. Похож на нападку и в конце с принежением ценности личности "сразу виден подход ларавельщика table gateway". Как будто контекст остался у вас в голове. Вы пытаетесь сказать что логику в модели писать это правильно? ибо Grasp? Про table gateway тоже не понятно. Это про тот gateway о котором я говорил в видео? Не знал что Роберт Мартин ларавельщик... Интересно он сам знает об этом? Подобное разделение ответственности впервые узнал от Мартина.
Вольный перевод статьи Фаулера anemic model Действительно, часто эти модели поставляются с правилами проектирования, в которых говорится, что вы не должны помещать какую-либо логику предметной области в объекты предметной области. Вместо этого существует набор сервисных объектов, которые захватывают всю логику предметной области, выполняя все вычисления и обновляя объекты модели результатами. Эти сервисы работают поверх модели предметной области и используют модель предметной области для данных. Фундаментальный ужас этого анти-шаблона заключается в том, что он настолько противоречит основной идее объектно-ориентированного проектирования; который должен объединять данные и обрабатывать вместе. Анемичная модель предметной области на самом деле представляет собой всего лишь процедурный дизайн, именно с этим объектные фанатики вроде меня (и Эрика) борются с первых дней существовани
Делайте, делайте все в моделях. Как вам будет угодно. И расчет зп помещайте в модель и все остальное. И обязательно об этом рассказывайте на собеседованиях.
@@DmitryAfanasyev так смысл же не в том, что бы делать все по шаблону (table gateway или ddd) всегда и везде, а в том, когда можно сэкономить и лупануть anemic model. И когда нельзя сэкономить - сделать rich domain с es и чем-нибудь еще)) и да, order может посчитать в этом случае свою цену(правда многое от контекста зависит и бл). Причем заметил такую фичу что если по ddd делать(в силу своих знаний и понимания темы), то юнит тесты очень репрезентативно показывают факапы. В то время как с table gateway подходом все немного сложнее в этом плане.
Спасибо за видео! Надеюсь, в будущем будет видео: "все это время ты использовал laravel неправильно, создаем абстракцию для всего фреймворка сразу" )))
Дмитрий, ты в начале упомянул, что многие люди выбрасывают из ларавелла Eloquent и ставят Doctrine. Это делается как раз для решения проблемы принадлежности сущностей к слою БД. В доктрине сущности предполагаются независящими от ОРМ, они по коду - часть чистой бизнес логики и ОРМ-овские аннотации в них нужны только репкам доктрины для рефлексии. Такой подход позволяет избежать костылей в виде гейтвеев и презентаторов и разбивать модель на более внятные архитектурные слои. Собственно, одна из хороших практик в симфони - сначала полностью описать бизнес-модель и только потом приделать к ней ОРМ, добавив конфиги в аннотациях или ямле. За ролик - лайк и спасибо. Надо будет поближе познакомиться с ларавеллем - уже если там есть такие проблемы, то наверняка есть и преимущества )
Да, я всю доку проштудировал по доктрине чтобы не попасть в просак (так как боевого опыта с доктриной не имел). И всё же пришел к выводу что таки да, не надо выпускать куски доктрины из слоя БД.
Если исходить из логики чистой архитектуре . То ORM это слой деталей а модель как enitty в центре и нельзя делать зависимость от деталей так что можно спокойно сказать это ошибочное мнение так делать на doctrine. В центре всего должны быть наши сущности для бизнеса а не ORM модели хоть и они удобны как аггрегаты с коробки
Спасибо большое за Ваши видео, Дмитрий, я стал меньше говнокодить, а так же благодаря Вам я улучшил свои навыки работы с Laravel. Всегда жду Ваших видео!!! Успехов!
в ларавеле модель - это вообще не модель в общепринятом понимании, а какой-то сам себе репозиторий и дто, какой-то кусок ОРМ, торчащий наружу, но ни как не "модель" модель должна моделировать предметную область при помощи данных и поведения, основанного на бизнес-правилах и вообще не должна знать о бд и самом приложении. Можно сделать ее богатой (ордер, который считает цену - это НЕ антипаттерн). Можно анемичной (антипаттерн по Фаулеру и Эвансу), разделив данные и поведение, положив его в доменные сервисы. Почти везде сейчас анемичная модель т.к нужная меньшая квалификация разработчиков
Что-то из раздела чистой архитектуры) Таким способом стоит попробовать сделать хотя бы один проект или хотя бы компонент, чтобы потом понимать где это лучше использовать а где нет.
Пару вопросов 1) Ты не раз ссылался на presenter это что такое? я нашёл только вот такую реализацию pdavidhemphill/presenter ну как я понял это обычная обвёртка над моделями она позволяет логику с моделей выкинуть в функционал это-го пакета . 2) Есть в laravel метод toBase() как мне его использовать со связями заезженный пример есть пользователи а них есть роли в обычном случае поступил бы вот так User::select(['id', 'name'])->with(['roles:id,name'])->limit(10)->paginate(10) всё ок а если я хочу получить не модельки а stdClsss то мне выплёвывает только юзера мне что теперь отказаться от связей и писать через join? Только не бей меня я ещё новичок в этом деле Пожелание можешь записать подробное видео или мини проект тяжеловесный с использованием вот это-го подхода?
Дмитрий, скажите пожалуйста, сколько вам нужно задонатить, чтобы ты записал курс по swoole(многопоточность, корутины, таблицы, сокет сервер и тд)?. Просто очень крутая китайская штука, решила многие проблемы с производительностью на проекте. Использовал на ощупь, не разобравшись. Хотелось бы поподробнее разобраться.
На самом деле если для какого то рассчета никаких внешних механизмов не требуется, то можно и моделью это посчитать и презентовать. Ну это только если, допустим, у модели атрибут А умножить на атрибут Б. Мы, конечно, можем не понять при первом знакомстве с проектом, что реальный прайс считается через GetOrderPrice, т.к. он висит где то отдельно, но это же самое и дает нам возможность изменить провайдера курса валюты или добавить интернацианализацию при перерассчете
Есть такой вопрос. Допустим есть абстрактный метод show (Получение статьи по ID), который получает модель в параметр с помощью сервис-контейнера. По логике из урока передавать эту модель таким образом не вариант: return view('template', ['model' => $model]); Тогда получается то, что нужно будет перед тем как передать в шаблон данные, предварительно прогнать эту модель в Presentator и уже в шаблон вернуть stdClass. $data = $this->presentator->model($model); return view('template', ['data' => $data]); Верно ли я понял?
Еще 1 вопрос. У меня на проекте не планируется менять ORM, нужно ли мне тогда использовать Gateway? Если нет то должна получиться схема: ORM - > REPOSITORY -> PRESENTATOR
Я веб-программист с опытом работы больше 15 лет, занимал должности и тимлида и техлида. Хотелось бы высказать своё мнение, касательно темы этого видео. Если программист начинает разработку без моделирования, то это очень, очень плохо. А если программист ещё изначально пишет код, который нуждается в рефакторинге - ещё хуже. Да, нужно понимать, что 80% времени программист исправляет ошибки в коде, свои или чужие, но если при разработке нового функционала не происходит хотя бы незначительные потуги в UML, то этот код через незначительное время придётся дебажить уже другому программисту. Вывод, рисуйте диаграммы и большая часть проблем решится в самом начале, а кодирование - это самая простая часть инженерии. На эту тему можно почитать С. Макконнелла "Совершенный код".
Есть разные подходы. Вы описываете Предварительное проектирование. А есть еще и Эволюционное. Так же не понятно как ваш коммент относится к теме видео...
Вопрос: если репозитории служат только для выборок данных, а напрямую обращаться к модели не следует в сервисах то какой слой использовать для Create, Update, Delete операций?
Спасибо Дмитрию за его подачу информации! Вопрос по репозиторию. В нем можно только операцию по чтению проводить или полный CRUD. И если только чтение то где совершать остальное ? Заранее спасибо.
Можно по разному. 1) Сам процесс сохранения идет в репозитории, который используется в отдельном классе, например UpdateUserTask($userData). Класс готовит данные, отправляет в репозиторий и репозиторий делает только save() без какой- либо логики. 2) Если нет идеи абстрагироваться от ОРМ, и репозиторий сожержит методы типа "ДаймМне10ПользователейКоторыеОтписалисьОтРассылки" то save можно вызвать у модели в UpdateUserTask 3) Есть практика когда делают 2 репозитория на одну сущность -1) Репозиторий только на выдачу 2) Репозиторий только на сохранение. Главное не помещать логику сохранения, а она может быть очень сложной, в сам репозиторий.
Дмитрий, добрый день! Выражаю огромную признательность вам за труд! Я почерпнул для себя массу нового и дошел до многих разных вещей! Прошу помощи разобраться с одной штукой, с которой давно хочу разобраться. Пересмотрел, пожалуй, все ваши видео тут на канале, если где-то об этом уже сказано, то, вероятно пропустил, и буду признателен за ссылку. Тема такая. Что такое "бизнес-логика"? Что вы понимаете под этим по сути? Тут кроме самого определения мне очень интересно разобраться - где же она должна быть? В каком слое приложения? Вы постоянно говорите, что контроллер должен быть тонким (совершенно согласен), что модели не должны содержать бизнес-логики (согласен), в билдерах, мостах, прокси, дто и т.д. ей тоже не место, так куда же ее выносить? Если следовать Porto, то - в таски? Тогда подвопрос: таски могут обращаться друг к другу, но само по себе обращение - это ведь тоже логическая связь, подчиненная каким-то законам бизнеса? К таскам можно обращаться из тасков другого модуля или контейнера, или из "акшонов", тогда получается размазывание бизнес-логики? А если не следовать Porto? Буду признателен за комментарий к моему вопросу.
Дмитрий, сделайте пожалуйста урок по AWS S3, (всё же это best practise по хранению файлов на сервере) документация достаточно бедная на эту тему, особенно что касается использования загруженных файлов. Спасибо :)
Вы рассматриваете всё это только в разрезе паттерна ActiveRecord, Doctrine использует паттерн DataMapper который как раз возвращает чистый объект который сам разработчик может наделить бизнес логикой. И как мне кажется не вся бизнес логика должна быть вынесена из модели, если эта логика зависит только от бизнес модели и не обращается к бд и внешним сервисам. По вашей логике модель это просто массив с полями.
@@DmitryAfanasyev Я правильно понимаю, что получится анимичная модель? И если у нас есть связь 1:м или 1:1 мы явно сделаем 2 вызова, то есть обратимся за моделью, а потом за связанными моделями? И если можно ещё вопрос как вы решаете транзакционное сохранение данных в бд?
@@DmitryAfanasyev В доктрине получив модель мы можем обратится к полю которое является коллекцией, внутри произойдёт магия и запрос в бд и вернётся коллекция моделей, если я правильно понял вашу идею с stdClass, то внутри он содержит только поля и не содержит никаких магических эффектов и коллекций, или это не так и модель может содержать вложенные коллекцию ?
Идея не моя, а Роберта Мартина, об этом я написал в описании к видео. На выходе мы должны получить - примитив. Простую структуру данных. Не вижу ничего страшного если некое отношение превратится из модели так же в примитив. Суть в том что нам для работы от БД нужны данные, не более. Не механики расчёта зп, цен и тп. Данные нужны. Вот и получаем данные.
Спасибо за ролик. Подскажите, пожалуйста, и в уроках по ларе, и тут речь ведется о селектах. Хорошо, я договариваюсь в проекте работать с моделями в особом слое, где на самом нижнем уровне конкретная ОРМ, а перед ней репозитории, гетвэи и презентаторы, на выходе получаю структуру данных, тут всё понятно. А как в такой схеме будет выглядеть вставка и обновление модели? Какие сущности в этом слое будут отвечать за эти процессы, может кто-то доступно объяснить? По схеме получается, что это ответственность репозитория или я не прав?
Спасибо большое за познавательный урок, вопрос, будет ли пример реализации этого подхода в виде кода. Очень интересно посмотреть именно вашу реализацию. Ещё такой вопрос, если проект большой, и следует DDD, то сущность не должна быть анимичной, необходимо как можно больше сократить использования сеттеров и использовать методы жизненного цикла сущности, в случае использования вашего подхода получится ли создать и использовать богатую модель? Если выбирать Doctrine, то лучше сразу выбирать symfony по моему мнению.
Подобный подход мы освоили недавно и применяли точечно. Не вижу сложностей кроме указанных в видео для создания крупного примитива модели (с отношениями и тп). Что касается "Если брать доктирну, то тогда уж симфони" - идея ведь в том чтобы жизненный цикл модели бы малый (как у реквеста в контроллере). И ареал так же очень мал - получили модель - сразу трансформировали. Исходя из этого - не важно какой у нас фреймворк.
@@DmitryAfanasyev "Не вижу сложностей кроме указанных в видео для создания крупного примитива модели (с отношениями и тп)". Вот тут можно чуть подробнее куда копать? Хотелось бы сделать что то такое "AnyModel::select(['field1', 'field2'])->with('anyRelation')->toBase()->paginate(5)", но на выходе нету никаких релейшенов и кастомных аттрибутов. Сам "toBase" классная штука. Использую в репозиториях, когда нужны простые данные. Но вот когда нужны связи и аттрибуты "toBase" уже не справляется.
То о чем ты говоришь это самый примитивный способ - чтобы сразу из запроса получить примитив. toBase отработает только с обычными полями, toArray может захватить и аксессоры те, которые были добавлены в свойство appends, далее массив можно превратить в stdClass например. Не знаю может ли toArray захватить и отношения - надо проверять. Второй способ использовать спец классы - презентаторы, которые будут трансформировать модель в требуемую структуру данных.
@@DmitryAfanasyev про to array знаю. С атрибутами кастомными проблем нет. Но очень смущает сам факт, что сначала запросом вытаскиваются все модели, потом они перегоняются в массивы, а следом их надо ещё и в stdClass перегнать и дальше ещё во вьюхе сделать цикл для вывода.. Выглядит как то не очень. Уже обнадёжился может какой секрет знаешь, как можно сделать это просто. Походу только презентаторы остаются, как вариант.
А почему не написать ОРМ где можно только определеные поля загнать в модель и если их потом пытатся взять то ексепшн. Плюс если через joinы пытаемся вытащить данные с разных тамблиц, то создавать много моделей сколько нужно под данные. Тогда всего этого не будет
Не настаиваю на логике работы с моделями и коллекциями, но мы лишаемся целого пласта валидации на уровне типов в таком случае. Считаю, что это самый важный минус
@@DmitryAfanasyev - есть работающая REST система. Есть фронтендщики. Есть БД отдельно. И тем и другим периодически взбрыкивает менять имена полей. Всмысле все приходящие данные из вне системы приходится конвертировать в понятные системы поля
Был такой вопрос и был ответ. 1) toBase, toArray 2) отдельный класс - презентатор, который на вход получает модель, на выходе примитив. Все максимально просто.
Вся суть опять создать прослойку, прослойки и тд. :) По поводу коллекции ее я думаю можно и передать, какая разница класс который наследует, так же может преобразовать структуру данных в коллекцию.
Почему именно stdClass, а не те же DTO? Вроде бы то, что ты описал - как раз и есть пересылка данных между слоями, где обычно и юзают DTO. Или потому что создание DTO - это дополнительная логика?
Огромное спасибо!!! Может быть будет нагловато, но все же: а есть возможность по работать с Вами в одной команде и на прямую набраться опыта и получать волшебных обучающих пендалей?
@@DmitryAfanasyev видимо запамятовал. Пересмотрел еще раз. Получается под Gateway и Presentator вы имеете ввиду класс-обертки? Gateway работает с билдером, возвращаемым из репозитория. Gateway берет на себя обязанность уточнения запроса к БД через доп. параметры. А presentator, это класс, который берет на себя обязанность привести модельки к std классу, снимая это бремя с Gateway. Верно?
все понятно, но зачем тогда в Laravel параметр роута сразу в модель превращается (например /users/{user}/projects/{project}) ? сами приучают народ что в контроллере у же есть модель и с ней можно быстренько что-то поделать)
Если нет знаний приемов как и что делать, то сколько бы денег в проект не вкладывали - будет говнокод. И говнокодеры всегда найдут отговорки почему всё плохо. Как сказал доктор Хаус - "знать - круто!"
Это все конечно очень интересно, но без примеров - ни о чем. Только не искусственно подогнанный пример (минипроект) под этот подход, как обычно любят делать, а нормальный. Ларавел очень хорошо подходит для RAD разработки, думаю поэтому куча такого кода. Тяп-ляп - работает и ладно. Поэтому конечно же хочется видеть примеры с нормальной архитектурой, а писать код сейчас может каждый. Некоторые даже не изучая php начинают с Laravel и задают такие вопросы, которые даже к фреймворку не относятся, а относятся к области необходимых элементарных знаний.
Не понятно для чего тут пример? И чем пример малый был бы плох? Вам нужен пример как использовать toBase() ? Да еще и в большом колечестве? Или вам нужен пример как создать класс презентатора который на вход получит модель и выдаст stdClass ? Да еще и в большом количестве? Возможно вам просто еще рано подобные моменты использовать. Но надо просто иметь их в виду. С опытом придет. Цель видео - показать путь и возможности.
Только на днях думал о том, что нехорошо когда модельки свободно гуляют по проекту. Хорошо бы их не выпускать из слоя БД. Собственно, всё как в видео. Решил перейти от теории к практике и попробовать реализовать - не получилось. Расстроился и забросил идею.. а тут смотрю, видео про модельки.. открываю и вах! Значит не всё у меня так плохо, раз сам до такого додумался. Дай-ка, думаю, еще раз попробую. Описал класс сущности, презентатор. Создаю репозиторий и описываю в нём метод findOrFalse($id). Ищу модельку, отдаю её в презентатор и на выходе получаю сущность (тут это вроде как делает Gateway, но по мне так это как раз задача для репозитория. Спорно, но сути дела не меняет). Дописал. Отлично, думаю, выходит! Да не тут то было... Надо мне запись сохранить.. и? Есть экшон. В него пробрасываю ДТОшку и репу в зависимостях. А дальше? Ну, вроде как создать сущность и пробросить её в репозиторий на сохранение. Ага. Только она имеет штук 5-6 полей, а для создания нужно 2. Остальные значения присваиваются при создании модели. Например, таймстемпы. И как быть? Создавать урезанную сущность? Так дтошка уже есть. Пробрасывать её транзитом из экшона дальше в репозиторий? Как-то не очень выглядит.. экшон тогда вообще не при делах. Чёт опять приуныл. Почитал комменты, тож не все доходят. Короче, Дима, пили видос. У тебя это хорошо получается. Ой как нужен видосик новый! Не так тут всё просто как кажется.
При всем уважении и подписки на ваш канал, но я считаю Repository это антипаттерн, это полное дно и его вообще нельзя юзать не прикаких абстоятельствах. Потом что он финализирует все движения get() и тд Оптимально под это все это какие нибудь Criteries или Scopes.
Если репозиторий используется как сосредоточение логики запросов. Например имеет методы типа ДайМнеХПользователейКоторыеЗарегалисьНеделюНазадВПолдень. То в репозитории будет обращение к классу модели, построение запроса и получение результата. И да, внутри метода будут where, join и тп. Если репозиторий будет как обертка для ОРМ, с целью иметь возможность не зависить от ОРМ, то появится уже новая сущность UserGateway::ДайМнеХПользователейКоторыеЗарегалисьНеделюНазадВПолдень() и внутри будет работа с репозиторием с помощью которого будет формироваться запрос. UserGateway не будет ничего знать об ОРМ.
Не совсем так. Получить коллекцию моделей для отчета, допустим, в котором нам потребуются 3 поля из 20 это отвратительно и нисколько не красиво. Красиво указать в запросе эти 3 поля и сделать toBase().
Ранний доступ к новым видео в телеграм-канале:
t.me/i640kb
t.me/i640kb
t.me/i640kb
Там 11-я версия apiato релизнулась)
Спасибо, надо глянуть 👍
Дмитрий, хочу выразить тебе огромную благодарность. По твоим видео, я научился работать с Laravel, и нашел работу, став разработчиком на Laravel, Vue, прошел после первого собеседования. У тебя лучшие видео на RUclips.
🙏
поддерживаю. Со мной так же сложилось 2 года назад, правда не с первого раза. Лучший
Я к такой архитектуре в голове пришёл с пол года назад и после её внедрения на практике сразу отказался. (для лары)
1. Если ты работаешь с ларой - ты работаешь с ларой. Что такое лара? Быстро поднять приложение легкой и средней сложности. Ключевое слово быстро, т.е. дешево.
2. Большинство ларавель программистов не ахти развиты в архитектуре(имхо). Просто потому что лара не заставляет думать. Это такая фишка фреймворка. И каждый новый прогер на проекте будет страдать. А вместе с ним страдать и ревьюверы, пытаясь донести ему где пахнет.
3. Ларавель такой монолитный фреймворк, что выпилив из него всю магию моделей ты превращаешь его в симфони. Тогда вопрос, почему бы сразу не писать на симфони, который чище на порядок?
4. Пакеты лары жёстко завязаны на модели и писать свои обработчики нарушает п.1 К примеру, аутентификация дергает пользователя, т.е. работает с моделью напрямую. Это уже нарушение архитектуры. Это можно обойти, но тогда юзера надо хранить как ДТО. Окей, храним как дто. Как мы будем писать политики? Никак. Окей, пишем свои политики. Как мы будем слушать события модели? Никак. Окей, пишем свои события, пишем команды и приближаемся к cqrs. И так далее. Суть ясна.
5. Шансы что когда-то проект на ларе дорастет до того чтобы самовыпилит лару невероятно низок. Поэтому закладывать на старте лара проекта то что ты будешь переобувать орм в дальнейшем сильно нарушает п.1
В общем, итого моего решения после всех раздумий:
1. Никогда не писать логику в моделях
2. Использовать модели только для релейшенов
3. Сложные запросы дергать репозиторием, простые в 2 строчки напрямую с модели(т.к. она уже и есть репозиторий и в этом сама ирония паттерна репозиториев для лары)
4. Не имеет никакого смысла создавать дто той же самой структуры что и модель, если ты делаешь с дто тоже самое что и с моделью.
5. Если руки прям горят в архитектуру - ставить симфони.
6. Если когда-то захотелось выпилить из своего проекта лару или симфони - то увы, в реалиях пхп это невозможно. Я больше поверю в то что рядом будет переписаны сервисы на другом языке или фреймворке чем то, что вы сможете безболезненно разобрать фреймворк из приложения. Я пытался. Честно) Чтобы отделить приложуху от фреймворка понадобится невероятно огромное количество прокси классов. И это не имеет никакого смысла для бизнеса.
В чём мораль басни: Прежде чем отступать от канонов фреймворка - 10 раз подумайте, а поймёт ли вас коллега, который сядет писать через год. Или другая студия, которая возьмёт проект после вас. Или другая команда.
PS чистая архитектура в грязном фреймворке - это очень мило. Как фотка парня в смокинге по пояс в болоте) Отнимите у типового разработчика ларавель возможность дёргать сервис контейнер по любому поводу и он сразу поплывёт. А создавать объекты из сервиса контейнера посреди кода - это лютейший антипаттерн, если что) Единственное место где одобряют его применение - контроллер. Что юзают в симфони. В остальных же местах можно и по рукам получить от ревьюверов.
+100500 и вообще нафига строить эти уровни когда в итоге приходим к микросервисам
Архитектура не зависит от фреймворка. То что в видео касается любого фреймворка, лара как деталь для примера. Отвязывать все приложение от фреймворка это сложно всегда и в любом фреймворке и на любом языке. Но стараться избавляться бизнес-логику от фреймворка можно и нужно. Например зачем фреймворку быть в классах расчета зп?
Микросервисы сейчас активно пидалируются разными образовательными центрами (была недавно волна рекламы в инсте). Полагаю мода. Далеко не всегда они нужны. И поддержка их тоже не так проста. Как по мне, так лучше рядовому разработчику порокачиваться в чистом коде и архитектурах, чем умея только писать говнокод лезть в микросервисы. А внутри микросервисов создавать годКлассы, пропускать реквесты в бизнеслогику и тп.
ты прав во многом, но в моделях лучше не писать свою говно логику. Мне кажется создать Репозиторий самое простое что можно сделать а так лично я использую для средних проектов Фасад - Сервис провайдер - Сервис контейнер - Репозиторий. Вообще для мелких проектов можно только репозиторий юзать поверх модели и все так как смысла нет от всей пидантичности
1. Никогда не писать логику в моделях - "сколько еще открытий чудных...". Вы пришли к анемичной модели, осталось обратно вернуться к рич модели. Пару легаси проектов с "Никогда не писать логику в моделях", а с логикой в сервисах изменят ваше мнение.
На последок напишу, что очень комфортно смотреть твой канал)) Чувствуется 100% знание материала и уверенность. Щепотка юмора и харизмы в самую точку)) Смотреть не наскучивает, это как читать интересную книгу. На рабочих проектах использую твои идеи, начиная с паттернов проектирования, заканчивая архитектурой Porto. После этого видео, я предложу тимлиду использовать именно этот способ получения данных. Буду это аргументировать плюсами из видео или просто скину ему этот ролик. Подписан на тебя с курса по Laravel и буду продолжать тебя смотреть даже после возможной блокировки ютуба. Надеюсь ты продолжишь радовать нас новыми видео.
PS. На телеграм канал подписался)
Дим привет, было бы круто посмотреть на минипроект с этими примерами, если есть возможность скинь ссылку плз
Есть в планах
Как раз тоже хотел такой же запрос сделать =)
Да, хотелось бы увидеть пример...
значит ждем, заранее благодарен!
тоже хотел увидеть , слышал только про один реальный проект, там тоже от базы до вью было куча слоев ,проект простой но тормозил жутко. И в разработке не все так гладко.
Важные темы обсуждаете. Хотелось бы продолжения, надеемся на скорейшее возвращение
Большое спасибо за видео. Согласен на все 100%. Единственный комментарий, это на счет сложности. При вводе дополнительных прослоек возрастает сложность структуры, а не просто сложность... Сложность, вот просто сложность. Это всетаки сложность решения задачи, которая превращается в сложность разработки и подержки, тоесть в технический долг. И очень часто усложнение структуры в конечном счете уменьшают сложность разработки и сложность поддержки.
Частично именно за это мы и любим фреймворки. За некие правила, которые один раз осознав и выучив, ты перестаешь ходить по граблям.
Лично я давно живу с дополнительным слоем возвращающем структуры. Т.к. это упращает логику работы с данными на порядок. Всегда удобней в контроллере получить чистые данные, и работать с ними, а не странный объект, который возможно поменяется.
Дмитрий, классный видос. Очень хотелось бы глянуть на практическое применение этих подходов (точнее последний, я думаю, все пользуются первыми двумя 😊), интуитивно понятно, но все же. Очень хотелось бы увидеть применение! В целом, спасибо тебе за твой труд - очень важные вещи рассказываешь!!!
Дмитрий, в случае с Doctrine - это data mapper, взгляни на эту идею с той стороны, что никакой бд нет, сохраняем в памяти или файлах. Придет понимание, что "не писать логику в моделях" - нарушает основной принцип - мы не используем логику там, где хранятся данные. Информационный эксперт (Information Expert) - основной принцип Grasp гласит: информационным экспертомявляется объект, обладающий максимумом информацией, необходимой для выполнения назначенных обязанностей. Логика обработки данных должна находится в в том объекте, где есть максимум данных для ее обработки. Причем тут бд - непонятно. Но сразу видет подход ларавельщика с table gateway.
Не понятен комментарий. Похож на нападку и в конце с принежением ценности личности "сразу виден подход ларавельщика table gateway". Как будто контекст остался у вас в голове. Вы пытаетесь сказать что логику в модели писать это правильно? ибо Grasp? Про table gateway тоже не понятно. Это про тот gateway о котором я говорил в видео? Не знал что Роберт Мартин ларавельщик... Интересно он сам знает об этом? Подобное разделение ответственности впервые узнал от Мартина.
Вольный перевод статьи Фаулера anemic model
Действительно, часто эти модели поставляются с правилами проектирования, в которых говорится, что вы не должны помещать какую-либо логику предметной области в объекты предметной области. Вместо этого существует набор сервисных объектов, которые захватывают всю логику предметной области, выполняя все вычисления и обновляя объекты модели результатами. Эти сервисы работают поверх модели предметной области и используют модель предметной области для данных.
Фундаментальный ужас этого анти-шаблона заключается в том, что он настолько противоречит основной идее объектно-ориентированного проектирования; который должен объединять данные и обрабатывать вместе. Анемичная модель предметной области на самом деле представляет собой всего лишь процедурный дизайн, именно с этим объектные фанатики вроде меня (и Эрика) борются с первых дней существовани
Делайте, делайте все в моделях. Как вам будет угодно. И расчет зп помещайте в модель и все остальное. И обязательно об этом рассказывайте на собеседованиях.
@@DmitryAfanasyev так смысл же не в том, что бы делать все по шаблону (table gateway или ddd) всегда и везде, а в том, когда можно сэкономить и лупануть anemic model. И когда нельзя сэкономить - сделать rich domain с es и чем-нибудь еще)) и да, order может посчитать в этом случае свою цену(правда многое от контекста зависит и бл). Причем заметил такую фичу что если по ddd делать(в силу своих знаний и понимания темы), то юнит тесты очень репрезентативно показывают факапы. В то время как с table gateway подходом все немного сложнее в этом плане.
Так оно и понятно что все зависит от ситуации. Можно и толстые контроллеры делать.
Отличный контент, надеемся вернется )
Вернусь конечно!
Спасибо за видео! Надеюсь, в будущем будет видео: "все это время ты использовал laravel неправильно, создаем абстракцию для всего фреймворка сразу" )))
Уже было 😂😂😂 в курсе Porto
Дмитрий, ты в начале упомянул, что многие люди выбрасывают из ларавелла Eloquent и ставят Doctrine.
Это делается как раз для решения проблемы принадлежности сущностей к слою БД.
В доктрине сущности предполагаются независящими от ОРМ, они по коду - часть чистой бизнес логики и ОРМ-овские аннотации в них нужны только репкам доктрины для рефлексии. Такой подход позволяет избежать костылей в виде гейтвеев и презентаторов и разбивать модель на более внятные архитектурные слои.
Собственно, одна из хороших практик в симфони - сначала полностью описать бизнес-модель и только потом приделать к ней ОРМ, добавив конфиги в аннотациях или ямле.
За ролик - лайк и спасибо. Надо будет поближе познакомиться с ларавеллем - уже если там есть такие проблемы, то наверняка есть и преимущества )
Да, я всю доку проштудировал по доктрине чтобы не попасть в просак (так как боевого опыта с доктриной не имел). И всё же пришел к выводу что таки да, не надо выпускать куски доктрины из слоя БД.
Если исходить из логики чистой архитектуре . То ORM это слой деталей а модель как enitty в центре и нельзя делать зависимость от деталей так что можно спокойно сказать это ошибочное мнение так делать на doctrine. В центре всего должны быть наши сущности для бизнеса а не ORM модели хоть и они удобны как аггрегаты с коробки
Спасибо большое за Ваши видео, Дмитрий, я стал меньше говнокодить, а так же благодаря Вам я улучшил свои навыки работы с Laravel. Всегда жду Ваших видео!!! Успехов!
Рад стараться!
Спасибо за вдумчивые пояснения. Было полезно! 👍
У тебя отличный канал!
Очень жалею что не наткнулся на него раньше 😭
Здравствуйте, хотелось бы от вас обзор DDD, плюсы, минусы, сравнение с близкими по устройству...
в ларавеле модель - это вообще не модель в общепринятом понимании, а какой-то сам себе репозиторий и дто, какой-то кусок ОРМ, торчащий наружу, но ни как не "модель"
модель должна моделировать предметную область при помощи данных и поведения, основанного на бизнес-правилах и вообще не должна знать о бд и самом приложении. Можно сделать ее богатой (ордер, который считает цену - это НЕ антипаттерн). Можно анемичной (антипаттерн по Фаулеру и Эвансу), разделив данные и поведение, положив его в доменные сервисы. Почти везде сейчас анемичная модель т.к нужная меньшая квалификация разработчиков
Показали мандалорца в "Книге Бобы Фета" - Дмитрий видео запилил... Праздник!
Что-то из раздела чистой архитектуры)
Таким способом стоит попробовать сделать хотя бы один проект или хотя бы компонент, чтобы потом понимать где это лучше использовать а где нет.
Спасибо за видео!) было бы интересно послушать про разные слои
Дмитрий, большое спасибо за то что вы делаете!
Рад стараться!
Очень крутое видео, спасибо. Уверен, не раз еще буду пересматривать.
Пару вопросов
1) Ты не раз ссылался на presenter это что такое? я нашёл только вот такую реализацию pdavidhemphill/presenter ну как я понял это обычная обвёртка над моделями она позволяет логику с моделей выкинуть в функционал это-го пакета .
2) Есть в laravel метод toBase() как мне его использовать со связями заезженный пример есть пользователи а них есть роли в обычном случае поступил бы вот так User::select(['id', 'name'])->with(['roles:id,name'])->limit(10)->paginate(10) всё ок а если я хочу получить не модельки а stdClsss то мне выплёвывает только юзера мне что теперь отказаться от связей и писать через join?
Только не бей меня я ещё новичок в этом деле
Пожелание можешь записать подробное видео или мини проект тяжеловесный с использованием вот это-го подхода?
Дмитрий, скажите пожалуйста, сколько вам нужно задонатить, чтобы ты записал курс по swoole(многопоточность, корутины, таблицы, сокет сервер и тд)?. Просто очень крутая китайская штука, решила многие проблемы с производительностью на проекте. Использовал на ощупь, не разобравшись. Хотелось бы поподробнее разобраться.
На самом деле если для какого то рассчета никаких внешних механизмов не требуется, то можно и моделью это посчитать и презентовать. Ну это только если, допустим, у модели атрибут А умножить на атрибут Б.
Мы, конечно, можем не понять при первом знакомстве с проектом, что реальный прайс считается через GetOrderPrice, т.к. он висит где то отдельно, но это же самое и дает нам возможность изменить провайдера курса валюты или добавить интернацианализацию при перерассчете
Есть такой вопрос. Допустим есть абстрактный метод show (Получение статьи по ID), который получает модель в параметр с помощью сервис-контейнера. По логике из урока передавать эту модель таким образом не вариант:
return view('template', ['model' => $model]);
Тогда получается то, что нужно будет перед тем как передать в шаблон данные, предварительно прогнать эту модель в Presentator и уже в шаблон вернуть stdClass.
$data = $this->presentator->model($model);
return view('template', ['data' => $data]);
Верно ли я понял?
Да, все верно.
Еще 1 вопрос. У меня на проекте не планируется менять ORM, нужно ли мне тогда использовать Gateway? Если нет то должна получиться схема:
ORM - > REPOSITORY -> PRESENTATOR
Я веб-программист с опытом работы больше 15 лет, занимал должности и тимлида и техлида. Хотелось бы высказать своё мнение, касательно темы этого видео. Если программист начинает разработку без моделирования, то это очень, очень плохо. А если программист ещё изначально пишет код, который нуждается в рефакторинге - ещё хуже.
Да, нужно понимать, что 80% времени программист исправляет ошибки в коде, свои или чужие, но если при разработке нового функционала не происходит хотя бы незначительные потуги в UML, то этот код через незначительное время придётся дебажить уже другому программисту.
Вывод, рисуйте диаграммы и большая часть проблем решится в самом начале, а кодирование - это самая простая часть инженерии.
На эту тему можно почитать С. Макконнелла "Совершенный код".
Есть разные подходы. Вы описываете Предварительное проектирование. А есть еще и Эволюционное. Так же не понятно как ваш коммент относится к теме видео...
Бро, просто, лучший как всегда )
Дмитрий почему перестал записывать ролики?
Вопрос: если репозитории служат только для выборок данных, а напрямую обращаться к модели не следует в сервисах то какой слой использовать для Create, Update, Delete операций?
ООП, вы хотели всего лишь банан, но в результате получаете гориллу, держащую этот банан, и все джунгли впридачу.
Спасибо Дмитрию за его подачу информации! Вопрос по репозиторию. В нем можно только операцию по чтению проводить или полный CRUD. И если только чтение то где совершать остальное ? Заранее спасибо.
Можно по разному.
1) Сам процесс сохранения идет в репозитории, который используется в отдельном классе, например UpdateUserTask($userData).
Класс готовит данные, отправляет в репозиторий и репозиторий делает только save() без какой- либо логики.
2) Если нет идеи абстрагироваться от ОРМ, и репозиторий сожержит методы типа "ДаймМне10ПользователейКоторыеОтписалисьОтРассылки" то save можно вызвать у модели в UpdateUserTask
3) Есть практика когда делают 2 репозитория на одну сущность -1) Репозиторий только на выдачу 2) Репозиторий только на сохранение.
Главное не помещать логику сохранения, а она может быть очень сложной, в сам репозиторий.
Дима, привет, последнее видео 4 месяца назад выкладывал ты))
Как будет время сделай пожалуйста свежие туториалы по работе с API на ларе. Спасибо
Принял
Дмитрий, добрый день! Выражаю огромную признательность вам за труд! Я почерпнул для себя массу нового и дошел до многих разных вещей! Прошу помощи разобраться с одной штукой, с которой давно хочу разобраться. Пересмотрел, пожалуй, все ваши видео тут на канале, если где-то об этом уже сказано, то, вероятно пропустил, и буду признателен за ссылку. Тема такая. Что такое "бизнес-логика"? Что вы понимаете под этим по сути? Тут кроме самого определения мне очень интересно разобраться - где же она должна быть? В каком слое приложения? Вы постоянно говорите, что контроллер должен быть тонким (совершенно согласен), что модели не должны содержать бизнес-логики (согласен), в билдерах, мостах, прокси, дто и т.д. ей тоже не место, так куда же ее выносить? Если следовать Porto, то - в таски? Тогда подвопрос: таски могут обращаться друг к другу, но само по себе обращение - это ведь тоже логическая связь, подчиненная каким-то законам бизнеса? К таскам можно обращаться из тасков другого модуля или контейнера, или из "акшонов", тогда получается размазывание бизнес-логики? А если не следовать Porto? Буду признателен за комментарий к моему вопросу.
Спасибо за видео, продолжай!!!!
Дмитрий, сделайте пожалуйста урок по AWS S3, (всё же это best practise по хранению файлов на сервере) документация достаточно бедная на эту тему, особенно что касается использования загруженных файлов. Спасибо :)
Благодарю за инфу
Вы рассматриваете всё это только в разрезе паттерна ActiveRecord, Doctrine использует паттерн DataMapper который как раз возвращает чистый объект который сам разработчик может наделить бизнес логикой. И как мне кажется не вся бизнес логика должна быть вынесена из модели, если эта логика зависит только от бизнес модели и не обращается к бд и внешним сервисам. По вашей логике модель это просто массив с полями.
Нет, я не рассматриваю все в разрезе AR. Для доктрины подобный подход так же подходит.
@@DmitryAfanasyev Я правильно понимаю, что получится анимичная модель? И если у нас есть связь 1:м или 1:1 мы явно сделаем 2 вызова, то есть обратимся за моделью, а потом за связанными моделями? И если можно ещё вопрос как вы решаете транзакционное сохранение данных в бд?
Не понятно про связи и получение данных. Оно никак не изменится - как запрограммируете, так и будет...
@@DmitryAfanasyev В доктрине получив модель мы можем обратится к полю которое является коллекцией, внутри произойдёт магия и запрос в бд и вернётся коллекция моделей, если я правильно понял вашу идею с stdClass, то внутри он содержит только поля и не содержит никаких магических эффектов и коллекций, или это не так и модель может содержать вложенные коллекцию ?
Идея не моя, а Роберта Мартина, об этом я написал в описании к видео. На выходе мы должны получить - примитив. Простую структуру данных. Не вижу ничего страшного если некое отношение превратится из модели так же в примитив. Суть в том что нам для работы от БД нужны данные, не более. Не механики расчёта зп, цен и тп. Данные нужны. Вот и получаем данные.
Спасибо за видео.
P.S. вес поднабрал?)
Угу 😟
как всегда шикарно !
Гос услуги vs Eloquent. Не факт что гос услуги продержатся дольше Eloquent.
Почему?
Как всегда, полезно
Про пользователя и зарплату было мощно))))
Реальный кейс был описан ))))
Спасибо за ролик.
Подскажите, пожалуйста, и в уроках по ларе, и тут речь ведется о селектах. Хорошо, я договариваюсь в проекте работать с моделями в особом слое, где на самом нижнем уровне конкретная ОРМ, а перед ней репозитории, гетвэи и презентаторы, на выходе получаю структуру данных, тут всё понятно.
А как в такой схеме будет выглядеть вставка и обновление модели? Какие сущности в этом слое будут отвечать за эти процессы, может кто-то доступно объяснить? По схеме получается, что это ответственность репозитория или я не прав?
Дмитрий, мне вас не хватает
Спасибо большое за познавательный урок, вопрос, будет ли пример реализации этого подхода в виде кода. Очень интересно посмотреть именно вашу реализацию. Ещё такой вопрос, если проект большой, и следует DDD, то сущность не должна быть анимичной, необходимо как можно больше сократить использования сеттеров и использовать методы жизненного цикла сущности, в случае использования вашего подхода получится ли создать и использовать богатую модель? Если выбирать Doctrine, то лучше сразу выбирать symfony по моему мнению.
Подобный подход мы освоили недавно и применяли точечно. Не вижу сложностей кроме указанных в видео для создания крупного примитива модели (с отношениями и тп). Что касается "Если брать доктирну, то тогда уж симфони" - идея ведь в том чтобы жизненный цикл модели бы малый (как у реквеста в контроллере). И ареал так же очень мал - получили модель - сразу трансформировали. Исходя из этого - не важно какой у нас фреймворк.
@@DmitryAfanasyev "Не вижу сложностей кроме указанных в видео для создания крупного примитива модели (с отношениями и тп)". Вот тут можно чуть подробнее куда копать? Хотелось бы сделать что то такое "AnyModel::select(['field1', 'field2'])->with('anyRelation')->toBase()->paginate(5)", но на выходе нету никаких релейшенов и кастомных аттрибутов. Сам "toBase" классная штука. Использую в репозиториях, когда нужны простые данные. Но вот когда нужны связи и аттрибуты "toBase" уже не справляется.
То о чем ты говоришь это самый примитивный способ - чтобы сразу из запроса получить примитив. toBase отработает только с обычными полями, toArray может захватить и аксессоры те, которые были добавлены в свойство appends, далее массив можно превратить в stdClass например. Не знаю может ли toArray захватить и отношения - надо проверять.
Второй способ использовать спец классы - презентаторы, которые будут трансформировать модель в требуемую структуру данных.
@@DmitryAfanasyev про to array знаю. С атрибутами кастомными проблем нет. Но очень смущает сам факт, что сначала запросом вытаскиваются все модели, потом они перегоняются в массивы, а следом их надо ещё и в stdClass перегнать и дальше ещё во вьюхе сделать цикл для вывода.. Выглядит как то не очень. Уже обнадёжился может какой секрет знаешь, как можно сделать это просто. Походу только презентаторы остаются, как вариант.
Передавать модель во вьюху, как по мне, жесть полная. Был свидетелем того как тащили модель заказа с 30+ полями во вьюху и там брали только ид....
Классы всё-таки должны называться существительными (GetOrderPrice и тд это таки глаголы).
А в остальном большое спасибо за видео)
Таки да, перепроверил у Мартина в "Чистый код" - существительные. Не глаголы. Спасибо за замечание.
До тех пор пока это не Porto где действия и задачи вынесены в отдельные классы.
Вот вопрос как будут выглядеть useCase если классы можно называть только существительными
Кто пример покажет?
А почему не написать ОРМ где можно только определеные поля загнать в модель и если их потом пытатся взять то ексепшн. Плюс если через joinы пытаемся вытащить данные с разных тамблиц, то создавать много моделей сколько нужно под данные. Тогда всего этого не будет
Подскажите, как в laravel заставить toBase() работать с with(). C toArray() работает нормально, а с toBase() не хочет.
Никак
Не настаиваю на логике работы с моделями и коллекциями, но мы лишаемся целого пласта валидации на уровне типов в таком случае. Считаю, что это самый важный минус
Не понятно. О какой именно валидации идет речь? Можно примитивный пример?
@@DmitryAfanasyev в модели имеется cast который удобно использовать в качестве приведения типов
Слой сущностей который возвращает презентатор тоже лучше создавать с полями предопределенного типа и наделять его нужной бизнес логикой
Работа с этими полями не изменится как и с мутаторами и аксессорами. Но только в слое бд.
не знаком честно говоря с шаблоном Presenter, но вроде две DTO на Request и на ORM сделают тоже самое?
Не понятно про две DTO.
@@DmitryAfanasyev - есть работающая REST система. Есть фронтендщики. Есть БД отдельно. И тем и другим периодически взбрыкивает менять имена полей. Всмысле все приходящие данные из вне системы приходится конвертировать в понятные системы поля
А можно примеры на конкретных данных, типа было/стало?
Был такой вопрос и был ответ. 1) toBase, toArray 2) отдельный класс - презентатор, который на вход получает модель, на выходе примитив. Все максимально просто.
Крутой мерч 😉
а что за программа использовалась для презентации подскажите пожалуйста?!
Я в видео прямо в схеме уже ответил на этот вопрос - xMind
Спасибо_
лайкос, заходЫ...
Вся суть опять создать прослойку, прослойки и тд. :) По поводу коллекции ее я думаю можно и передать, какая разница класс который наследует, так же может преобразовать структуру данных в коллекцию.
Я и не говорил что коллекции не надо возвращать. Коллекции МОДЕЛЕЙ не надо возвращать, а коллекции примитивов - пожалуйста.
Реальный пример будет (ссылка на код) или выйдет новое видео?
Есть в планах
@@DmitryAfanasyev Хорошо, будет интересно глянуть!
легенда🤙
Почему именно stdClass, а не те же DTO? Вроде бы то, что ты описал - как раз и есть пересылка данных между слоями, где обычно и юзают DTO. Или потому что создание DTO - это дополнительная логика?
Про дто есть видео. Полагаю ответы там.
Димон, ну куда пропал?
Огромное спасибо!!! Может быть будет нагловато, но все же: а есть возможность по работать с Вами в одной команде и на прямую набраться опыта и получать волшебных обучающих пендалей?
Если вы сильный миддл, то да. Пишите в лс
@@DmitryAfanasyev Написал вам на почту
Что такое презентатор и gateway и что они из себя представляют?
Я же в видео рассказывал про это...
@@DmitryAfanasyev видимо запамятовал. Пересмотрел еще раз. Получается под Gateway и Presentator вы имеете ввиду класс-обертки?
Gateway работает с билдером, возвращаемым из репозитория. Gateway берет на себя обязанность уточнения запроса к БД через доп. параметры.
А presentator, это класс, который берет на себя обязанность привести модельки к std классу, снимая это бремя с Gateway.
Верно?
Да, верно.
все понятно, но зачем тогда в Laravel параметр роута сразу в модель превращается (например /users/{user}/projects/{project}) ?
сами приучают народ что в контроллере у же есть модель и с ней можно быстренько что-то поделать)
Как один из вариантов использования. Если у вас нет целей абстрагировать бизнес правила от деталей - то можно делать и так.
Один из лучших русскоязычных скринкастов по php laravel, возвращайся, куда пропал.
95% решений, какой подход использовать, принимается в зависимости от время/деньги.
Если нет знаний приемов как и что делать, то сколько бы денег в проект не вкладывали - будет говнокод. И говнокодеры всегда найдут отговорки почему всё плохо. Как сказал доктор Хаус - "знать - круто!"
@@DmitryAfanasyev так-то да, но если нужно сделать что-то быстро и на коленке, то о каких репозиториях может идти речь
Дмитрий, а ты вернёшься на ютуб? Телеграм не находит кстати.
Привет. Да, вернусь. А где нерабочая ссылка на телегу? (да, менял урл).
Вот рабочая t.me/afanasyev_it
Хотелось бы код увидеть
Классный видосик.
Я бы возвращал коллекцию дто со всеми геттерами. Потому что любитель ооп.
Как сказал Мартин Фаулер - "Вы же не собираетесь сделать страшное и объявлять публичные свойства, так ведь?" )))))
@@DmitryAfanasyev ага)))
дто ничего общего с ооп не имеет.
@@user-lk1fw1lp8b правда? почему?
@@alexanderk8992 дто нарушают инкапсуляцию
Нам одним харошо
ЗАЧЕМ ТЫ К НАМ В ШКОЛУ ИДЁ
Куда ж он пропал, более года нет видео
Скоро вернусь
@@DmitryAfanasyev ждем возвращения!
@@DmitryAfanasyev ☺💥laravel 9 или 10, а может symphomy
гений
Надо бы пример такого многослойного проекта.
Лайк не глядя
анахуавсёусложнять программирование - это просто!
Ура ура ура
Почему перестали выпускать, да понимаю удовольствие от этого мало, но можно раз в 2-3 месяца выпускать чо нибудь полнзное
да, надо возобновлять! Спасибо за интерес! (удовольствия на самом деле от этого много. Проф выгорание настигало, настигало и настигло)
МУРМАНСК
Все хорошо, но все это ломается о пагинацию или чанки.
Нет, не ломается
Это все конечно очень интересно, но без примеров - ни о чем. Только не искусственно подогнанный пример (минипроект) под этот подход, как обычно любят делать, а нормальный. Ларавел очень хорошо подходит для RAD разработки, думаю поэтому куча такого кода. Тяп-ляп - работает и ладно. Поэтому конечно же хочется видеть примеры с нормальной архитектурой, а писать код сейчас может каждый. Некоторые даже не изучая php начинают с Laravel и задают такие вопросы, которые даже к фреймворку не относятся, а относятся к области необходимых элементарных знаний.
Не понятно для чего тут пример? И чем пример малый был бы плох? Вам нужен пример как использовать toBase() ? Да еще и в большом колечестве? Или вам нужен пример как создать класс презентатора который на вход получит модель и выдаст stdClass ? Да еще и в большом количестве? Возможно вам просто еще рано подобные моменты использовать. Но надо просто иметь их в виду. С опытом придет. Цель видео - показать путь и возможности.
Только на днях думал о том, что нехорошо когда модельки свободно гуляют по проекту. Хорошо бы их не выпускать из слоя БД. Собственно, всё как в видео. Решил перейти от теории к практике и попробовать реализовать - не получилось. Расстроился и забросил идею.. а тут смотрю, видео про модельки.. открываю и вах! Значит не всё у меня так плохо, раз сам до такого додумался. Дай-ка, думаю, еще раз попробую. Описал класс сущности, презентатор. Создаю репозиторий и описываю в нём метод findOrFalse($id). Ищу модельку, отдаю её в презентатор и на выходе получаю сущность (тут это вроде как делает Gateway, но по мне так это как раз задача для репозитория. Спорно, но сути дела не меняет). Дописал. Отлично, думаю, выходит! Да не тут то было... Надо мне запись сохранить.. и? Есть экшон. В него пробрасываю ДТОшку и репу в зависимостях. А дальше? Ну, вроде как создать сущность и пробросить её в репозиторий на сохранение. Ага. Только она имеет штук 5-6 полей, а для создания нужно 2. Остальные значения присваиваются при создании модели. Например, таймстемпы. И как быть? Создавать урезанную сущность? Так дтошка уже есть. Пробрасывать её транзитом из экшона дальше в репозиторий? Как-то не очень выглядит.. экшон тогда вообще не при делах. Чёт опять приуныл. Почитал комменты, тож не все доходят. Короче, Дима, пили видос. У тебя это хорошо получается. Ой как нужен видосик новый! Не так тут всё просто как кажется.
НЕНАДА
Метадран))
чтож вы забросили канал то!
При всем уважении и подписки на ваш канал,
но я считаю Repository это антипаттерн, это полное дно и его вообще нельзя юзать не прикаких абстоятельствах.
Потом что он финализирует все движения get() и тд
Оптимально под это все это какие нибудь Criteries или Scopes.
Не понятно почему это антипаттерн - ссылку плз
Нужно ли в репозиторий выносить селекты, ордеры и лимиты?
Если репозиторий используется как сосредоточение логики запросов. Например имеет методы типа ДайМнеХПользователейКоторыеЗарегалисьНеделюНазадВПолдень. То в репозитории будет обращение к классу модели, построение запроса и получение результата. И да, внутри метода будут where, join и тп. Если репозиторий будет как обертка для ОРМ, с целью иметь возможность не зависить от ОРМ, то появится уже новая сущность UserGateway::ДайМнеХПользователейКоторыеЗарегалисьНеделюНазадВПолдень() и внутри будет работа с репозиторием с помощью которого будет формироваться запрос. UserGateway не будет ничего знать об ОРМ.
Щас бы переживать о расходе памяти и юзать ORM.
Хочется красиво - будет медленнее. Хочется быстрее - будешь прямыми запросами в базу пулять.
Не совсем так. Получить коллекцию моделей для отчета, допустим, в котором нам потребуются 3 поля из 20 это отвратительно и нисколько не красиво. Красиво указать в запросе эти 3 поля и сделать toBase().
Да и "пулять" в БД продолжаем через ORM, но в слое БД. Продолжаем использовать всю мощь ORM, но только в слое БД.