GWT MVP Pattern

gwt development GWT MVP Pattern

There is a ton of hype about the Model, View and Presenter (or MVP for short) pattern on the GWT forums and tutorial sites.  Unfortunately, there is just as much confusion about the GWT MVP Pattern as there is discussion.  The trick to this pattern is realizing that there really is nothing new about it, the pattern is a twist on some older patterns that you may be very familiar with.

Advantages of the GWT MVP Pattern

Before we get into the actual how-to of MVP, it is good to know why you actually should be using this pattern.  Just blindly doing something because it is the “new thing”, “everyone is doing it”, or “cool > useful” is usually a bad idea.  Know why you want to use something before you use it.

Decoupling

The first advantage for MVP is to decouple the view and the logic.  We all know that it is a good idea to decouple responsibilities as much as possible and the view and control code is no exception.  The old adage “let a class do one thing only and do that thing well” is sage advice and the MVP pattern helps with that.  When done properly, you will have one class that is the view and one that is the logic that controls the view’s behavior.  Of course, the best way to do this is through the use of interfaces.  The view would typically communicate via a presenter interface and the presenter would control the view through a view interface.

Unit Testing

If you are coding through the interfaces from the Decoupling section, then you will find unit testing your presenters a breeze especially if you are using a dependency injection framework like Gin and Guice.  When you create the instance of the presenter for the unit test, you can inject a mock of the view quite easily and control its behavior from the setup of the test.  The best part of this is you don’t have to use GWTTestCase.  This keeps you from needing to spin up a GWT container for every test which can be extremely time consuming.  Unit tests for presenters are just as fast as normal tests because they ARE normal tests.  There is never an excuse not to run them!

Coding to Other Platforms

One very cool feature, if you use the “correct version” of MVP, is that you can reuse your presenter logic on many other platforms for free.  Remember, you are writing actual Java code and there is no reason that you couldn’t drop it into a Swing or Android application.  Just rewrite the the view in whatever platform you are supporting, wire it to your presenter and ** POOF Magic ** you have a working application.

What do I mean by the “correct version”?  First, you need to code to interfaces because the presenter can’t be hard wired to the GWT version of your view.  Secondly, the view interface can’t expose any GWT specific widgets or interfaces.  For example, if your view interface has a method called getFirstNameHasText() and it returns the GWT version of the HasText interface, it won’t work on any other platforms.

GWT MVP Pattern Code Example

There are two main camps when it comes to using the MVP pattern.  The main difference seems to be the responsibility of presenter.  One side exposes interfaces for the presenter to register itself for change events from the widgets and the other delegates that responsibility to the view which in turn tells the presenter if something happens.  Personally, I am in the second camp because it looks cleaner and if you are going to be supporting multiple platforms you don’t need to write a bunch of wrapper classes to register to in order to expose the widgets.  I will show both versions of the GWT MVP Pattern and you can choose which one you like the best.

For this example, lets assume we have a form that we want to collect the user’s name.  This is of course a fairly trivial example, but when you do larger, more complex systems, it is really just a matter of copy and paste for each control on your form.  It doesn’t get more complex as you add more to the screen.

GWT MVP Pattern implementation #1

The first implementation is to completely decouple the view and presenter with interfaces and make them talk to each other through the interfaces (the “version” that I prefer) and not through registration of listeners.  The view and presenter interfaces would be something along the lines of the following:

As you can see, this will allow each other to let the other one know that something has changed but not know anything about how the other is implemented.  You will also notice the setPresenter on the view interface.  This may or may not be there depending on how you are creating your classes.  If you are using a dependency injection framework, you probably won’t have these types of “handshake” methods which leads to cleaner looking code.

Now to the meatier pieces, the presenter and view.  First lets take a look at the implementation of the presenter:

There are three main pieces to note in this code.  Line 10 is simply showing a bit of manual wiring that happens without dependency injection.  That way the view will have a reference to the presenter for later on.  Line 13 is an example of how the presenter takes data from the model and tells the view to display the information.  Remember, one of the presenter’s jobs is to be a bridge between the view and model.

Then on line 19 we have a situation that may not seem quite intuitive yet because we haven’t looked at the view implementation yet.  This is the method that will be called from the view when the name text box has changed values.  When the presenter is told about a change to the name value, it needs to save it into the model.

In the view, things get a little tricky if you aren’t used to any type of GUI programming.  I am also taking the liberty of assuming that the nameTextBox was somehow magically created and added to the UI.  There are several ways to do this such as programmatically doing it in the view constructor or using UIBinder.  How ever you choose to do it, don’t get hung up on this, it doesn’t matter to the pattern we are looking at.

The first item to notice in the view is on line 8 and 11.  Line 8 is simply registering for a change notification and line 11 is telling the presenter that it needs to do something with this new value.  The view really doesn’t care about what the presenter does as long as it does something.

Line 18 is getting called from the constructor of the presenter.  When the presenter tells the view what the actual value is, it needs to turn around and set the value into the actual control.

That is really all there is to the version 1 of the GWT MVP Pattern implementation.  It is pretty straight forward once you understand the few moving parts.

GWT MVP Pattern implementation #2

The second variation to the pattern is to have the presenter register itself to exposed interfaces and handle change events itself.  As in the last example, we will take a look at the interfaces before we get started with the real code.  Make note in this version that there doesn’t really need to be an interface for the Presenter because the view never is going to talk directly to it.

Line 3 is the big change here.  It is returning a HasText along with a new naming convention for the method name.  The HasText is a GWT interface that simply allows you to interact with the instance as something that contains and displays text in an unknown way.  If you are going to stick with this version of implementation, it is a good idea to adopt the naming convention as well.  It is quite easy to tell what you are going to be dealing with just by looking at the name.  If there was a method called getSaveHasClickHandlers(), you could safely assume that you are probably working with a save button that you need to register a ClickHandler with.

Line 4 is how you will register the presenter to listen for changes to the name widget.  Then when the value changes, the listener will in turn update the model.

Notice in the implementation that both of the methods return the nameTextBox.  It just so happens that TextBox implements both the HasText and the HasChangeHandlers interfaces.  Interestingly, with this version of the GWT MVP Pattern the view becomes a bit more simple.  It is only responsible for laying out the widgets and providing access to them

The presenter is where the largest changes come into play.  Just like the last example, it is responsible for initially setting the values into the widget.  It just happens that this is accomplished differently.  The presenter is also required to register handlers for change events so the model can get updated.

The presenter accomplishes its first responsibility on line 5.  It asks the view for the HasText and sets the value from the model into the view component.  This is fairly straight forward.  The second requirement of listening for changes has a bit more to it.  Line 8 and 11 is where the listening and updating is accomplished.  Line 8 asks the view for the HasChangehandlers and then registers a new ChangeHandler to take care of the changes.  When the value in the text box changes, line 11 will be called.  The presenter once again asks the view for the HasText, gets its value, and then sets it into the model.

Wrap Up Discussion

Both versions have merit and, to be honest, some of the decision comes down to personal style.  Some folks feel that one or the other looks more aesthetically pleasing to them.  In the end, the reason that I chose the first example over the second is because of unit testing.  There is far less that you need to actually mock out in the first version.  There are no HasText or HasChangeHandlers to mock, just the view interface (which is extremely easy if you are using Mockito or EasyMock).

No matter which version you use, the GWT MVP Pattern is definitely the right way to go.  Don’t get hung up on which version or all the nitty gritty details of all the arguments across the internet, just pick one and stick with it.  The important part is that you are doing it and using a great design!

Technorati Tags: , , , , , , , ,

Tags: , , , , , , , ,

2 Responses to "GWT MVP Pattern"

Leave a Comment