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


9

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

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

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

私の質問は:

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

回答:


8

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

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

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

(太字強調鉱山)

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

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

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

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

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

ただし、textViewビューはボタンイベントを単にPresenterに転送するだけなので、ビューのボタンイベントハンドラーもコンテンツの受け渡しに責任を負うべきではないと主張することもできます。

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

// 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、イベントハンドラーを使用して直接ビューに渡すのとどう違うのですか?主な違いは、プレゼンターはオブジェクトを作成するロジックを最終的に担当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ウィジェットプロパティの状態に関するステートメントであっても-空のテキストボックスのチェック、またはチェックボックスのブール値)、それはプレゼンターに属します。


1
すばらしい回答@BenCottrell!しかし、もう1つあります。)プレゼンターメソッドにという名前を付けるのは良い習慣ですonSomethingClicked()。そのため、ユーザーが「何か」をクリックすると、ビューが呼び出されpresenter.onSomethingClicked()ますか?または、私のプレゼンターメソッドは、私の場合、目的のアクションとして名前を付ける必要がありaddUser()ますか?
Rômulo.Edu

1
@regmoraesいい質問です。そして、あなたは私のコード例で少し匂いを強調したと思います。PresenterUIロジックではなく、ドメインロジックのためのコース責任者であり、かつ特異的に仕立てViewという名前のメソッドが存在するはずのような概念は、UIの概念ですので、onSomethingClicked()実際には適切です。後から考えると、上記の例で選択した名前は、あまりにおいがしません:-)。
Ben Cottrell 2016年

@BenCottrell最初に素晴らしい答えをありがとう。私が理解GetUserInfoしているように、あなたが述べたようにビューにこのメソッドがあれば有効です(プレゼンターからトリガーされます)メソッドif内で考えられる条件はどうGetUserInfoですか?たぶんUserInfoのいくつかのフィールドはユーザーの反応を介して設定されますか?シナリオ:ユーザーがチェックボックスを選択すると、いくつかの新しいコンポーネント(新しいEditTextなど)がユーザーに表示されます。その場合、GetUserInfoメソッドにはif条件があります。このシナリオでGetUserInfoはまだ有効ですか?
ブラックカラ2017

1
治療を検討@Blackkara UserInfoとしてモデル・オブ・ビュー(「ビューモデル」別名) -そのシナリオでは、私は追加することになりboolean、チェックボックスの状態と、空の/ NULL可能Stringにテキストボックスの状態をUserInfoUserInfoViewModelPOJOがUserInfoPresenter、ビューステートについての情報を見つけることを唯一の本当の目的とするクラスであるという観点から考えると役立つ場合は、名前を変更することを検討することもできます。
Ben Cottrell 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.