Обновить

Комментарии 29

Явные контракты — теперь мы чётко видим и понимаем, какие данные принимает приложение при создании заказа и какие данные возвращает

StoreOrderFeatureTest

app/UseCases/V1

StoreOrderHandler

testUserCanCreateOrder

у разрабов на laravel какая то особая тяга к хаосу.

  • фичатест тестирует контроллер, а не фичу

  • фича - сохранить заказ (не обработать, не принять, не поставить в очередь на обработку)

  • название тест метода говорит чтт проверяется то что пользователь может ссоздать заказ, хотя фича сохранить заказ

  • фича сохранить заказ проверяется в тесте контроллера апишеи, который проверяет может ли пользователь создать заказ

  • фича сохранить заказ = обработать запрос "сохранить", вызвав обработчик сохранения заказа, который на самом деле юзкейс

  • тест фичи "сохранить заказ" проверяет что "пользователь может создать заказ", проверяя что "после вызова запроса апи от юзера 1 в базе есть заказ юзера 1"

плавает как утка, крякает как дятел, ведет себя как покемон, но в целом - енот охотничей породы

Тестирование UseCase? - это ещё проще!
В данном случае я советую писать тесты которые проверят работоспособность вашего бизнес-процесса.

барабанная дробь... да, тестируется именно контроллер, все эти юзкейсы инпуты аутпуты были зря.

вопросы:

  • а зачем тогда вам были нужны все эти церемонии с выделением input/output/handler?

  • что, кроме бессмысленных в приведенном примере 3+ классов, вы потеряете в этом случае, если контроллер просто сохранит заказ из данных полученных в запросе?

  • как вы собираетесь использовать версионирование юзкейса "сохранить заказ"? будет ли ситуация что их 2 параллельно работают?

учиться и учиться!

Большое спасибо за прочтение и за ваш комментарий!
Остальные классы вы также можете протестировать)
Да контроллер может сохранить заказ без проблем!

Все мы учимся!

Капец. Если б не ваша статья я бы считал что usecases я сам придумал неделю назад. Я их назвал прям так же. Использовал схожим образом. И был настолько рад этой идее что мне даже не пришло в голову нагуглить что-то подобное:)

Большое спасибо что прочитали)

Да UseCase-ы как оказалось уже стандарт, особенно их ценят в бигтех, так как бизнес-процессы там большие и запутаться в них легко.

Почитайте про Vertical Slice Architecture (VSA).

Почему то в ру сегменте подход, и информация о нем, слабо распространены.

Спасибо, обязательно посмотрю!

Если не считать того, что Rational Unified Process был опубликован, кажется, в 1998, и, следовательно, прорабатывался в целом в конце прошлого века, и да, там есть юз кейзы, вы оба молодцы. :)

😂😂😂

Большое спасибо)

Спасибо за наводку, копну этот участок

Так то usecase не должны возвращать результаты, результат выполнения события, посмотрите видео с DrupalCon которому уже 10лет, там все подробно разложено https://youtu.be/ajhqScWECMo

Большое спасибо что прочитали статью)

Не могу отрицать такие реализации тоже имеют место быть, но в данном случае мы работаем с restAPI приходиться что-то возвращать)

Если речь о Rest API, то в некоторых случаях можно возвращать 204 No Content :)

Имхо ситуация отличается от проекта к проекту, тут сложно предугадать.

Если можно сформировать DTO'шку из текущего агрегата, почему этого не сделать? Такой код не будет делать лишние запросы в базу и, скорее всего, его будет просто понять. Тут скорее важно только где и как вы мапите в DTO и что бы сам агрегат не был слишком раздут.

С другой стороны, если так поступить не получится, придётся обращаться к CQRS, который, как тут недавно писали, нарушает DDD, и делать запрос из ReadRepository.

Поэтому имхо баланс очень важен.

Согласен с вами полностью!

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

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

Был у нас такой юзкейсер, до сих пор разгребаем..)

Большое спасибо что прочитали статью)

Если не секрет что конкретно разгребаете? С какими проблемами столкнулись?

с проблемой полотна юзкейсов, которые оказываются избыточной прослойкой из двух доп. классов для любой операции

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

Что бы знать, что делает приложение, в 90% случаях достаточно посмотреть на точки входа, разве нет? Оставшиеся 10% это какие нибудь бекграунд джобы.

Имхо, не важно как вы называете это, но это просто добавление 4 слоя к стандартной трехслойной архитектуре. И имхо в идеале добавлять это только для части сценариев, где наблюдается сложная бизнес логика, связанная с множеством сервисов и репозиториев. Таких сценариев часто не очень много, подавляющее большинство вполне укладываются в три слоя.

Как мне кажется выделить какой либо сценарий в 4 слой можно на любом этапе разработки, когда в этом появится необходимость (каждый сам проведет границу).

Полностью с вами согласен!

1. Вот был у меня UseCase - создание приглашения о присоединении к системе для пользователя (в табличку запись добавляется, пользователю письмо улетает).
Потом появился новый сценарий - принятие запроса на временное присоединение к пространству пользователя специалиста поддержки, в который так же входит отправка приглашения пользователю (в табличку запись добавляется, пользователю письмо улетает). Теперь мой первый UseCase - уже не UseCase, если это часть другого UseCase? Что мне делать с "последовательностью управляющих конструкций"? Продублировать в двух UseCase'ах? Вынести код из первого UseCase в разделяемый сервис/модель? Вызвать один UseCase из другого?

2. Если сервисы делать маленькими, то это уже UseCase'ы?

Большое спасибо что прочитали статью!)

  1. Вы можете вынести общую логику в сервис, и сервис уже подключить в двух UseCase. Использовать один UseCase в другом UseCase лучше в самую последнюю очередь.

  2. Маленькие сервисы это не UseCase. Размер класса не определяет его роль. UseCase - это один конкретный бизнес процесс, бизнес сценарий. А Service это переиспользуемая бизнес-логика, т.е. часть какого-либо сценария.

Ну и в чём тогда выигрыш. Вот мы разложили всё по "сервисам" - переиспользуемую бизнес-логику и "use-case'ы" - конкретные бизнес-сценарий. У нас система развивается и "конкретный бизнес-сценарий" превратился в "переиспользуемую бизнес-логику". Так что границы между этими понятиями, которые мы для себя нарисовали, оказались весьма условны.

Граница между Service и UseCase действительно условна. Но цель UseCase не в строгой классификации классов. Его задача сделать структуру приложения отражением бизнес-сценариев системы.

Статья напомнила мне об архитектурном паттерне Porto, с которым я недавно познакомился. Porto — это значительно более широкая концепция, нежели просто use cases: она описывает полноценную архитектуру приложения с чётким разграничением зон ответственности между компонентами.

Тем не менее, раздел про Actions и Tasks в документации Porto перекликается с идеями из этой статьи — там подробно описано, как декомпозировать бизнес-логику и куда её помещать.

Всем, кого заинтересовала тема, рекомендую ознакомиться с разделом «Components» в официальной документации Porto — думаю, это даст более широкий контекст для понимания подобных подходов.

Большое спасибо что прочитали статью)

Обязательно почитаю про данный подход, спасибо!)

юзкейсы, как в любой из домейн центрик архитектур, которые умные люди описали десятки лет назад, чудиса на виражах!

Большое спасибо что прочитали статью!)
Полностью с вами согласен, за нас уже всё придумали)

Хорошая статья, приятно видеть, что тема usecase-подхода всё чаще появляется в обсуждениях — тенденция действительно радует.

Под Laravel я пару лет назад опубликовал пакет lemax10/simple-actions, где объединил подходы Actions и UseCases, и продолжаю его поддерживать. Возможно, кому-то из читающих будет интересно взглянуть.

Вообще, концепция юзкейсов и действий, на мой взгляд, неплохая практика для структурирования логики, но нередко её усложняют на ровном месте. Хотя многие и пишут про своего рода «разумную гранулярность», но на практике часто получается обратное — обычный сценарий превращают в крупный комбайн со множеством условий.

Спасибо что прочитали статью! Рад что есть единомышленники) Спасибо за ваш пакет, выглядит очень мощно, жаль что не встретил его раньше)

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации