web-dev-qa-db-ja.com

アーキテクチャレビュー-ケーススタディ(Spring MVC)

Java Springを使用したWebアプリケーションを開発しています。アーキテクチャについていくつか質問があります。表示する前に、context

  • データベースに80を超える既存のテーブルがあるWebアプリケーションを開発しています。
  • アプリケーションとデータベースの両方が同じサーバーマシン上にあります。
  • 私のアプリケーションは将来成長するので、必要に応じて、データベースはマシン内だけにあり、Webアプリケーションは別のマシンからアクセスします。
  • 今、私はすべてを行いますが、将来的には、それぞれの領域やレイヤーで特定の専門家が私と一緒に作業するようになります。
  • (EDIT)私はシステムをゼロから開発しているため、データベースのモデリングと準備を担当しています。つまり、私はすべてを一人でやっています。

これが私のアーキテクチャの一般的なモデルです:

enter image description here

私がコメントしたい特定のポイントがあります(clarificationの場合):

  • 主なコンポーネントは、SERVICE、DAOなど、白で強調表示されています。これらのコンポーネントは、相互にデータを交換することによって通信し、アクションを実行します。
  • 緑と灰色のコンポーネントは、メインコンポーネント間で交換されるデータのタイプを表します。
  • アーキテクチャはレイヤーへの分離を示しています。

この提示されたモデルに関連して、私はいくつかの質問を持っています:

  • 緑の要素は疑問/混乱を表しています。 「???」が付いているものは、私が知らないデータ型です。ここにはどのタイプのデータを入れればよいですか? (正しいタイプを交換するために)これには翻訳者が必要ですか?
  • 他のタイプの書き込まれたデータ( "DOMAIN MODEL ENTITY"-これはJPAエンティティ、@ Entity)は正しいですか? DAOレイヤーはこれらのタイプのオブジェクトのみに関係するべきであり、ケアすることは完全に独立しているべきだと思います。
  • DAOタイプは単一のエンティティのみに関係する必要があることを知っているので、クエリパラメーターは常にそれらのフィールド/属性/プロパティです。ただし、その関係の1つに存在するパラメーターが必要なエンティティを検索する必要がある場合はどうなりますか?たとえば、先月購入したXより大きい値を持つすべてのユーザーを検索しますか?この場合、Purchaseエンティティにある詳細が必要です。これをDAOに入れますか?また、サービスクラスに配置する必要がある場合は、サービス内にEntityManagerも設定する必要があります。これにより、DAO永続化レイヤーの目的がなくなる可能性があります。
  • 最後に、この建築モデルは私がやりたいことに対して間違っていますか?修正する必要があるものはありますか?

明確に言うと、この組織では、次のような状況に影響を与える可能性があります。

enter image description here

このスキーム/図は、コントロールからDAOへの呼び出し(ユーザーコントロールからUserDAOへの呼び出し)を示しています。

たとえば、使用する永続化実装を制御の反転で選択できることがわかります。ここにも何か問題があるかどうか知りたい

ありがとうございました。

注:正しい方法を探していません。私は物事がどういうものか知っています。私はこのモデルを完成させたいと考えています。システムのメンテナンスとそのコンポーネントの分離の能力を考慮して、私がやりたいことにそれが当てはまるかどうかを考えています。それだけ。

編集2

だから...よく考え、研究し、頭を悩ませた結果、ようやく結論に達することができたと思います。

  • 自殺します...

...いや、冗談だよ!ここに結論があります:

enter image description here

各コンポーネントの各バルーンは、コンポーネント自体の紹介であり、それらの責任を明らかにしています。これはばかげているように見えるかもしれませんが、それぞれの責任の違いをうまく表現しています。

状況によっては、一般化することができません。サービスが常にDTOを返すとは限りません。同様に、サービスがアクションを実行するために単純なパラメーターを必要とするわけではありません。したがって、制御とサービスの間のデータ交換は異なる場合があります。

アプリケーション層とビジネス層は同じもの、同じサーバーマシンで実行される同じシステムにすることができます。ある日、あなたは物事を分離したいと思うかもしれません。 Webサーバーのビジネスレイヤーを有効にすると、特定のビジネスのサービスを使用するために複数のタイプのクライアントアプリケーションを使用する場合に役立ちます。

コード生成ツールを使用すると、次のようなものをほんの数分で生成できます。

  • ドメインモデルエンティティ。
  • DTO。
  • フォームオブジェクト(クラス)。

同じツールでDAOクラスを生成することもできますが、私が見たところ、それらは完全ではなく、修正が必要になります。サービスクラスは、それぞれのケースに非常に特有です。このタイプのコードを生成するためのツールはないので、ゼロから作成する必要があると思います。

3
Loa

緑の要素は疑問/混乱を表しています。 「???」が付いているものは、私が知らないデータ型です。ここにはどのタイプのデータを入れればよいですか? (正しいタイプを交換するために)これには翻訳者が必要ですか?

これは好みの問題であり、個人的にはDTOを使用するのは好きではありません。それらは主にビジネスクラスを複製することで書き込みアダプターを作成し、遅延読み込みなどの機能をかなり混乱させるためです。さらに、フィールドを追加する必要があるたびに、どこにでもフィールドを追加して、すべてを再テストする必要があります。

だから私がやったことはビジネスモデルだけを持っていて、それに必要なすべての注釈(jpa/jackson)を付けました。

はい、これは私のアプリケーションをjpa/jacksonにバインドします。これは、私のアプリケーションがSpringに大きく依存しているためですが、これらすべてを適切に分離すると、変更されないものに対してかなり多くの作業が追加されます。他の注釈(XMLシリアル化)が必要な場合は、後で追加するか、最後にこれだけのDTOレイヤーを追加します。これは事の複雑さに依存します。

他のタイプの書き込まれたデータ( "DOMAIN MODEL ENTITY"-これはJPAエンティティ、@ Entity)は正しいですか? DAOレイヤーはこれらのタイプのオブジェクトのみに関係するべきであり、ケアすることは完全に独立しているべきだと思います。

前に述べたように、JPAのすべての機能を使用したい場合は、使用しないでください。 JPAを抽象化すると不必要に複雑で非効率的なコードが生成されるため、同じことを聞かれたStackoverflowでの私の質問は次のとおりです。 https://stackoverflow.com/questions/37811139/good-usage-of-managed- entities-proxies-with-orm

DAOタイプは単一のエンティティのみに関係する必要があることを知っているので、クエリパラメーターは常にそれらのフィールド/属性/プロパティです。ただし、その関係の1つに存在するパラメーターが必要なエンティティを検索する必要がある場合はどうなりますか?たとえば、先月購入したXより大きい値を持つすべてのユーザーを検索しますか?この場合、Purchaseエンティティにある詳細が必要です。これをDAOに入れますか?また、サービスクラスに配置する必要がある場合は、サービス内にEntityManagerも設定する必要があります。これにより、DAO永続化レイヤーの目的がなくなる可能性があります。

DAOレイヤーは、定義上、モデルの関係を認識しています。もちろん、彼はサブフィールドなどに対してクエリを実行できます。 DAOレイヤーはエンティティマネージャーであると考えたので、DAO /サービスについてあまり具体的でない限り、これに合うサービスレイヤーしかありません。

最後に、この建築モデルは私がやりたいことに対して間違っていますか?修正する必要があるものはありますか?

私が言ったように、私はいくつか異なることをしましたが、あなたのモデルは良いです:

  • DAOは永続性のみを処理し、ビジネスロジック/トランザクションは処理しません。
  • サービスはビジネスロジックとトランザクションを処理します。
  • コントローラはビ​​ジネスロジックとトランザクションを処理しません。

あなたは正しい基盤を持っています。

2
Walfrat

Walfratの回答には多少同意しませんが、DTOがアプリケーションに適しているかどうかを判断する前に、最初に決定する必要があるいくつかの重要な考慮事項があると思います。彼の答えは間違っていません。実際、DTOは保守性のコストであり、DRY原則の違反の可能性があります。ただし、特定の状況では、ドメインとしてJPAエンティティを使用すると思います。サービスとコントローラーのモデルエンティティは誤りです。

データベースに80を超える既存のテーブルがあるWebアプリケーションを開発しています。

既存のスキーマがある場合、これは通常、レガシーソフトウェアコンポーネントを段階的に廃止し、新しいソフトウェアコンポーネントに置き換えることを意味します。この時点でレイヤーを適切に分離することの重要性が高まります。これは、ある時点で、次の2つのうちの1つがおそらく発生する可能性があるためです。

  1. データベースは将来的にリファクタリングまたは置き換えられる可能性があります
  2. 他のレガシーアプリケーションがこのデータベースと相互作用し、そのスキーマに影響を与える可能性があります。

ポイント2の場合、他のレガシーソフトウェアコンポーネントによるわずかな影響でさえ、アプリケーション層に影響を与える可能性のある波及効果を送信する可能性があります。 (例:JPAエンティティは、スキーマの変更、サービスレイヤーの変更、コントローラーとエンティティのJSONマッピングの変更、JSPとJavascriptの変更、JSON構造の変更などの可能性があるため、変更する必要があります。)

DTOを維持するためのケースは、あなたの特定のインスタンスで強力なものだと思います。これにより、レイヤーがさらに分離され、多くの利点があります。

  1. 各コンポーネントはより個別に単体テスト可能です
  2. JPAマッピングとエンティティの変更は、サービスおよびコントローラドメインモデルエンティティから抽象化されます。
  3. JSONマッピングとプレゼンテーションエンティティバインディングは、データベースから切り離されています。

これがあなたのアーキテクチャへの最良のアプローチだと思います。

1
maple_shaft