web-dev-qa-db-ja.com

マイクロサービス間でのDTOオブジェクトの共有

TL; DR-サービス間でPOJOライブラリを共有しても問題ありませんか?

一般的に、サービス間の共有は、可能な限り厳密になしに制限することをお勧めします。データを共有しているサービスがクライアントが使用するクライアントライブラリを提供する必要があるかどうかについては、いくつかの議論があります。 client-libは通常、サービスのクライアントが使用するオプションであり、APIを使用できますが、client-libを使用するか、代替言語を使用してライブラリの一般的な側面を使用するかなど、好きなように使用できます。

私の場合-データのオブジェクトを作成するサービスを検討しています。このオブジェクトがPETであると仮定しましょう。これはデータベースエンティティではありませんが、基になるデータを暗黙的に表すPOJOです。このPOJOは、APIが定義したものです。想定:ペット-年齢、体重、名前、所有者、住所、種など.

Service 1-PetKeeper:何らかの理由でペットを生成し、すべてのデータを保持します。このサービスを参照してペットを取得したり、ペットを変更したり、名前を変更したり、アドレスの変更は、このサービスへのAPI呼び出しを通じて行う必要があります。

サービス2-PetAccessor:このサービスはペットを収集し、検証チェックを行います

サービス3,4-より多くの中間サービス呼び出し

サービス5-ユーザーインターフェイス

これらは非常に恣意的ですが、要点は簡単です。 UIまたは一部のユーザー向けサービスは、この「PET」オブジェクトを何らかの方法で提示したいと考えています。必要な情報を収集してリレーバックを開始するサービスに到達するまで、APIを介してサービス(サービスを呼び出すサービス、サービスを呼び出すなど)を呼び出す必要があります。最後に、UIサービスには表示するPETオブジェクトがあります。

これはかなり一般的ですが、私たちの絶対的な考え方では、PETオブジェクトをすべてのサービスに複製しました。DRY(繰り返さないでください))原則は、サービス内にコードを記述し、サービス全体には適用されませんが、ポイントはまだあります。フィールドを追加するとどうなりますか?それぞれのPOJOの5つのサービスを変更する必要があります。

-または-APIからのpojoの一部を含むPet-Objects-Libraryを提供でき、各サービスはライブラリにインポート/依存できます。サービス自体への依存はなく、一般的なライブラリのみです。各サービスに同じタイプのオブジェクトがあり、更新が簡単になるように、このアイデアが気に入っています。しかし、私は神オブジェクトについて心配しています。

プロ/デメリットは何ですか-最高のデザインは何ですか?同じPOJOクラスの繰り返しを最小限に抑えながら、分離されたままにするために、サービス間でデータを渡すために何をしましたか?

15
Aerith

最高のデザインは何ですか?

同じPet[〜#〜] dto [〜#〜]オブジェクトを(一般的なビジネスロジックを処理する)バックエンドサービス間で再利用できますが、プレゼンテーション層(ユーザーインターフェイス)については、FormBean(プレゼンテーションロジック用のフィールドが追加された別のBean)を使用してプレゼンテーションロジックとビジネスロジックが明確に分離されます

サービスは再利用可能である必要があり、単一のサービスが複数の/異なるエンドポイント(フロントエンドまたは別のWebサービスなど)によって公開/再利用できるため、これが必要です。これらのエンドポイントの場合、サービスの上のそれぞれのコントローラーまたはレイヤー(アダプターなど)によって入力される追加のフィールドが必要になる場合があります。

同じPOJOクラスの繰り返しを最小限に抑えながら、分離されたままにするために、サービス間でデータを渡すために何をしましたか?

ビジネス層とWeb層の間で単一のBeanを使用する場合、プレゼンテーションロジックとビジネスロジックを緊密に結合しているこれは良い方法ではなく、要件のサービスを変更することになりますフロントエンド(たとえば、ユーザーインターフェイスに表示される別の日付形式)また、(DTOからFormBeanまたはViceversaへのような)Bean全体にデータを入力/コピーするこのプロセスを行うには、ApacheBeanUtils.copyProperties()または Dozerは、定型コードを回避します。

5
developer

DTOがすべてのマイクロサービスで同じビジネスエンティティを表す場合、サービス間で共有されるクラスは1つだけです。同じオブジェクトに対して重複したコードを使用することは(ほとんど)正しくありません。

4
Jim Garrison

私が今それを行うことを計画する方法は、各サービスがDTOのみをパッケージ化し、それらをjar libとしてNexusに入れることです。他のサービスがそれらを必要とする場合、manve/gradleの依存関係としてDTOライブラリを取得します。 1つのサービスで新しいDTOバージョンがリリースされた場合、古いバージョンも同時にサポートされている限り問題ありません。下位互換性、バージョニングなどを壊さないでください。これがバックエンド間のバックエンド領域です。 循環依存を防ぐために、サービスをdtoパッケージングから分離することをお勧めします

バックエンドからフロントエンド、およびその逆を見てくださいプレゼンテーションレイヤーとしてのUIが異なるという以前のコメントに同意しません。 IT IS NOT !!! UIは、イベントを消費および生成するマイクロサービスの1つにすぎません。

バックエンドからフロントエンドへの方向 POJO(dtos)をTypeScriptインターフェースに変換し、NPMにパッケージ化して、Nexusにもロードします。 UI nodejsベースのプロジェクトは、それらを消費して使用します。これは、UIへのサービスです。

フロントエンドからバックエンドへの方向 UIからサービスレイヤーイベントに、TypeScriptインターフェースを変換してPOJO(dtos)に変換し、jarとしてパッケージ化し、jarの形式でNexus(またはいくつかのリポジトリ)にアップロードしてバックエンドサービスによって消費されます。

これらのプロセスは、CIプロセス(Travis、Gitlab CIなど)によって簡単に処理されます。

このアプローチに対するコメントは歓迎されます。

1
kensai