I'm a big advocate of MVP and haven't really tried MVVM. The drawback of the possibility of a Presenter
getting out of control is something I've had experience with but it can be mitigated.
In the example from the post the business logic will be relatively simple. There is likely only one model to deal with and not too much complex logic.
Let's think of a more complicated example though. Say you have an app that sells flowers. Once the user has chosen their bunch of flowers they get taken to the order options screen where they can:
- add a message to the flowers
- choose a gift vase
- select postage addresses
- choose a delivery date
Then add some domain requirements:
- you can't add a message if they're delivering abroad
- some areas have different lead times on delivery
- some vases are only available with some flowers
This might not be the best UX but putting that aside you now have a Presenter
that has to deal with many different Model
s (account, address, vases, orders) and can very quickly start taking on many responsibilities beyond simply telling the View
what to display and passing events to the Model
. This violates the Single Responsibility Principle. Also any time a class starts getting beyond 500 lines I start getting upset.
The solution is relatively simple though. You separate all your separate bits of logic out into UseCase
classes. I use a relatively simple base class as follows:
public abstract class UseCase<I, O> {
public static final int NO_STATUS = -1;
public Observable<Integer> getStatus() {
return Observable.just(NO_STATUS);
}
public abstract Observable<O> getAction(I input);
}
You specify an input & output type and inject all the models you need in the constructor in the concrete implementation class. The Presenter
takes events and input from the View
passes this to the appropriate UseCase
, this then does the complex logic with the Model
and returns the appropriate data to the Presenter to update the View
.
You can send periodic status updates back to your Presenter
using the status if needed to update the UI state.
This way your Presenter
returns to being a simple conduit for transferring data & events between the View
and the Model
and the business logic is nicely contained in a separate class for each action.