オブジェクト指向とレイヤード。バランス“ OO純度”物事を成し遂げる

StackOverflow https://stackoverflow.com/questions/153394

  •  03-07-2019
  •  | 
  •  

質問

私はオブジェクト指向を信じていますが、不適切なデザイン/実装が「OO準拠」のためだけに使用されるべきではありません。

それで、Serlvet / EJB / DataContainer階層化アーキテクチャの取り扱い方法:

  • サーブレットはリクエストを受け取り、「ビジネス層」を呼び出します。 (例:セッションEJB)
  • ビジネスレイヤーはデータベースからDataContainerを見つけ、それらを操作してビジネスロジックを実装します
  • DataContainersには実際のコードは含まれていません。データベースに対応するget / setのみです。

このアプローチには魅力があります。 DataContainerの動作は明確であり、データがどこから来ているかを知るのは非常に簡単です。

オブジェクト指向ではないことを除けば、これは不明確なビジネス層クラスにつながり、名前を付けたり整理したりすることが難しくなります。

さらに「強く」しようとした 場合でも、 (たとえば、これらのメソッドの一部をDataConatinersに入れる)、これらの操作の一部は複数のデータセットで動作します。

どのようにして、ビジネスレイヤーが混乱を招くような手続きをとらないようにしますが、DataContainersをビジネスロジックで汚染することはありませんか

class UserServlet {
  handleRequest() {
    String id = request.get("id");
    String name = request.get("name");
    if (UserBizLayer.updateUserName(id,name))
      response.setStatus(OK);
    else
      response.setStatus(BAD_REQUEST);
  }
}

class UseBizLayer {
    updateUserName(String id, String name) {
        long key = toLong(id);
        user = userDAO.find(key);
        if user == null
            return false;
        if (!validateUserName(name))
            return false;
        user.setName(name);
        userDAO.update(user);
        return true;
    }

    validateUserName(String name) {
        // do some validations and return
    }
}

class User {
    long key;
    String name;
    String email;

    // imagine getters/setters here
}
  • ユーザーに対しては validateUserName は必要ありません。名前に対してのみ機能するためです。別のクラスに入る可能性があると思いますが、その後、別の手続き型の「uti」があります。型クラス
  • データ構造を永続化戦略から切り離すことに価値があるため、ユーザーに永続化メソッドは必要ありません
  • ビジネスロジックをサーブレットで使用したくないのは、そのロジックを他の場所で再利用する必要があるかもしれないからです
  • ユーザークラスにビジネスロジックを使いすぎて、ビジネスロジックの再利用が難しくなり、ユーザーを永続化戦略と結び付けるため、ユーザーにビジネスロジックが必要ない

この例はそれほど悪くないことを理解していますが、10個のDataContainersと20個のBizLayerオブジェクトがそれぞれいくつかのメソッドを持っていると想像してください。これらの操作の一部が「中心」ではないことを想像してください。特定のデータコンテナ。

これを手続きの混乱から守るにはどうすればよいですか

役に立ちましたか?

解決

だから、これに関する私の考えをいくつかの箇条書きで説明します:

  1. Java EEシステムでは、Java EEの配管に対処する必要がある時点で思われます。配管はOOの概念から常に恩恵を受けるわけではありませんが、確かに少しの創造性と作業が可能です。たとえば、AbstractFactoryなどの機能を利用して、このインフラストラクチャを可能な限り共通化できます。
  2. 調査対象の多くは、ドメイン駆動設計と呼ばれるEric Evansの優れた本で説明されています。彼はドメインの知識を表現し、それをサポートするための技術インフラストラクチャを扱う問題に取り組んでいるので、あなたがそれを見ることを強くお勧めします。
  3. DDDの一部を読み取り、GROKDして、技術インフラストラクチャをリポジトリにカプセル化します。リポジトリはすべて、セッションEJBに基づく永続性の戦略を使用するように作成されます。セッションEJBと通信する方法を知っているデフォルトの実装を作成します。これを機能させるには、少し規約を追加し、インターフェイスでその規約/契約を指定する必要があります。リポジトリはすべてのCRUDを実行し、絶対に必要な場合にのみそれ以上を実行する必要があります。 「私のDAOSは私のリポジトリです」と言ったら、同意します。
  4. これで続行します。 UseBizLayerで表現される作業単位をカプセル化する何かが必要です。このレベルでは、その性質は、すべてトランザクションスクリプトになるコードを書くのにこだわっていることにあると思います。あなたは責任と状態の分離を作成しています。これは通常、Java EEシステム内でデフォルトの種類のアーキテクチャとして行われているのを見てきました。しかし、それはオブジェクト指向ではありません。モデルを調べて、少なくともBizClassesに書き込まれる動作の一部を共通化できるかどうかを確認します。
  5. 私が以前に使用した別のアプローチは、BizLayerクラスを取り除き、ドメインからの呼び出しを、操作を実行する実際のリポジトリ/ DAOにプロキシすることです。ただし、これにはインフラストラクチャの構築にいくらかの投資が必要になる場合があります。しかし、Springのようなフレームワークで多くのことを行い、AOPコンセプトを使用してこれをうまく機能させ、必要なカスタムインフラストラクチャの量を削減することができます。

他のヒント

クラスとオブジェクトを実装しているので、ソリューションはオブジェクトの階層化方法に関係なくオブジェクト指向になります-状況/ニーズによってはあまり構造化されていないかもしれません! ;-)

特定の質問に関しては、validateUserNameがUserクラスに属することは、すべてのユーザーが有効な名前を持ちたいため、場合によっては意味があります。または、他の物には同じ検証ルールを使用する名前があると仮定して、検証ユーティリティクラスを作成できます。メールについても同じことが言えます。これらをNameValidatorクラスとEmailValidatorクラスに分割できます。これらを頻繁に使用するのであれば、これはすばらしい解決策になります。また、ユーティリティクラスメソッドを呼び出したばかりのUserオブジェクトにvalidateUserName関数を提供することもできます。これらはすべて有効なソリューションです。

OOD / OOPの大きな喜びの1つは、設計が正しい場合、それが正しいことを知っているということです。以前はできませんでした。

この場合、NameValidatorクラスとEmailValidatorクラスを作成します。他のエンティティには将来的に名前と電子メールアドレスが含まれる可能性が高いためです。使用するbizオブジェクト。

残りの「希望しない」箇条書きは正しい。それらは適切な階層化に必要なだけでなく、クリーンなオブジェクト指向設計にも必要です。

レイヤリングとオブジェクト指向は、レイヤ間の関心の分離に基づいて、手に手を入れます。あなたは正しいアイデアを持っていると思いますが、提示されているように一般的な検証のためにいくつかのユーティリティクラスが必要になります

コンピューターがなければこれらのタスクがどのように行われるかを考え、システムをそのようにモデル化します。

簡単な例...クライアントはフォームを記入してウィジェットをリクエストし、従業員に渡し、従業員はクライアントの身元を確認し、フォームを処理し、ウィジェットを取得し、ウィジェットとトランザクションの記録をクライアントに送信し、会社のどこかにトランザクションの記録を保持します。

クライアントはデータを保存しますか?いいえ、従業員は行います。従業員は、クライアントデータを保存するときにどのような役割を果たしますか?クライアントレコードキーパー。

フォームは正しく記入されたことを確認しますか?いいえ、従業員は行います。従業員はそれをしているときにどのような役割を果たしていますか?フォームプロセッサ。

クライアントにウィジェットを提供するのは誰ですか?ウィジェットディストリビューターとして機能する従業員

など...

これをJava EE実装にプッシュするには...

サーブレットはクライアントに代わって動作し、フォームに記入し(HTTPリクエストからデータを引き出し、適切なJavaオブジェクトを作成し)、適切な従業員(EJB)に渡します。行われなければ。リクエストの処理中に、EJBは異なるタスクに特化した別のEJBにそれを渡す必要があるかもしれません。その一部には、ストレージ(データ層)からの情報へのアクセス/ストレージへの情報が含まれます。類推に直接マッピングしてはならない唯一のものは、オブジェクトが相互に通信する方法と、データ層がストレージと通信する方法の詳細です。

同じ考えを自分で持っています。

従来のMVCで最も重要なことは、ビューをモデル部分とコントローラー部分から分離することです。肥大化したモデルオブジェクトになる可能性があるため、コントローラーとモデルを分離するのは良い考えのようです:


public class UserModel extends DatabaseModel implements XMLable, CRUDdy, Serializable, Fooable, Barloney, Baznatchy, Wibbling, Validating {
  // member fields
  // getters and setters
  // 100 interface methods
}

上記のインターフェースの多くに個別のコントローラー(またはパターン全体)を使用できますが、はい、それは本質的に手続き型ですが、最近はそれがどのように機能するかを推測します。あるいは、いくつかのインターフェースが同じことを実行していることを理解することができます(CRUDdy-データベースの保存と取得、Serializable-バイナリ形式と同じ、XMLable、XMLと同じ)。各潜在的なバックエンドは、システムが処理する個別の実装です。神様、それは本当にひどく書かれています。

「co-classes」のようなものがあるかもしれません。これにより、コントローラ実装用の個別のソースファイルを、あたかもそれらが動作するモデルクラスのメンバーであるかのように動作させることができます。

ビジネスルールに関しては、多くの場合、同時に複数のモデルで機能するため、別々のモデルにする必要があります。

これは「懸念の分離」に関する質問だと思います。レイヤードアーキテクチャの正しい道をずっと進んでいるように見えますが、同じことをもっと行う必要があるかもしれません-つまり、Java EEレイヤー内にアーキテクチャーレイヤーを作成しますか?

DataContainerは、データ転送オブジェクト(DTO)パターンによく似ています。

最新のOOデザインには多数の小さなクラスがあり、各クラスは少数の「友人」に関連付けられています。コンポジション経由。これにより、実際に使い慣れているよりもはるかに多くのクラスとJavaボイラープレートが生成される可能性がありますが、ユニットテストと保守がより簡単で階層化された設計になるはずです。

(質問に+1、レイヤー化の権利があるとわかったときの答えに+1)

おおざっぱに言うと、「私たちは望んでいません」セクションは行かなければなりません。あなたはそれが正しいことを望むか、あなたはそれをそのままにしておきたいのです。必要なときにクラスを作成しない ことに意味はありません。 「たくさんあります」悪い言い訳です。

実際、すべての内部クラスを公開することは 悪いですが、私の経験では、概念ごとにクラスを作成します(つまり、ユーザー、ID、データベース概念...)常に役立ちます。

その次に、Facadeパターンは、整然と整理された1つのインターフェイスの背後に隠されたBizRulesクラスの負荷の存在を解決するものではありませんか?

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top