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.