GWT and the Discipline of MVC

When you're developing a desktop or GWT application you're going to go through a bunch of iterations, tweaking the UI, adding components, etc. Sometimes in all of that work it is very tempting to take a shortcut and update a view directly from a controller (label.setText(model.messsageString)). That way lies madness. Before long you've got your view code strewn across the length and breadth of your application. Change the view or some aspect of the model and you're on a refactoring of biblical proportions.

In fact there's never a good time to break out of MVC, but sometimes you just don't know what sort of Observable your model should be. Will you be using a table, a tree, some custom component? In those situations I try to preserve MVC while punting the hard decision until later. To this end, I've written a little set of utility classes called SimpleModel. How do you use SimpleModel?

Label error = new Label("");
SimpleModel errorModel = new SimpleModel();
 
errorModel.addSimpleModelListener(SimpleModelListener () {
    public void onChange(SimpleModelEvent event) {
        String oldModel = event.getOldModel();
        String newModel = event.getNewModel();
        error.setText(newModel);
    }
});
 
// wire up the GUI here
 
// now change the model
errorModel.setModel("This should show up as an error");

Very simple. No deltas, no change, remove or insert events. But it does get you hooking up your V to your M without clogging up your C. If, at some later point, you decide to move to a Tree, you will need to wire up the MVC a little differently, but at least the separation is already there. No serious refactoring necessary.

Ideally you'd like to have the listener code resident in your view, but for purposes of illustration, I used a simple Label rather than a Composite widget.

My SimpleModel has a special SlicedSimpleModel that uses timers to dispatch each listener separately. That shields against long running listeners.

public class SlicedSimpleModel extends SimpleModel {
    public void fireSimpleModelEvent(final SimpleModelEvent event) {
        if (listeners == null) {
            return;
        }
        for (final SimpleModelListener listener : listeners) {
            Timer t = new Timer() {
 
                public void run() {
                    listener.onChange(event);
                }
            };
            t.schedule(5); // run right away
        }
    }
}

Anyhow, if there is interest, I can add SimpleModel to the jsonwrapper project. But whether you use my utility code or write your own, make sure to wire your GUI's up as MVC even when you're just spitballing.

Related posts:

  1. Remove/Cancel Bubbling for an Event in Flex3
  2. Adding a Timer Component to Echo2
  3. Bean of the Devil: Tally-Ho CMS
  4. GWT Hyperlink and the Mouse That Went Over
  5. Getting Rid of the “handler.call: handler undefined” Error

Topics: , ,

Comments: 8 so far

  1. Very interesting. In a very short article, you have stated the true value of MVC. Care to share your source for SimpleModel()?

    Comment by Mike Shaffer, Wednesday, December 10, 2008 @ 1:10 pm

  2. Since JavaScript is Single threaded using the Timer to handle the events asynchronously will not guard you against long running listeners. Sure, you will be able to make sure the UI is rerendered before the listeners are triggered, but what would that help ?

    Comment by David, Wednesday, December 10, 2008 @ 1:58 pm

  3. @David

    sorry, I wasn’t precise. The scheduler will try to boot a script that has run for more than 5 seconds. If I have 4 listeners, each of which runs for 2 seconds, then I have a problem. Scheduling each of these listeners via Timer gets around that.

    Comment by Dietrich Kappe, Wednesday, December 10, 2008 @ 2:23 pm

  4. @Mike

    I’ll package it up and add it to the jsonwrapper project.

    Comment by Dietrich Kappe, Wednesday, December 10, 2008 @ 2:24 pm

  5. Now I understand. Until now I never done that in my models. I always assume that long running tasks should fork themselfves as incremental commands.

    By using Timers in the model you are tying the model to GWT. I like to keep the model pure Java, that way I can switch to SWING or any other Java UI technology without the problem that I need to modify the model implementations.

    Comment by David, Wednesday, December 10, 2008 @ 3:39 pm

  6. @David

    Actually, since you’re wrapping your underlying model in SimpleModel (the model property of SimpleModel), you aren’t tying it to GWT. Certainly SimpleModel will work in Swing (and I’ve used it there, in fact), you’re just using a subclass to play nice with the JavaScript scheduler.

    If you think about it, SimpleModel is just providing the Observer/Observable behavior, not your underlying business logic.

    Comment by Dietrich Kappe, Thursday, December 11, 2008 @ 1:54 am

  7. This pattern is usually called “value model”. Take a look at this:
    http://c2.com/ppr/vmodels.html

    You can find a Java implementation in the Spring Rich Client project (http://spring-rich-c.sourceforge.net/1.0.0/index.html). I ported its code to a GWT project with only some little tweaks, and it’s working great.

    Now I can’t live without it ;-)

    Comment by Juanjo, Tuesday, December 16, 2008 @ 4:33 am

  8. Interesting. I’m working on a new ground up app currently, I’m finding that the little extra perception and work I’m putting into making sure MVC is proper is paying off as the app grows.

    Comment by Nick, Saturday, January 3, 2009 @ 8:31 pm

Leave a comment

Powered by WP Hashcash

Launch: Pathfinder Newsletter

    Get a monthly update on best practices for delivering successful software.

    Subscribe via email


    Subscribe via RSS      RSS icon

Topics

Search

WordPress

Comments about this site: info@pathf.com