CSR - одно из самых неудачных архитектурных решений со времен Б4. Предлагается для каждой модели написать свой репозиторий и сервис к нему. Но, простите, а что делать, если, например, одной модели оказывается недостаточно? К примеру пользователю понадобился адрес, его куда прикажете запихивать? В UserRepository? Или уже в AddressRepository? Если в последний, то как передать пользователя? Через id? Тогда будет N+1. Через ids? Тогда что делать, если сам UserRepository используется в каком-нибудь CustomerService который, не к ночи будет сказано, подтягивает еще какой-нибудь OrderRepositiory? Т.е. дальше одного шага проблема не решается принципиально, придется городить какие-то обходы выборок, сбор ids, передача всего этого в репы... и всё ради чего??? ------------------- %%(php) try { $user = $service->getUser($request->getUserId()); } %% Изюмительно. Я прямо сижу.. и старческие слезы умиления наворачиваются на глазах. Простите, а что Вы собираетесь делать, когда в запрос нужно будет передать новый параметр, кроме id? Ну, например, СНИЛС или что-то еще? Давайте я Вам помогу. Небольшой реверс-энжинеринг. Так как getUserId - это какой то малопонятный огород, вангую, что это обычная обертка над Request за каким-то бесом засунутая в виде метода в ShowUserRequest %%(php) protected int $userId; public function __construct() { $this->userId = (int) $this->id; } public function getUserId(): int { return $this->userId } %% Зачем? Да просто, ради писанины. Ведь теперь, чтобы добавить новый параметр и передать его в сервис нужно еще методов в ShowUserRequest закинуть. Почему нельзя просто сделать (int) $request->get('id', 0) ? Вопрос чисто риторический. Ну оке.. с ид понятно, добавление всего одного поля в такую систему приводит к каскаду правок в 1. реквесте 2. контроллере 3. сервисе(он же получает не реквест, а параметры отдельно) 4. репозитории(его же нужно как то обработать) Несколько многовато для такого простого действия. %%(php) catch (UserNotFoundException $exception) { return view('user.not_found', ['user_id' => $request->getUserId()]); } %% тут еще интереснее. Вместо совершенно логичного и общего для любых моделей ModelNotFound требуется на каждый реп описать свой эксепшен. За ради что? Т.е. в репе User::find($userId) заменить на User::findOrFail($userId) - уже не православно, а наогородить %%(php) if ($user === null) { throw new UserNotFoundException("User {$userId} not found.'); } %% - это феншуй. Ню... токооое. ------------------- "Негативные последствия такой реализации в том, что при необходимости получения разных ответов в разных методах контроллеров, одно и то же исключение может быть преобразовано по разному." Это в каком мире 404 страница должна быть преобразована по разному? Нет модели - пульнул одну для всех 404 и забыл. Я так понимаю, что разные ответы нужны чтобы программисты не скучали. ------------------- "В теле метода сервиса не выполняются запросы к базе данных. Только бизнесовая логика" и это приводит к тому, что запросы выполняются катастрофически долго, а логика превращается в спагетти-стайл с вызовом сервисов внутри других сервисов обернутое циклами внутри других циклов со вложенностью 5 и более и нытьём что ой у нас все как то сложно получилось давайте перейдем на DDD там всё еще сложнее. ------------------- "Репозитории — классы, отвечающие за сохранение и извлечение некоторого набора данных" Нет конечно. Ничего подобного репозитории НЕ ДЕЛАЮТ. Этим занимается DAO! Запомни, а лучше запиши и никогда в дальнейшем не путай!!! Репозиторий - это высокоуровневая абстракция доступа к данным. Никаких изменений он делать не может и не умеет. ------------------- "В идеале репозиторий не должен возвращать или принимать объекты класса Model" В сферическом вакууме, надо понимать. Там, где сферические кони. Паттерн был придуман задолго до того, как появилась эта ваша богомерзкая DDD и предназначался, в первую очередь, для быстрого доступа к уже полученным данным. Возможно ты в курсе, что есть языки, которые не выгружаются из памяти всякий раз на каждом запросе, так вот в них(например в яве) репы очень комфортно себя чувствуют, так как являются эдаким кэшем справочника в памяти, ну и, разумеется, хранят они самые что ни на есть Models, а не эти ваши "энтити", простихоспиди. ------------------- "Лучше создать собственные entity или dto." Ага.. давай еще один огород сверху прикостылим. А то там абстракций чет маловато, ОРМ уже не хватает. Теперь для добавления одного поля мало того, что нужно будет сделать миграцию и добавить логику в сервис, так еще написать пару-десятков методов гетеров и сетеров в entity, dto, valueObject commandBus и всё заверте... но это не точно. ------------------- "Но с опытом вы поймете..." что простое лучше чем сложное, что код, который никогда не ломается - это код, которого нет. Его проще сопровождать, проще добавлять новые фичи, проще разбираться с багами. YAGNI + KISS.