9

I'm using MVP pattern in an android app that I'm developing.

I have basically 4 elements:

  1. The AddUserView where a new user can be added:
  2. The AddUserPresenter
  3. The UserInfo (the pojo)
  4. The UserInfoManager ( businness logic and storage manager)

My question is:

When I press the "Add" button in the AddUserView, it should get the content of the textviews, instantiate a new UserInfo and pass it to the Presenter. Or should the AddUserView just get the textViews contents and pass them to the AddUserPresenter, which will in fact instantiate the UserInfo and pass it to the UserInfoManager?

1 Answer 1

8

According to Martin Fowler's description of MVP ( http://martinfowler.com/eaaDev/uiArchs.html )

Of the View portion of MVC, Fowler says:

The first element of Potel is to treat the view as a structure of widgets, widgets that correspond to the controls of the Forms and Controls model and remove any view/controller separation. The view of MVP is a structure of these widgets. It doesn't contain any behavior that describes how the widgets react to user interaction.

(Bolded emphasis mine)

Then of the presenter:

The active reaction to user acts lives in a separate presenter object. The fundamental handlers for user gestures still exist in the widgets, but these handlers merely pass control to the presenter.

The presenter then decides how to react to the event. Potel discusses this interaction primarily in terms of actions on the model, which it does by a system of commands and selections. A useful thing to highlight here is the approach of packaging all the edits to the model in a command - this provides a good foundation for providing undo/redo behavior.

(Again, bolded emphasis mine)

So, in accordance with Fowler's guidelines, your View should not be responsible for any behaviour in response to the button event; which includes creating an instance of UserInfo. The responsibility of deciding to create an object belongs to the Presenter method to which the UI event is forwarded.

However, one could also argue that the View's button event handler should also not be responsible for passing the content of your textView either, since the View should merely be forwarding the button event into the Presenter and nothing more.

With MVP, it's common for the view to implement an interface which the presenter can use to pick up data directly from the view (while ensuring the presenter is still agnostic to the view itself). Since UserInfo is a simple POJO, it may be valid for the view to expose a getter for UserInfo which the Presenter can pick up fron the View via an interface.

// 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.
    }
}

How is this any different to passing the UserInfo directly into the view using the event handler? The main difference is that the presenter is still ultimately responsible for the logic which causes a UserInfo object to be created. i.e. the event reached the Presenter before the creation of the UserInfo, allowing the Presenter to make the decision.

Imagine a scenario where you had presenter logic where you didn't want that UserInfo to be created based on some state within the view. For example, if the user has not ticked a checkbox on the view, or you had a validation check against some field to be added into UserInfo which failed - your presenter might contain an additional check before calling GetUserInfo - i.e.

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

    public void onSomethingClicked() {            

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

That logic remains inside the presenter, and doesn't need to be added into the view. If the view were responsible for calling GetUserInfo() then it would also be responsible for any logic surrounding its use; which is what the MVP pattern is trying to avoid.

So while the method which creates that UserInfo may physically exist in the View class, it is never called from the View class, only from the Presenter.

Of course, if creation of the UserInfo ends up requiring additional checks against the content of user input widgets (e.g. string conversion, validation, etc. ), then it would be better to expose individual getters for those things so that validation/string conversion can take place within the Presenter - and then the presenter creates your UserInfo.

Overall, your main goal with regards to separation between Presenter/View is ensuring that you never need to write logic in the view. If you ever find yourself needing to add an if statement for any reason (even if it's an if statement regarding the state of a widget property - checking an empty textbox, or a boolean for a checkbox), then it belongs in the presenter.

4
  • 1
    Great answer @BenCottrell ! But I have another one :) Is a good practice naming the presenter methods as onSomethingClicked(), so when the user click on "something" ,the View calls presenter.onSomethingClicked()? Or my presenter methods should be named as the intended actions, in my case addUser() ? Mar 12, 2016 at 20:53
  • 1
    @regmoraes Good question; and I think you've highlighted a slight odour in my example code. The Presenter is of course responsible for UI logic rather than domain logic, and tailored specifically to the View, therefore concepts which should exist are UI concepts, so a method named onSomethingClicked() is indeed appropriate. With hindsight, the naming I've chosen in my example above doesn't smell quite right :-). Mar 12, 2016 at 21:40
  • @BenCottrell Firstly many thanks for great answer. I understand, that's valid having this GetUserInfo method in the view as you mentioned(will be triggered from presenter) What about the possible if conditions inside GetUserInfo method ? Maybe some fields of UserInfo will be set via user reaction ? A scenario : Maybe user selects a check box then some new components(a new EditText maybe) will be visible to user. So in that case, GetUserInfo method will have if condition. In this scenario GetUserInfo is valid still ?
    – blackkara
    Apr 8, 2017 at 13:15
  • 1
    @Blackkara Consider treating UserInfo as a model-of-the-view (a.k.a "View Model") - In that scenario I would add the boolean state of the check box and the empty/nullable String state of the text box into UserInfo. You might even consider renaming it into UserInfoViewModel if that helps to think in terms of the POJO being a class whose only real purpose is to let the UserInfoPresenter find out information about the View state. Apr 8, 2017 at 13:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.