次の2つのオプションのどちらが適切なアプローチであり、その理由を理解しようとしています。
コントローラーまでWebから呼び出されるGetHotelInfo(hotel_id)
APIがあるとします。
GetHotelInfoのロジックは次のとおりです。
GetHotelPropertyData()
を呼び出す(場所、施設…)GetHotelPrice(hotel_id, dates…)
GetHotelReviews(hotel_id)
すべての結果が返されたら、データを処理してマージし、ホテルのすべての関連データを含む1つのオブジェクトを返します。
オプション1:
3つの異なるリポジトリ(HotelPropertyRepo、HotelPriceRepo、HotelReviewsRepo)を作成します。
これら3つのリポジトリを使用し、最終結果を返すGetHotelInfoユースケースを作成します。
オプション2:
3つの異なるリポジトリ(HotelPropertyRepo、HotelPriceRepo、HotelReviewsRepo)を作成します。
3つの異なるユースケースを作成(GetHotelPropertyDataUseCase、GetHotelPriceUseCase、GetHotelReviewsUseCase)
前の3つのユースケースを調整するGetHotelInfoUseCaseを作成します。 (コントローラになることもありますが、それは別のトピックです)
現在、GetHotelInfo
のみがWebに公開されているとしましょう。将来的には、内部リクエストの一部も公開する予定です。
また、GetHotelInfoの実際のロジックが3つのエンドポイントの組み合わせではなく10の場合、答えは異なりますか?
期待されるインタラクター(ユースケースクラス)は他のインタラクターを呼び出します。したがって、どちらのアプローチもクリーンアーキテクチャの原則に従います。
しかし、 "たぶん将来的に"句は、優れた設計およびアーキテクチャの慣例に反します。
再利用を優先できるように、最も抽象的な方法を考えることができます。しかし、常に物事をシンプルに保ち、不必要な複雑さを避けます。
GetHotelInfoの実際のロジックが3つのエンドポイントの組み合わせではなく、10の場合、答えは異なりますか?
いいえ、同じです。ただし、APIを設計しているときに、数十のエンドポイントの組み合わせが必要な場合は、プロジェクトを複雑にするのではなく、GraphQLレイヤーを配置することを検討する必要があります。
同様のメソッド(Get()
と呼ばれます)は、「 GOを使用したクリーンアーキテクチャ黒田真奈
マナトはそれを指摘している:
そのため、例のリポジトリ manakuro/golang-clean-architecture
では、Manatoはユースケースのレイヤー3ディレクトリを作成します。
その例を使用して、hotel_interactor.go
ファイルで最初に宣言されたGetHotelInfo
を使用し、hotel_repository
で宣言された特定のビジネスメソッドとhotel_presenter
で定義された応答に応じて、ケースを適応させることができます。
クリーンは明確に定義された用語ではありません。むしろ、変更の影響(サービスの追加または削除)を最小限に抑えることを目的とする必要があります。 「影響」とは、コストと時間の要素だけでなく、回帰を導入するリスク(システムの別の部分を壊すことを意図していない)も意味します。
「変更の影響」を最小限に抑えるには、これらを個別のサービス/境界コンテキストに分割し、イベントを通じてのみ対話できるようにします。 「コントローラー」は「ホテル情報リクエスト」などのイベントを(共有バス上で)発生させ、個別のサービス(プロパティ、価格、レビュー)はそれぞれ独立して非同期に(おそらく同じバス上で)応答し、コントローラーは結果を集計してクライアントに返します。これは、一定期間後に行うことができます。結果アグリゲーターを適切にコーディングすると、新しい「機能」を追加したり、他の機能とは完全に独立して既存の機能を削除したりできるようになります。
これを改善するには、各コンテキストの読み取り機能と書き込み機能を独自のコンテキストに分離し、それぞれが適切なイベントに応答します。これにより、読み取り関数とは無関係に書き込み関数を最適化およびスケーリングできます。これをCQRSと呼びます。