In general, MVP (Model View Présenter/Controller) is a very nice pattern presented in many different languages and used in tons of development, especially when it’s about frontend.
On paper, MVP looks like in Ref – 1. That’s fine and as you can see, Presenter seems to depend on both the View and the Model.
The major problem with MVP is that it is generally implemented like what you see on Ref – 2.
As you can see, we are very close to the concept of anti-pattern even it looks like a normal MVP.
First of all because the View now depends on the Model (we have this concept of “crossing Model” : a Model that goes all over your architecture from the bottom to the top. A classical concept on which I’m preparing a post). On the other hand, you can also see a very nice graph cycle between the View and the Presenter. First, creating a cycle is bad. Why is it so bad ? because anytime you make a change into one of the cycled classes, then the other ones are at risk (and potentially you could make changes forever…), because if you deploy one, you’ll have to deploy the other ones, because any analysis based on your code will potentially fail and because a graph must be acyclic if you want to be able to maintain it correctly (arrows crossing a border in 2 different directions…).
One solution to this is of course to use Dependency Inversion. Ref – 3 shows one implementation that I like to use now.
The interesting part is the boundary that encapsulates the Presenter into its own module. My Presenter is now protected from the Model thru the creation of an interface <IModel>. So now I can push any kind of model into my presenter without being force to use one, thus making the Presenter testable. The View does not use anymore the Model. It has now a ViewModel Object that belongs to the Presenter Module and that the View depends on. The View still depends on the Presenter, but Views are known for being very volatile component and that will change a lot. The fact that it depends on Presenter and ViewModel is something we can handle.
The last thing to notice is the reverse in terms of dependency between the View and the Presenter. The Presenter now defines an interface <IView> that will be implemented by the View thus making the Presenter independent from the View and the View could be completely mocked to generate UITesting in an easier way thru Unit Testing. The View could also be exchanged for something else like a JSON api, a PDF printer, Desktop View, or whatever could be asked by the Business.
This way your code is decoupled from all external constraints, completely testable and easy to maintain, extend and changed. I hope this will help you to integrate Dependency Inversion in your code.
Have a very nice weekend and I wish you a happy new year.