nwebb

Flex, Flash, AIR

Archive for July, 2009

The Presentation Model – post #3

Example & Screen Recording

This example of using Flex and the Presentation Model together is more complicated than the last two but similar enough that you can progress through from the previous example apps. Rather than expect you to just wade through the code, I've created an accompanying screen recording which highlights the main points. You can find it here - please excuse the initial mumbling; It gets clearer as it goes on, honest :)

Get Adobe Flash player


Views, Presentation Models & Data Models

In my client's Flex project the view is bound directly to properties on a model. I've seen many projects work this way and guess it's the de facto way of doing things:

1) The view fetches a particular model it needs from a "Model Locator" class.
2) The view components all bind to properties on that model.
3) The view calls model.getData(), and the model loads the data (via a delegate).
4) When the model properties update, the bindings are triggered on the view, and vice-versa.

In this particular project, data with identical rules (or indeed the same data) can be used in multiple screens, and because some underlying logic applies to that type of data in all circumstances, it was deemed that the DataModels should not only contain the data, but contain logic related to that data too. This means if some logic changes, there is only one class where changes need to be made.

Currently it looks a bit like this:

VIEW <-> DATAMODEL

However, if we now add in the Presentation Model,  things look more like this:

VIEW <-> PRESENTATION MODEL <-> DATAMODEL

You end up with a class stuck in between the two. The main issue I've been having is how do I maintain a set up like we've got now (where changes to the view automatically update the data model and vice versa) while using this third class?

I've looked at some other Flex & PresentationModel examples, but while they load initial data via a delegate (read: DataModel), once the data is loaded, it seems to be the Presentation Model that holds this data and all changes to it.  It also seems to be the Presentation Model which holds logic relating to the data. That measn repeating logic in multiple PMs ... unless you extract the logic in to helper classes (remember, PMs are tightly coupled to particular views).


Example Code

In my above example, the data-logic remains in the DataModel class, presentation logic is in the PresentationModel class and View-only logic is in the View class (though there isn't really any view-only logic in this example).

The example has a ModelData class, which gets updated in synch with the View, and a View which always reflects what is in the ModelData class. In Martin Fowler's description he says the view should simply be a reflection of the PresentationModel, so perhaps I should regard this as something else entirely?!

In the example's code comments, I've outlined some of the issues I encountered in more detail (see the DataModel class in particular), so remember to right-click and view the code!

Again, this is a learning exercise, certainly not a definitive "how to" and in all honesty by this point I am suffering from "code blindness" so I fear that I'm  overlooking something hugely, glaringly obvious, so please feel free to laugh if I am ... as long as you let  me know and show me a better way to approach things  :]

Also, if there is a framework out there which solves these particular issues let me know. The problem I find with these types of questions is that they are too long to post on a forum and many people won't be interested or have a clue. If you're still reading this I hope it's a topic which does interest you, and hopefully you can impart your wisdom - essentially that is what I'm looking for from this post,  a better way :]
Edit(s):
1) Yep, if you disable the top NumericStepper you can't re-enable it. It's thrown in to show how you can put PresentationModel logic in the PM - it has no real purpose so I didn't bother implementing it fully (I just know someone will say "Hey, I can't re-enable the input") ;]

2)  I forgot to mention: See how I put the logic which checks/sets the "inputStyle" in a getter (not a setter). That's because, until the data has reached the model, it's not been validated. In this example it was easy to stick it in the getter for 'total'. I guess it would be better to have the DataModel dispatch an event which would be picked up by the PresentationModel ... doing that in a getter is weird admittedly. There are several potential issues with this way of doing things. Feel free to highlight any you can think of.

3) As a potential way of handling validation errors in the DataModel, substitute the bbb setters for the ones below and then set the value of B to 81 or more (thanks Graeme):

Actionscript:
  1. // In DataModel:
  2. public function set bbb(value:int):void
  3. {
  4. if (value&gt; 80)
  5. {
  6. throw new Error("bbb cannot be greater than 80");
  7. }
  8. else
  9. {
  10. _bbb = value;
  11. calculateTotal();
  12. }
  13. }
  14.  
  15. // In PresentationModel
  16. try
  17. {
  18. _data.bbb = value; //SET ON MODEL
  19. dispatchEvent(new Event('bbbChanged'));
  20. dispatchEvent(new Event('totalValueChanged'));
  21. }
  22. catch (E:Error)
  23. {
  24. Alert.show(E.message);
  25. }

2 comments

Bad Behavior has blocked 399 access attempts in the last 7 days.