Accessibility

Table of Contents

An architectural blueprint for Flex applications

MVCS (Model-View-Controller-Service) architecture in ReviewTube

Now I'll return to MVCS, looking at ReviewTube and referring to specific features and objects within it. Our once abstract architecture diagram now looks like Figure 4.

Block diagram of the ReviewTube application

Figure 4. Block diagram of the ReviewTube application

This diagram includes various elements that make up ReviewTube. For instance, VideoInfo is a Model class that represents the information known about some video clip; MediaService is a Service class that talks to YouTube. So I can now start to talk about specific examples of Model, View, Controller, and Service objects in more detail.

When I'm done with examining the MVCS elements of ReviewTube, I'll follow a single user action in ReviewTube all the way through the system, from the beginning to the end.

Model objects

I'll kick off with our Model (see Figure 5), whose main job is to represent our application's state, and what it knows about the outside world. By walling all such knowledge off within the Model, one makes it easy to change our definition of what this state is, without having to change many other data structures throughout the application.

Application state in the ReviewTube Model

Figure 5. Application state in the ReviewTube Model

In ReviewTube, the Model includes the following:

  • VideoInfo objects with attached Comments, representing information known about particular videos
  • Collections of related VideoInfos, e.g. Top or Recent
  • A user object, representing some registered ReviewTube user
  • The Session object, containing a current User (if known) and a currently selected VideoInfo

In all cases, these are passive objects that hold pure information, with no visual or interactive aspects and no interaction with any other part of the system. Such objects are often referred to as value objects. Any change to the state of these objects should dispatch events so that interested View objects will update themselves.

Look at VideoInfo for an example of some key guidelines:

package com.joeberkovitz.reviewtube.model
{
    import mx.collections.ArrayCollection;
    
    /**
     * Value object representing all known information about a Video.
     */
    [Bindable]
    public class VideoInfo extends ValueObject
    {
        public var reviewTubeId:int = -1;
        public var providerId:String;
        public var providerMediaUrl:String;
        public var providerMediaUrlRequested:Boolean;
        public var removed:Boolean;
        
        public var creationDate:Date;
        public var title:String;
        public var duration:int;
        public var description:String;
        public var thumbnailUrl:String;

        // elements are Comments
        public var comments:ArrayCollection = new ArrayCollection();
        public var commentCount:int;
        public var modificationDate:Date;
   }
}

This class illustrates some typical features of a model object:

  • It's defined in a special package, in this case com.joeberkovitz.reviewtube.model.
  • There are no references to any non-Model classes.
  • There are no functions, only read/write properties. Properties in ActionScript are the cleanest way to represent "pure information" in such an object. In general, avoid functions, since they introduce more complexity, and stray interactions with non-Model objects can creep in. Complex logic for model objects usually belongs in the Controller.
  • Every property is declared [Bindable], ensuring that change events will be dispatched when any property is changed. For example, when a comment is added to a VideoInfo, the commentCount property is incremented. Because it's Bindable, a PropertyChangeEvent for commentCount is dispatched. This event causes the corresponding "# of comments" cell in a VideoBrowser's DataGrid to update itself accordingly.
  • ArrayCollections are always used to represent lists, not Arrays. This ensures that additions, updates and deletions of items will dispatch CollectionEvents if change, keeping all Views up to date. For example, when a comment is removed from the comments property (whose elements are Comment model objects), a CollectionEvent is dispatched from that ArrayCollection. The caption display, the time strip, and the comment list all use this same ArrayCollection as a data provider, and the dispatched event causes each view to automatically remove its display of the deleted comment in its own way.

In thinking about your Model classes and data structures, it's a really good idea to optimize for the benefit of Views. Many developers take pains to duplicate existing server-side data structures on the client side with virtually no change. I think this is often a mistake, because server-side object design is driven by a very different set of concerns, like getting the data in and out of a relational database, or supporting back-end business operations.

Don't just mirror the model on the server. Consider optimizing your client-side model objects so that the user interface is as easy as possible to construct. This means thinking hard about how events and data bindings will work, because these are the workhorses of successful Model/View communication. There may be some slight rearrangements involved in moving data back and forth, but they will often pay off in much simpler presentation code.