3

Struts、Spring、Hibernateを使用する大規模なJavaアプリを継承しました。私が毎日扱っているクラスとインターフェースは、Strutsアクション、Struts ActionForms、値オブジェクト、サービスインターフェースと実装、DAOインターフェースと実装、およびエンティティです。ActionForms、Value Objects、およびEntitiesの間の責任の正しい分離について確信が持てないことを除いて、これらのほとんどの方法と理由についてはかなり明確です。また、ドメインモデル(つまり、すべてのエンティティ)には、実際のビジネスロジックが(あるとしても)あまり含まれていないことにも言及する必要があります。これは本質的にCRUDアプリであり、実際のロジックのほとんどはデータベースにあります(うん!)。とにかく、私が疑問に思っているいくつかの明確なJava関連の問題があります。

1)エンティティと値オブジェクト(VO)の間に大きな違いはないようであり、どちらかの方向にサービスレイヤーを通過するときに、他のオブジェクトに変換するために多くのコードを記述する必要があります(Strutsアクションは処理するだけです) VO、DAOはエンティティのみを扱います)。したがって、VOとエンティティはやや冗長に見えます。なぜ両方を持っているのですか?

2)VO <->エンティティ変換コードはどこに配置する必要がありますか?サービスレイヤー、エンティティ、VO?

3)VOはActionFormsに直接配置され、JSPのタグに直接バインドされます(例)。これは良い習慣ですか?そうでない場合、適切なデザインは何ですか?

4)値オブジェクトで外部キーの依存関係を適切に処理する方法が不明です。たとえば、特定のVOには、データベース用語で、タイプテーブルへの外部キー関係を表すタイプフィールドがあります。UIでは、これは、ユーザーがタイプを選択できるドロップダウンフィールド、またはタイプのテキスト表現を単に表示するラベル(画面によって異なります)に変換されます。さて、VOには、タイプID、タイプのテキスト表現、またはその両方のプロパティが必要ですか?誰がいつ、2つの間を翻訳する責任がありますか?

5)VOには、データベースIDのフィールドがあります。VOにはアイデンティティがないと思いましたか?これはどうしたの?

これらの質問が一般的な関心を引くのに十分一般的であることを願っています。これは、このタイプのアーキテクチャでは常に発生するようです。

また、このアーキテクチャはこのアプリにとって非常に重いのではないかと疑っています。より良いアーキテクチャについて提案がある場合は、先に進んでください。ただし、別のアーキテクチャは長期的なリファクタリングであり、現在は実行できないため、主に上記の質問への回答に関心があります。

4

3 に答える 3

3

1. DAO - VO 変換を考慮する。これが役立つかどうかは、Hibernate の使用方法によって異なります。Web リクエスト処理全体が 1 つの Hibernate セッション内にある場合、別個の VO は実際には必要ありません。

ただし、DAO レイヤーがオブジェクトを取得するためにセッションを開き、DAO の使用が終了する前にセッションを閉じると、コレクションや他のオブジェクトへの参照で問題が発生する可能性があります。これらが遅延ロードされる可能性はかなりあります。つまり、これらのプロパティを要求するときにセッションを開く必要があります。

つまり、これらの VO を捨てる前に、データベースのトランザクションとセッションの境界をよくよく見てください。

3. フォームで VO を使用する場合。VO が JSP に適切にマップされている場合、なぜそうしないのでしょうか? データ モデルがサポートするプロセスと非常によく一致していることに感銘を受けました。また、データベースが正規化されていないことに少し疑いを持っていました (将来的に問題が発生する可能性もあれば、発生しない可能性もあります)。

1 に戻ります。遅延ロードとコレクションで DAO を使用する場合は、データベース セッションに JSP フェーズも含める必要があることに注意してください。DAO はそのフェーズで読み取られるためです。

  1. サービス層には、どのデータベース オブジェクトを変更するかを知る機能が必要であり、id はまさにそれを行うように設計されています。サービス層はデータベースから DAO を取得し、DAO の VO からフィールドを書き込む必要がありますが、明らかに DAO の ID を VO の ID で更新する必要はありません :)

  2. リクエストから必要なのは、外部キー フィールドの ID です。クライアントから送信されるため、そのような ID を持つオブジェクトが存在するかどうかをビジネス ロジックで確認する必要があります。

VO が外部オブジェクトの ID を受け入れるか、オブジェクトを必要とするかに応じて、次のいずれかを行う必要があります。

  • IDを設定する、または
  • サービスレイヤーを使用してIDで外部オブジェクトをVOとして取得し、VOに入れ、サービスレイヤーを使用して保存します

サービス層はオブジェクトの取得と保存のみを扱うため、ビジネス層は翻訳を担当します。また、テキストまたは ID はオブジェクトではなく、オブジェクトの識別子です。サービス層は検索機能を提供する場合がありますが、コンテキスト情報は必要ありません。

そして、私があなたの質問を正しく読んだ場合、あなたの VO はデータベース内の他のオブジェクトを ID で参照しています。その場合、ID を入力します。クライアントから文字列を取得した場合は、(サービス層を使用して) ビジネス層で検索し、見つかったオブジェクトの ID を VO に入れる必要があります。または、ID が見つからない場合は、適切なエラー メッセージを返します。

結びのメモとして; 本当によくやっていることがわからない限り、DAO-VO のことには触れないでください。Hibernate は、一見簡単に使える強力で複雑なツールです。非常に簡単に間違いを犯す可能性があり、それらを見つけるのは非常に困難です。また、顧客も上司も、以前は機能していた機能にバグが導入されることを歓迎していないようです。

ところで; DAO-VO に関する私の保守主義は、​​EJB2 から Hibernate への移行における同様の問題による問題を修正することから来ています。悪魔は細部に宿ります。データ レイヤーの処理方法を変更することは、たとえ簡単に思えるとしても、大きなリファクタリングです。

于 2008-10-03T20:58:03.513 に答える
1

1) 個別の VO とエンティティは必要ありません : 一部の企業は、プロジェクトにそのような構造を義務付けています。別のプロジェクトで意味があった可能性があるため、義務付けられました(私は推測することしかできません)

2) サービス層 : DAO とアクション層からの自然な分離ですよね?

3) 害はありませんが、値オブジェクトは、DAO に送信される前に適切に検証されている限りバインドされます。

4) サービス層は、2 つの間の変換を担当する必要があります。読み込み時と保存時

5) ID がない場合、重複を防ぐにはどうすればよいですか?

これらの簡潔な回答がお役に立てば幸いです。後で戻って、より長い答えを出そうとします。

于 2008-10-03T15:51:27.987 に答える
0

最後の部分に答えるには、Strutsの代わりにSpringMVCを使用してください。次に、すべてのレイヤーで同じドメインオブジェクトを使用できます。フォームパラメーターにバインドするクラスはHibernateでも使用され、実際のビジネスロジックが含まれています。

たとえば、Spring MVCを使用して行ったアプリでは、メンバークラスがありました。ログイン、登録、パスワードの変更、およびプロファイルの編集フォームはすべて、このクラスにバインドされていました。このクラスには、休止状態のマッピングと、内部にかなりのビジネスロジックもありました(たとえば、ソーシャルネットワークの場合は「友達を追加」メソッド)。

于 2008-10-03T20:20:39.423 に答える