Peter Hall's Flash, Flex and AIR blog. News and insights into development with Flash, Flex and AIR.

This page is powered by Blogger. Isn't yours?
Monday, May 26, 2008

Slide framework preview part 1: hierarchical view states

The cornerstone of the Slide framework is view state management. Typically, if you have code in a controller, that needs to make a change to the view - for example to change the index of a ViewStack - the controller will need access to that view. In Cairngorm, "commands" work like controller delegates, and get a reference to the view that triggered it; or they can affect view states by setting bindable flags on the ModelLocator, or use ViewLocator (deprecated) to update the view directly. Slide removes the need for controller type logic from needing access to views by having views respond to changes in global application view state.

Slide differentiates between two different kinds of view state changes; data and navigational. Data here means changes to the models that a view is bound to. They could cause a Repeater to update, a Label to change its text or a RadioButton to change its selected state. Navigation refers to larger changes where you move from one functional part of the application to another. The former is handled in Cairngorm quite well, and Slide does it in a similar way. But if you want to navigate around your application, it's a bit clumsy to control that with properties on the ModelLocator, and putting too much knowledge of view structure inside controllers can get messy quickly. I imagine this is part of the reason that ViewLocator is deprecated in Cairngorm now.

By comparison, in a classical JSP or RoR application, views are HTML-based templates with bindings. Controllers update the models and then send the populated template back to the browser, but they don't need to know anything about how that template is structured. That makes a page-based HTML application very straightforward to implement in clean MVC. In a typical "Ajax" application, this gets muddier because the controller is on the server but controller-type decisions are being made on the client too. This extra decision-making tier on the client must know a lot about the structure of the views in order to do it's job.

In a Flex application, you have the same problem with the client-side controller. Bindings take care of data-oriented state changes but often, to get to a particular "screen", you have to update several parts of the display tree.

Slide uses URI's to represent a navigational state of an application. This lets you think about your application controllers in a similar way to how you would in the classical JSP/RoR application. When you make a decision in the controller, you can update the application's view state URI, which is similar to redirecting to a URL, except of course without a page refresh.

For example, a Slide-based shopping cart might have the following view state URI's defined:

  • /MyShop/browse
  • /MyShop/cart
  • /MyShop/cart/checkout
  • /MyShop/cart/checkout/complete
  • /MyShop/cart/checkout/failed

From your controller's perspective, in moving between the steps, all it needs to do is:

stateManager.stateURI = "/MyShop/cart/checkout";

All views in your application have the opportunity to respond to this state change and update themselves. The framework automatically maps changes to the view state URI to Flex states, if the view has defined one.

So the main MXML file in the application might have states defined like this:

<mx:states>
   <slide:ViewState name="browse" uri="/MyShop/browse">
      <mx:SetProperty target="myViewStack"
             name="selectedChild"
             value="{browseView}" />
   </slide:ViewState>
   <slide:ViewState name="cart" uri="/MyShop/cart">
      <mx:SetProperty target="myViewStack"
             name="selectedChild"
             value="{cartView}" />
   </slide:ViewState>
</mx:states>

Note that, this view hasn't defined the checkout states, but these are child states of cart, so it will automatically go into the cart state.

In the above case, the states match up with the display tree structure. But suppose there is a footer in the application that needs to show contextual advertisements as your browse through products, shipping options when viewing the cart, and a legal disclaimer once you are at the checkout. The footer component might define states like this:

<mx:states>
   <slide:ViewState name="browse" uri="/MyShop/browse">
      <!-- Show contextual adds in this state -->
   </slide:ViewState>
   <slide:ViewState name="cart" uri="/MyShop/cart">
      <!-- Show shipping options in this state -->
   </slide:ViewState>
   <slide:ViewState name="cart" uri="/MyShop/checkout">
      <!-- Show legal disclaimers in this state -->
   </slide:ViewState>
</mx:states>

As an application grows in complexity, managing states like this becomes increasingly valuable to keep navigational logic clear and simple.

The URI hierarchy is independent of the display list hierarchy. Views anywhere in the display list may react and update themselves based on any view state change. This allows you to be extremely flexible with how views are structured, without affecting controller logic.

The other huge benefit we have got from managing states this way is in the design phase. From an early point, we try to define the different view states and match up visual designs with URI's. This means we can build simple HTML click-throughs of the application to demonstrate the flow, and easily compare what we have built with what was designed.

Saturday, May 17, 2008

introducing the Slide framework for Flex at WebDU

In June, I'll be presenting at WebDU in Sydney about Slide, our application framework, which will go open-source about the same time.

Slide is mostly about managing views and application states, but also about how different parts of an application get access to things like models and controllers. Over the coming weeks, prior to WebDU, I'll be posting about some of the ideas behind Slide and hopefully prompt some discussion.

At Memorphic we've been using the principals behind Slide for more than a year, and gradually combining the ideas into a framework that can be easily re-used distributed. It's been used in production sites for the likes of Fidelity Investments, Airbus and LMG (Nectar Loyalty Program) for both public and internal applications.

What we came up with is a library of classes that do a lot of work for you and encourage you to work in a certain way. However, you can just as easily take the parts that you want, and continue to build the majority of your app using the framework you are used to, such as Cairngorm or PureMVC.