« Flex/Flash Architectural Challenge | Main | Web 2.0, RIAs, AJAX, and the semantic web (lowercase s) »

August 18, 2005

Flex/Flash Architectural Challenge (part 2)

In the previous part of this challenge, I was asking the question of whether model/view separation was enough for most RIAs, or whether MVC was required. As a concrete exercise, I thought it would be good to imagine building a specific small app, so I picked Ta-da List.

I took some time to sketch out what I think a model/view version of this app might look like in Flex pseudocode. How would an MVC version be structured differently?

ListApp.mxml
--
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml" xmlns="*" initialize="onInitialize()">
	<mx:Script source="ListApp.as" />
	
	<mx:HDividedBox width="100%" height="100%">
		<mx:Panel title="My Lists" width="200" height="100%">
			<mx:List id="listOfListsView" width="100%" height="100%" dataProvider="{listOfLists}" cellrenderer="ListOfListsRenderer" change="onSelectedListChanged()" />
			<mx:ControlBar>
				<mx:Button label="new list" click="onNewList()" />
			</mx:ControlBar>
		</mx:Panel>
		<mx:Panel title="{selectedList.title}" width="100%" height="100%">
			<TodoListView id="todoListView" width="100%" height="100%" dataProvider="{selectedList}" />
			<mx:ControlBar>
				<mx:Button label="add item" click="onAddItem()" />
				<mx:Button label="edit"     click="onEdit()"    />
				<mx:Button label="share"    click="onShare()"   />
			</mx:ControlBar>
		</mx:Panel>
	</mx:HDividedBox>
</mx:Application>


ListApp.as
--
// included from ListApp.mxml

var session : ListAppSession; // Magic session state variable which I will imagine is already populated.

var user : ListAppUser;
var listOfLists : ListOfLists;
var selectedList : TodoList;

function onInitialize()
{
	// Ask the static factory methods of ListAppUser and ListOfLists classes to fetch
	// data from the server and create instances of my client side representations.

	user = ListAppUser.getInstance(session.userId);
	listOfLists = ListOfLists.getInstance(user);
	
	// Once these get filled in, data binding will take care of view updates.
}

function onNewList()
{
	// When a new list is requested, pop up a dialog, and call the model to ask
	// it to add a new list.

	var dialog : NewListDialog = PopUpManager.createPopUp(this, NewListDialog);
	var handler = function() { 
		listOfLists.newList(dialog.fields.title, dialog.fields.description) 
	};
	
	dialog.addEventListener("ok", handler);
}

function onSelectedListChanged()
{
	// Query the listOfLists object for the contents of the selected list.
	// Data binding ensures that the view is updated.

	selectedList = listOfLists.getItemAt( listOfListsView.selectedIndex );
}

function onAddItem()
{
	// Adding an item works differently than creating a new list, because the
	// TodoListView handles it. It already knows which list to add to, because
	// its data provider is data bound to selectedList.

	todoListView.onAddItem();
}

function onEdit()
{
	// Similiarly, going into the "edit state" is handled by todoListView.

	todoListView.editable = true;
}

function onShare()
{
	// Sending email is handled by the todoList object, which ultimately sends a web service request.

	selectedList.sendAsEmail();
}

Posted by sho at August 18, 2005 8:03 PM