Software Development

Thoughts on the MVP Pattern

Hello, dear readers, and welcome to my thoughts on the MVP (Model-View-Presenter) pattern, which I finally got around to learning. I had tried before, but everybody always explained it so abstractly that, even when compared to MVVM abstractly, I couldn’t tell what it was. But I recently got to see the pattern being implemented in some live-coding episodes  I don’t really have a whole lot to share; I’m focusing on one mini anti-pattern within the typical implementation that I’d like to provide alternative ideas for.

General Thoughts on MVP

First, I will give you my overall thoughts on MVP. My first thought about it is, “Is this really any different than MVC?” And truly, MVP is pretty much what I had always thought of MVC to be. The problem wasn’t MVC, in my opinion, but what so many people had come to think MVC was. Having heard what Uncle Bob has said about MVC, it’s clear that there has been severe “evolution” to the community’s understanding of MVC, but the MVC I was taught in college is almost exactly the same thing as MVP, with all the differences being negligible compared to the differences between my understanding of MVC and so many others’ understanding.

Beyond all that, though, I do like MVP, overall. When done correctly, it follows the Clean Architecture. Unfortunately, many people’s understanding of a domain model (or “entity” in Clean Architecture) goes against what I follow, which is akin to Domain Driven Design’s understanding, which I believe Uncle Bob (the creator of Clean Architecture) leans toward as well. With that said, I’m fine with letting others do that part however they like, since there are so many conflicting ideas about it. Really, the pattern is fine, except for the one anti-pattern I’m focusing on today.

Cyclic References in MVP

From what I’ve seen, everyone implements MVP with a cyclic reference. And I can understand why, it’s the simplest and most obvious way to implement the pattern. Almost no matter what system you develop in, the View is also going to be the system that receives events, and for the events (or commands derived from the events) to get to the Presenter, the View must have a reference to the Presenter. This is all as it should be. The problem comes from the fact that the Presenter is then expected to give commands back to the View after doing its business with the Model. Typically, this is done by a simple method call on the View object that is stored on the Presenter. Boom! Cyclic reference. The View holds a reference to the Presenter, which holds a reference to the View.

How Do We Get Around This?

The most obvious way to get around a cyclic reference is to instead pass the View in as an argument to the Presenter’s methods. This is simple, straightforward, and just a tad tedious (that’s a lot of typing “this”), but if you care about avoiding cyclic references, this is certainly a way to go.

Another way to go is to return some sort of command object. This is sort of old-fashioned OO and would likely require a lot of type checking and casting to determine which kind of command is returned and grabbing the data needed to do it. I would not recommend this.

A “solution” that I’ve seen someone use is to make the reference to the View a weak reference (one that isn’t counted by the garbage collector). While this gets around the biggest reason why cyclic references are bad, it doesn’t actually get rid of the cycle. If you don’t really care about cyclic references, I would still recommend doing this at least, and if you’re doing MVP in Android, I recommend checking out the android-arch-sample repository on GitHub, as it shows how someone can use a weak reference as well as some other scaffolding to make it so the Presenter replaces its View object when there’s a configuration change (such as rotating the screen), since configuration changes cause the Activity (which doubles as the View) to be destroyed and rebuilt. It also has the single greatest use of a stateful Singleton I’ve ever seen. There’s a way around it needing to be a Singleton, I’m sure, but I don’t actually want to get around it, it’s so clever.

So, what do I think is the best solution to avoiding cyclic references? Lambdas. It’s similar to the command solution, but instead of returning a command, you returns an anonymous function via lambda or method reference which the View will then call, passing itself in as an argument. It’s more functional, and not just because it uses higher-order functions. Rather, it’s more functional because the Presenter methods now have something to return. They can be pure (though they’re not likely to be because the model will be accessing some sort of mutable data store, most likely), since they’re not calling the “void” methods on View. It leaves the impure functions to be called at the outermost layer, the View, which is ideal.

What Do I Really Think?

Now, having said that I think that lambdas are the best solution, I’m not actually convinced of that. Theoretically, it’s the best, since the Presenter never has any reference to the View, but is it actually?

  1. It relies on the View to call the returned function, which it can totally ignore doing, and easily forget to do.
  2. Even using lambdas isn’t likely to keep the Presenter pure because it accesses the Model, which is likely to use a mutable data store.
  3. All you’re really doing is moving the same calls you were going to make anyway, but not they’re in a lambda or method reference.

My actual suggestion, until I can come up with a better idea or better reason for something else, is to pass the View in as an argument. That is, unless you’re using Android (it’s the only system I know of that destroys and completely rebuilds its Activities – or equivalent), where I recommend following the pattern in the android-arch-sample repository.

Until next time, thank you for reading.

Reference: Thoughts on the MVP Pattern from our JCG partner Jacob Zimmerman at the Programming Ideas With Jake blog.

Jacob Zimmerman

Jacob is a certified Java programmer (level 1) and Python enthusiast. He loves to solve large problems with programming and considers himself pretty good at design.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Blaise
Blaise
6 years ago

I’m using a observer|listener pattern to avoid teh cyclic reference. The presenter receive the view and listen to all events that he is interested in. This can be a lot of boilerplate code in some language but works well with lambdas (or Scala)

“`
class Presenter(view: View) {
view.onTextChanged((text)->{
// …
});
}

class View {
private Consumer observer;
public void onTextChanged(Consumer observer) {
observer.accept(this.text);
}
}

Jacob A Zimmerman
6 years ago
Reply to  Blaise

That’s a fair workaround, though I’m curious if everyone would consider that to still be MVP. I’ll allow it, but I don’t know about everyone else.

Back to top button