After some reads on the subject and experienced at work, I have decided to study a bit more the MVP pattern to formalize a simple vision. In my opinion, the higher level pattern of an app must be as simple as possible and, ideally, not rely to many template classes or additional libraries. I give you here my thoughts on the subject.
Why the V would be the gang leader ?
Liaison between M, V and P
In all implementations I have seen, the V instantiates the P and/or is the master of the liaison. The P of MVP is a fully-fledged controller in the same way as the one of MVC and has even more responsibilities (reference), the View is supposed to be passive. It would then be more to the P to control the liaison, moreover, without knowing the concretion of V.
In the same way, we often see the view passing the Model to the Presenter or init a synchronization service. Based on the same principle, it does not have to do it.
It is likely for ease that, on Android, the V inherits from these responsibilities for, I think, 2 reasons :
- it is not instantiable directly but started by the framework
- it is the closest to the framework because tightly coupled with it (widget libraries), the P rather being in charge of coordination operations and so, naturally more independent from the framework
Interfaces between V and P
- 1 unique contract class containing the interfaces V (XViewContract) and P (XPresenterContract) : regroups the interactions between V and P inside a same class, improve the readability of the code.
- Ideally no base interface for V and P : complicate the code (additional structural classes to have in mind while programming).
The eligible methods are mainly the ones related to the attachment and detachment of the view. If we do not manage the orientation changes (and the need to manage the asynchronous callbacks) these methods are not necessary, the attachment is done by the constructor and there is no detachment.
If we want to manage the orientation changes and so , the attachment – detachment – reattachment, it is possible to avoid to regroup them in a mother class by using, for example, an annotation (no example of framework permitting this).
The pattern is called Passive View
- Affirmed dependence to the Android framework (UI libraries, OS’s, etc.)
Removing the view from the activities and fragments by considering them as simple framework controllers would add, in my opinion, a too important complexity (framework controller, V , P and M classes).
- Adapter : no particular treatment (except particular responsibility), the V responsible of the list pass it its P.
- Possibility to have many Presenters (eg one by subdivision of the model) for a complex View
The natural leader
- Master of the liaison with the 2 others
A solution to decouple V from P and M could be to notify a controller during the creation of V. The controller would then instantiates the concerned P and assigns it the V and vice-versa, it would also instantiates and assigns M. At the moment, as far as I know, there is no implementation of MVP working that way, maybe an idea of library…
Note : some implementations are based on a dagger injection of P in the View class, here the V does not know the concretion of P but stay master of the liaison (asks to the injector to instantiate the P). Moreover, I think that adding dagger to the first level pattern add an additional complexity (component, module, etc.).
- Usage of dynamic callbacks by anonym instantiation to manage the asynchronous callbacks to the business. Clearer, the presenter implements only its contract (no additional behavior at the class level).
- Avoid lifecycle methods (attachment / detachment) : they add a heaviness to the class and also imply to pass by parent classes (additional complexity). A good solution would be to pass by annotations. Not managing the orientation changes permits to avoid it by passing the View and the Model in the constructor. The copy of the onResume/onPause methods is to avoid, these methods being specific to the activity and fragment’s life cycle (at least rename them).
- Optimized orientation changes : ideally we don’t want to recreate the P with the activity but to keep it. This permits particularly to not have to make again the asynchronous calls which were pending during the destruction of the activity, and also to keep the state of P (no reinstantiation neither manual save/restore mechanism). This management implies the creation of a specific mechanism like the one implemented by the ThirtyInch library.
The business aside
- In its own project : permits to guarantee a by-design decoupling and improve the maintainability (conformity of the code, readability, modularity (unit tests of the business module eased))
- The less possible dependences to the framework : none would imply to deprive of utility classes brought by the framework for an ideal vision or a hypothetic usage in a no-Android context which will probably not happen. In a next future, will we be able to sharpen this dependence to the framework with a feature similar to Jigsaw on Android ?
- Repository more than DAO : improves the maintainability of the model (readability, eased testability (limitation to one method by CRUD), better independence to the model)
To conclude, I am still not satisfied with the proposed frameworks, while thinking that one is necessary to ease some operations related to the MVP pattern (liaison of the M, V and P, reattachment following an orientation change, buffering of the aynchronous call’s responses). Maybe a new library to come…