(Golang) Чистая архитектура - Кто должен делать оркестровку? - PullRequest
4 голосов
/ 18 марта 2020

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

Допустим, у нас есть GetHotelInfo(hotel_id) API, который вызывается из Интернета до контроллера.

Лог c в GetHotelInfo:

  1. Invoke GetHotelPropertyData() (Местоположение, услуги…)
  2. Invoke GetHotelPrice(hotel_id, dates…)
  3. Invoke GetHotelReviews(hotel_id)

Как только все результаты вернутся, обработайте и объедините данные и верните 1 объект, который содержит все соответствующие данные отеля.

Вариант 1 :

  • Создание 3 различных хранилищ (HotelPropertyRepo, HotelPriceRepo, HotelReviewsRepo)

  • Создание сценария использования GetHotelInfo который будет использовать эти 3 хранилища и вернет окончательный результат.

Вариант 2 :

  • Создание 3 различных хранилищ (HotelPropertyRepo, HotelPriceRepo, HotelReviewsRepo)

  • Создание 3 различных сценариев использования (GetHotelPropertyDataUseCase, GetHotelPriceUseCase, GetHotelReviewsUseCase)

    *1051**1054* Создайте GetHotelInfoUseCase, который будет координировать предыдущие 3 варианта использования. (Это также может быть контроллер, но это другая топи c)

Предположим, что сейчас только 1059 * выставляется в Интернете, но, возможно, в будущем, Я также выставлю некоторые внутренние запросы.

И ответ будет другим, если фактический лог c GetHotelInfo не является комбинацией 3 конечных точек, а скорее 10?

Ответы [ 3 ]

2 голосов
/ 25 марта 2020

Ожидается, что Interactors (класс Use Case) вызовет другие интеракторы. Итак, оба подхода следуют принципам чистой архитектуры.

Но фраза ", возможно, в будущем " идет вразрез с хорошими практиками проектирования и архитектуры.

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

И ответ будет другим, если фактический лог c GetHotelInfo не является комбинацией 3 конечных точек, а скорее 10?

Нет, это будет одни и те же. Однако, когда вы разрабатываете API-интерфейсы, в случае, если вам нужна комбинация десятков конечных точек, вам следует подумать о том, чтобы добавить слой GraphQL вместо того, чтобы усложнять проект.

2 голосов
/ 22 марта 2020

Подобный метод (называемый Get()) можно увидеть в « Чистая архитектура с GO» из Манато Курода

Манато отмечает, что:

  • по Acycli c Принцип зависимостей (ADP) , зависимости только указывают внутрь круга, а не указывают наружу и не имеют циркуляции.
  • что контроллер и презентатор зависят от входного порта варианта использования и выходного порта, который определен как интерфейс, а не как специфицированный c logi c (подробности). Это возможно (не зная деталей во внешнем слое) благодаря принципу инверсии зависимостей (DIP) .

https://miro.medium.com/max/1053/1*mTIKd9Vf0l7Sg7oXhmamQw.jpeg

Именно поэтому в примере с репозиторием manakuro/golang-clean-architecture Манато создает для слоя «Варианты использования» три каталога:

  • , репозиторий,
  • Presenter: в плата за порт вывода
  • : отвечает за порт ввода с набором методов, определяющих c бизнес-правила приложения, в зависимости от интерфейса репозитория и презентатора.

Вы можете используйте этот пример, чтобы адаптировать ваш случай, когда GetHotelInfo объявлен первым в файле hotel_interactor.go, и в зависимости от конкретного c бизнес-метода, объявленного в hotel_repository, и ответов, определенных в hotel_presenter

1 голос
/ 22 марта 2020

Чистый не является четко определенным термином. Скорее, вы должны стремиться минимизировать влияние изменений (добавление или удаление службы). И под «воздействием» я подразумеваю не только факторы стоимости и времени, но и риск введения регрессии (нарушения другой части системы, к которой вы не должны прикасаться).

Чтобы минимизировать «влияние изменений» вы бы разбили их на отдельные службы / ограниченные контексты и разрешить взаимодействие только через события. «Контроллер» инициирует событие (на общей шине), например «запрос информации об отеле», и каждая отдельная услуга (свойство, цена и отзывы) будет отвечать независимо и асинхронно (возможно, на одной шине), оставляя контроллер в агрегировать результаты и возвращать их клиенту, что можно сделать через некоторое время. Если вы закодируете агрегатор результатов соответствующим образом, можно будет добавить новые «функции» или полностью удалить существующие независимо от других.

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

...