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?

Rômulo.Edu
  • 269
  • 2
  • 9

1 Answers1

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.

Ben Cottrell
  • 11,656
  • 4
  • 30
  • 41
  • 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()` ? – Rômulo.Edu Mar 12 '16 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 :-). – Ben Cottrell Mar 12 '16 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 08 '17 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. – Ben Cottrell Apr 08 '17 at 13:31