この質問は、その中核となる設計上の問題です。 Java/Java EEの例を使って質問を説明します。デザイン:ドメインオブジェクトとサービスオブジェクトの間の線が明確でないとき
永続性のためにJPAを、サービス層にEJBを使用して構築されたWebメールアプリケーションを考えてみましょう。
public void incomingMail(String destination, Message message) {
Mailbox mb = findMailBox(destination); // who cares how this works
mb.addMessage(message);
}
このように、私たちはEJBのサービスメソッドを持っているとしましょう。これは一見合理的なビジネスメソッドです。おそらくメールボックスオブジェクトは引き続きアタッチされ、変更内容をデータベースにシームレスに保存します。結局のところ、それは透明な持続性の約束です。
メールボックスオブジェクトは、このメソッドを持っているでしょう:
public void addMessage(Message message) {
messages.add(message);
}
それが複雑になるのはここだ - 私たちは、他のメールボックスの種類を持つようにしたいと仮定します。送信者に自動的に応答するAutoRespondingMailboxと受信した電子メールごとにヘルプデスクチケットを自動的に開くHelpDeskMailboxがあるとします。
行うには自然な事はAutoRespondingMailboxは、このメソッドを持っているメールボックスを拡張するために、次のようになります。
public void addMessage(Message message) {
String response = getAutoResponse();
// do something magic here to send the response automatically
}
問題は、私たちのMaiboxオブジェクトであり、それはサブクラスはまた、「ドメインオブジェクト」です(この例ではですJPAエンティティ)。 Hibernateの人たち(そして他の多くの人)は、依存しないドメインモデル、つまりコンテナ/ランタイム提供サービスに依存しないドメインモデルを宣言しています。そのようなモデルの問題は、AutoRespndingMailbox.addMessage()メソッドは、たとえばJavaMailにアクセスできないため、電子メールを送信できないということです。
HelpDeskMailboxでは、HelpDeskシステムと通信するWebServicesまたはJNDIインジェクションにアクセスできなかったため、まったく同じ問題が発生します。
ですから、このように、サービス層でこの機能を置くことを余儀なくしている。そのようにinstanceofを使用する必要が
public void incomingMail(String destination, Message message) {
Mailbox mb = findMailBox(destination); // who cares how this works
if (mb instanceof AutoRespondingMailbox) {
String response = ((AutoRespondingMailbox)mb).getAutoResponse();
// now we can access the container services to send the mail
} else if (mb instanceof HelpDeskMailbox) {
// ...
} else {
mb.addMessage(message);
}
}
は、問題の最初の兆候です。メールボックスをサブクラス化するたびにこのサービスクラスを変更することは、問題のもう一つの兆候です。
誰もこれらの状況の処理方法に関するベストプラクティスを持っていますか?何人かは、メールボックスオブジェクトはコンテナサービスにアクセスしなければならないと言っています。これはいくつかのファジシングで行うことができますが、JPAの意図された使い方と戦うのは間違いありません。これは予想されるユースケースではないということです。
代わりに何をする予定ですか?私たちのサービス方法をリサイズし、多形性をあきらめますか?私たちのオブジェクトは自動的にCスタイルの構造体に降格し、オブジェクト指向の利点のほとんどを失います。
Hibernateチームは、ドメイン・レイヤーとサービス・レイヤーの間でビジネス・ロジックを分割し、コンテナーに依存しないすべてのロジックをドメイン・エンティティーに入れ、それに依存するすべてのロジックコンテナをサービス層に追加します。誰かが多態性を完全にあきらめたり、インスタンスや他の不幸に頼らなくても、私がどのように行うかの例を私に与えることができれば、私はそれを受け入れることができます
私の質問の意図を忘れてしまったと思います。この例の詳細を忘れて、エンティティのいくつかのサブクラスがコンテナ提供サービスに依存する動作を必要とすると仮定します。 – TTar
私はこれに同意します。問題は、ドメインオブジェクトがもはやデータの単純な所有者ではなくなったことですが、今では(永続性に影響を与えた)振る舞いをそれに関連付けました。個人的には、これはサービスレベルで処理されるべきもののような感じです。 –
ドメインオブジェクトがデータの単純な所有者である場合、私のドメインオブジェクトは単なる構造体ではありませんか?オブジェクト指向設計の定義は、データとビヘイビアがオブジェクトに結合されているのではないのですか? – TTar