データ中心のアプローチによるSpringMVCでのクリーンなアーキテクチャの維持
作業中の新しいJavaベースのWebアプリ(ポータルタイプのアプリケーション)のフロントエンドのアーキテクチャを計画しようとしています。私はこれを初日から正しく理解したいと思っています。ここで議論を開始して、ボブおじさんのクリーンアーキテクチャを建築設計に実装するのに役立てたいと思います。
これが私たちの技術スタックの簡単な要約です(技術は重要ではなく、構造は重要です):
- Oracleデータベース
- WSDLを使用してサービスを公開するOracleServiceBus
- JAX-WSはWSDLからJavaクラスを生成しました(これを「生成されたサービス層」と呼びましょう)
- 生成されたデータオブジェクトにマップされたPOJOで構成されるドメインモジュール
- 「生成されたサービスレイヤー」をフロントエンドアプリケーションに公開するコンシューマーモジュール
- FreeMarkerを使用してビューをレンダリングするSpringMVCベースのフロントエンドモジュール
キーポイント:
特に、外側の円で宣言されたものの名前は、内側の円のコードで言及してはなりません。これには、関数、クラスが含まれます。変数、またはその他の名前付きソフトウェアエンティティ。
ボブのクリーンアーキテクチャに固執しようとして、アプリケーションロジック、つまり彼のアーキテクチャの「ユースケース」レイヤーをどこに配置するかについて、私は自分自身と少し行き来しました。
これが私が思いついたアプローチです:
レイヤー1-エンティティ
エンティティは、エンタープライズ全体のビジネスルールをカプセル化します。
これは、ドメインオブジェクトを含むドメインモジュールが存在する場所です。これらは、相互依存が最小限の自己完結型オブジェクトです。オブジェクト自体に関連するロジックのみがこれらのドメインオブジェクトに存在でき、ユースケース固有のロジックは存在しません。
データベースへのアクセスは、JPAやHibernateのようなORMとは対照的に、データを変換するサービスバスを使用してWSDLを介して公開されます。このため、従来の意味での「エンティティ」(IDを使用)はありませんが、このレイヤーをデータアクセスレイヤーにするデータ中心のアプローチで、コンシューマーモジュールによってアプリケーションの残りの部分に提示されます。
レイヤー2-ユースケース
この層のソフトウェアには、アプリケーション固有のビジネスルールが含まれています。
これは、アプリケーションのユースケースに固有のロジックが存在する場所です。この層への変更は、データアクセス層(層1)に影響を与えないはずです。GUIまたはフレームワークの実装(Spring MVC)を変更しても、このレイヤーには影響しません。
ここで少し
注意が必要です。データアクセス層(層1)はアプリケーションロジックをクリーンに保つ必要があるため、ユースケースに適した方法でその層の使用を容易にする層が必要です。この問題に対して私が見つけた解決策の1つは、MVC-VMと呼ぶことを選択した「 MVVMパターン」のバリアントを使用することです。説明については、以下を参照してください。この「VM」の一部は、このユースケース固有のロジックをカプセル化するクラスで表されるこのユースケースレイヤーに存在します。*ViewModel
レイヤー3-インターフェースアダプター
このレイヤーのソフトウェアは、データをユースケースやエンティティに最も便利な形式から、データベースやWebなどの外部機関に最も便利な形式に変換する一連のアダプターです。
これは、GUIのMVCアーキテクチャ(「MVC-VM」の「MVC」)が存在する場所です。基本的に、これは、Controller
-classesが-classesからデータを取得し、*ViewModel
それをModelMap
ビューのFreeMarker-templatesによって直接使用されるSpringMVCのオブジェクトに配置する場合です。
私の見方では、サービスバスもこの層に分類されます。
レイヤー4-フレームワークとドライバー
通常、このレイヤーには、内側の次のサークルと通信するグルーコード以外のコードはあまり記述しません。
このレイヤーは、実際にはアプリケーションの構成レイヤー、つまりSpring構成にすぎません。これは、たとえば、FreeMarkerを使用してビューをレンダリングすることを指定する場所です。
モデルビューViewModelパターン
MVVMは、グラフィカルユーザーインターフェイス(マークアップ言語またはGUIコードとして)の開発を、モデル(ビューと区別するためのデータモデルとも呼ばれる)と呼ばれるビジネスロジックまたはバックエンドロジックの開発から明確に分離することを容易にします。モデル)。MVVMのビューモデルは値コンバーターです。つまり、ビューモデルは、モデルからのデータオブジェクトを簡単に管理および使用できるように、それらのオブジェクトを公開する役割を果たします。
ウィキペディアのMVVMパターンの詳細。
MVC-VMの役割は、次のようにアプリケーションで実行されます。
- モデル-
ModelMap
ビューテンプレートで使用されるSpringMVCのデータ構造で単純に表されます。 - 表示 -FreeMarkerテンプレート
Controller Springの
Controller
-HTTPURLリクエストを特定のハンドラー(およびFrontControllerなどの関数)に送信するクラス。これらのクラスのハンドラーは、データを表示するときにユースケースレイヤーからデータをフェッチしてビューテンプレートにプッシュし(HTTPGET
)、保存するためにデータを送信します(HTTPPOST
)。このように、モデルを使用して、基本的にViewModelとViewの間のバインダーとして機能します。ViewModel-これらのクラスは、1)ビューで使用できる方法でデータアクセス層からのデータを構造化し、2)ビューからのデータ入力を処理する役割を果たします。「処理」とは、データを検証して分解し、データをスタックに送信して保存できるようにすることを意味します。このレイヤーは、
<UseCase>VM
SpringMVCviewmodel
フロントエンドモジュールのパッケージ内のクラスとして形成されます。
ModelMap
ここでの重要なコンポーネントは、SpringMVCでとFreeMarker-templatesの間で発生する暗黙的なバインディングです。テンプレートModelMap
は、コントローラーが使用可能な形式でデータを配置したモデル(s)のみを使用します。そうすれば、次のようなテンプレートを作成できます。
<body>
<h1>Welcome ${user}!</h1>
<p>Our latest product:
<a href="${latestProduct.url}">${latestProduct.name}</a>!
</body>
冗長な説明をお詫びしますが、この(比較的単純な)アーキテクチャをより少ない言葉で説明することはできませんでした。
ここでの私のアプローチに関するいくつかの意見をいただければ幸いです-私は正しい方向に進んでいますか?MVC-VMのことは意味がありますか?クリーンアーキテクチャの原則に違反していますか?
もちろんこれには多くの解決策がありますが、私は1)過剰に設計されておらず、2)ボブのクリーンアーキテクチャの原則に準拠している解決策を見つけようとしています。
アップデート:
ここで私を思いとどまらせる重要な問題は、このアプリケーションで「ユースケース」レイヤーがどのような形をとるかということだと思います。データアクセス層からデータを取得するMVCフロントエンドがあることを忘れないでください。MVCパーツがBobの「インターフェイスアダプター」に適合し、データレイヤーのドメインモデルがBobの「エンティティ」レイヤーに適合する場合、アプリケーションロジックを実装するユースケースクラスを何と呼びますか?私はそれらを<UseCase>Model
sと呼んで、MVCプロジェクトに入れたいと思っていますが、Bobによると
モデルは、コントローラーからユースケースに渡され、ユースケースからプレゼンターとビューに戻される単なるデータ構造である可能性があります。
つまり、モデルオブジェクトは「ダム」(Springの単純なMap
。ModelMap
のように)である必要があり、ユースケースクラスのデータをこのMap構造に配置するのはコントローラーの責任です。
繰り返しになりますが、私のユースケースクラスはどのような形式を取りますか?どう<UseCase>Interactor
ですか?
しかし、結論として、MVC-MVのものは過剰に設計されている(または単に正しくない)ことに気付きます。「mikalai」は、この下に、現在の形式では本質的に2層のアプリケーションを示しています。データアクセス層とフロントエンドMVC層。そのような単純な。