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.
Topics: Design Patterns, GWT, MVC
Comments: 8 so far
Leave a comment
About Pathfinder
Follow the Blog
-
Get a monthly update on best practices for delivering successful software.
Subscribe via email
Subscribe via RSS
Categories
Topics
Archives
- July 2009
- June 2009
- May 2009
- April 2009
- March 2009
- February 2009
- January 2009
- December 2008
- November 2008
- October 2008
- September 2008
- August 2008
- July 2008
- June 2008
- May 2008
- April 2008
- March 2008
- February 2008
- January 2008
- December 2007
- November 2007
- October 2007
- September 2007
- August 2007
- July 2007
- June 2007
- May 2007
- April 2007
- March 2007
- February 2007
- January 2007
- December 2006
- November 2006
- October 2006
- September 2006
- August 2006
- July 2006
- June 2006
- May 2006
- April 2006
- March 2006
Blogroll
Recent
- Elements of Testing Style
- Aesthetics and Web Design
- Asterisk-Java Testing with Groovy
- 3 Misuses of Code Comments
- Fluently NHibernate
- Digging a Hole and Covering it with Leaves — The Software Development Version
- The Importance of User Experience - Do You Understand It in Your Bones?
- Writing Your Own Protocol With NSURLProtocol
- What’s In Your Dock: iPhone edition
- Feature Fatigue

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
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
@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
@Mike
I’ll package it up and add it to the jsonwrapper project.
Comment by Dietrich Kappe, Wednesday, December 10, 2008 @ 2:24 pm
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
@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
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
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