web-dev-qa-db-ja.com

MVPパターンでは、ビューはUIコンテンツに基づいてモデルオブジェクトをインスタンス化する必要がありますか、それともこれらのコンテンツをパラメーターとしてプレゼンターに渡しますか?

開発中のAndroidアプリでMVPパターンを使用しています。

基本的に4つの要素があります。

  1. 新しいユーザーを追加できるAddUserView:
  2. AddUserPresenter
  3. UserInfo(pojo)
  4. UserInfoManager(ビジネスロジックとストレージマネージャー)

私の質問は:

AddUserViewの[追加]ボタンを押すと、テキストビューのコンテンツが取得され、新しいUserInfoがインスタンス化されて、Presenterに渡されます。または、AddUserViewは単にtextViewsコンテンツを取得してAddUserPresenterに渡す必要があります。これにより、実際にはUserInfoがインスタンス化され、UserInfoManagerに渡されますか?

9
Rômulo.Edu

マーティンファウラーのMVPの説明によると( http://martinfowler.com/eaaDev/uiArchs.html

MVCのビュー部分のうち、Fowler氏は次のように述べています。

Potelの最初の要素は、ビューをウィジェットの構造、フォームとコントロールモデルのコントロールに対応するウィジェットとして扱い、ビューとコントローラーの分離を削除することです。 MVPのビューは、これらのウィジェットの構造です。ウィジェットがユーザーの操作にどのように反応するかを示す動作は含まれていません

(太字強調鉱山)

その後、プレゼンターの:

ユーザーの行動に対するアクティブな反応は、別のプレゼンターオブジェクトにあります。ユーザージェスチャーの基本的なハンドラーはウィジェットにまだ存在しますが、これらのハンドラーは単にプレゼンターに制御を渡します

プレゼンターは、イベントへの対応方法を決定します。Potelは、主にモデルのアクションに関してこの相互作用について説明します。これは、コマンドのシステムによって行われます。と選択。ここで強調すべき便利な点は、モデルへのすべての編集をコマンドにパッケージ化するアプローチです。これは、元に戻す/やり直し動作を提供するための優れた基盤を提供します。

(再び、大胆な強調鉱山)

したがって、Fowlerのガイドラインに従って、ビューはボタンイベントに応答する動作に対して責任を負うべきではありません。これには、UserInfoのインスタンスの作成が含まれます。オブジェクトの作成を決定する責任は、UIイベントの転送先のPresenterメソッドにあります。

ただし、ビューはボタンイベントをforwardingするだけなので、textViewのコンテンツを渡す責任もビューのボタンイベントハンドラーにもないことを主張することもできます。プレゼンターとそれ以上。

MVPでは、プレゼンターがビューから直接データを取得するために使用できるインターフェイスをビューが実装するのが一般的です(プレゼンターがビュー自体にまだ無知であることを確認しながら)。 UserInfoは単純なPOJOであるため、ビューがUserInfoのgetterを公開して、プレゼンターがインターフェイスを介してビューから取得できることは有効な場合があります。

_// The view would implement IView
public interface IView {

    public UserInfo GetUserInfo();
}

// Presenter
public class AddUserPresenter {

    private IView addUserView;

    public void SetView(IView view) {
        addUserView = view
    }

    public void onSomethingClicked() {

        UserInfo userInfo = addUserView.GetUserInfo();
        // etc.
    }
}
_

これは、イベントハンドラーを使用してUserInfoをビューに直接渡すこととどう違うのですか?主な違いは、プレゼンターがlogicを最終的に担当し、UserInfoオブジェクトが作成されることです。つまり、イベントはUserInfoが作成される前にプレゼンターに到達し、プレゼンターが決定できるようにしました。

ビュー内のいくつかの状態に基づいてUserInfoを作成したくないプレゼンターロジックがあるシナリオを想像してみてください。たとえば、ユーザーがビューのチェックボックスをオンにしていない場合、またはUserInfoに追加するフィールドに対する検証チェックが失敗した場合-プレゼンターはGetUserInfoを呼び出す前に追加のチェックを含む可能性があります。

_    private boolean IsUsernameValid() {
        String username = addUserView.GetUsername();
        return (username != null && !username.isEmpty());
    }

    public void onSomethingClicked() {            

        if (IsUsernameValid()) {
            UserInfo userInfo = addUserView.GetUserInfo();
            // etc.
        }
    }
_

そのロジックはプレゼンター内に残り、ビューに追加する必要はありません。ビューがGetUserInfo()の呼び出しを担当している場合は、その使用を取り巻くロジックも担当しています。これは、MVPパターンが回避しようとしていることです。

したがって、UserInfoを作成するメソッドは物理的にViewクラスに存在する可能性がありますが、Viewクラスから呼び出されることはなく、Presenterからのみ呼び出されます。

もちろん、UserInfoの作成でユーザー入力ウィジェットのコンテンツ(文字列変換、検証など)に対する追加のチェックが必要になる場合は、検証/文字列変換ができるように、それらの個別のゲッターを公開することをお勧めしますプレゼンター内で行われ、プレゼンターがUserInfoを作成します。

全体として、Presenter/Viewの分離に関する主な目標は、ビューにロジックを記述する必要がないしないことです。何らかの理由でifステートメントを追加する必要がある場合(ウィジェットのプロパティの状態に関するifステートメントであっても、空のテキストボックスをチェックするか、チェックボックスのブール値である場合)、それはプレゼンターに属します。

8
Ben Cottrell