|
|
||||||
| Ultrashock Tutorials > Flash 8 > XML Portfolio Viewer | ||||||
|
||||||
|
|
XML Portfolio Viewer |
|
||||
ArchitectureIf you assign ten different programmers a task, it is likely you will see ten different implementations and ten different arguments as to why each implementation is the 'best.' When people ask me about my favorite pattern, I always say it's the 'six-month' pattern. That's where you go back to an application six months after implementation. If you can still understand the architecture and make reasonable modifications in a quick and easy manner, it was a good implementation. Instead of trying to force the application to fit a particular pattern, I will attempt to create a six-month pattern for the portfolio viewer. In the process, I hope to expose some of the thinking process and tradeoffs in application development. Instead of promoting a particular pattern or point of view, I want to illustrate different alternatives. I strongly encourage you to modify the architecture. From past experience, I've found that a great way to learn is to take something that works and improve upon its implementation. MVC At a high level, the architecture bears a resemblance to a MVC (Model-View-Controller) application. I'm an old-school assembler programmer and had to be dragged into OOP languages like Smalltalk and C++ kicking and screaming. My first exposure to the MVC pattern was writing plugins for 3ds max, working with the Windows message pump. So, every discussion I've seen regarding MVC in Flash seems somewhat foreign. I view MVC like any other pattern; it is a general template or outline for application development, not a round hole in which I wish to force a square peg. When I say MVC, I am referring to an application structure with a single Controller or Manager class, and a set of classes individually concerned with application data and application display. A driver program -- .FLA in this case -- calls methods of the Controller and responds to events dispatched by the Controller to run the application. Model classes are concerned exclusively with loading and managing application data. The View and Controller agree on an interfaces to Model data, allowing them to either request or modify data. Neither the View or Controller are exposed to the Model's internal representation of data or how the Model obtains data. In other words, neither the View or Controller care that the Model data is represented in static XML files. Next week, the Model data may come from a Webservice. The week after, it may be directly queried from a database. As long as the Model, View, and Controller agree on interfaces for application data, Model sources and structure may change without affecting anything else in the application. The View is responsible for application display. The View exposes public methods to the Controller for display of information collected by the Model. Neither the Model or Controller care whether the View uses a low-level TextField or a third-party TextArea component or some other means to display a particular item. The specific means of display for any component of the application should be independent of the Model data. Display details should be completely encapsulated away from the Controller. The Controller directs Views of the application through simple, display-independent methods. The Controller manages application logic and serves as a broker between the Model, View and the driver. In Windows applications, the Controller executes a tight loop around the message pump and is exposed to every action taken by the user. In a Flash application, it is annoying to bubble up every single viewer action to the Controller, just to determine how to process a button click. It is expedient to allow either the View or View helper classes process some of the lower-level interactivity, thus taking on actions that might typically be relegated to a Controller. In this regard, it could be argued that the current implementation is a closer match to Model-View-Presenter. Every implementation of MVC is both application-dependent and dependent on the personal views of the programming team implementing the application. The team should agree on interfaces between the Model, View, and Controller allowing them to work independently on each area of the application. If this is accomplished and reasonable future changes have only a local effect on the code base, then they have met the spirit of the pattern. Portfolio Viewer For the portfolio viewer, the first task is to decide how to divide application responsibilities over the driver, Model, View, and Controller. A reasonable architecture is one that both performs its specified task and holds up well to reasonable changes. One of the first items to consider is how the application might change over time. The most likely change is the layout itself, repositioning and resizing components. To a large degree, this has already been taken into consideration with relative components. The means used to display components might also change over time. Primitive TextFields might be replaced with more general-purpose display components. Item display is isolated away from the primary View code by encapsulating basic item data and display logic in a LayoutItem class. Custom item display is handled by classes that extend LayoutItem. This allows the Model to place data in a LayoutItem class (or subclass) and provides the View with a consistent API for displaying components. Portfolio data can be placed in a simple PortItem class. During parsing, the Model places portfolio data in instances of the PortItem class. Changes in portfolio data are localized to the parser and PortItem class. After processing all data, the Model contains two primary data arrays; an array of PortItem references and an array of LayoutItem instances or instances of LayoutItem subclasses. The latter array contains named references to an Object with a known API for manipulating components in the layout. Style management is handled by a StyleMgr class. Individual style properties are placed in a StyleLayout class. StyleMgr handles the task of collecting StyleLayout references by name and registering LayoutItem instances with each style. The StyleMgr is owned by the Controller. A reference is passed to the Model to load styles as they are parsed. Changes are most likely individual style properties, which are local to the StyleLayout class and do not affect the StyleMgr architecture. One thing I normally do with the Controller that is a deviation from the norm is to break the application up into small, well-defined tasks. The Controller exposes public methods to implement each task and dispatches events on their completion. The driver (.FLA file) calls Controller methods to execute each task in the application. Normal convention is to expose a single method that accepts all necessary input data and then has the Controller execute the entire application. Any event dispatch is upon completion of the application. What is gained by breaking the application into small segments? One thing you learn by working on applications for other organizations is that there are people in the company who feel a constant need to justify their existence and position. This is often accomplished by getting their 'stamp' on an application, i.e. adding on requirements. These requirements are presented as something that 'saves' the application from a critical mistake or makes it significantly better. In reality, the requirements amount to nothing more than useless busywork. Let me give you a real example. In an application similar to this one (i.e. read XML data, display thumbnails, then display auxiliary information after clicking on a thumbnail), a marketing person insisted on adding a modal window that appeared just before the thumbnails displayed. The window stated that all material displayed in this application was copyrighted and could not be used outside the application. This requirement was provided two days before the final due date. Forget the fact that the project had been specified in detail two months earlier. Forget the fact that the .SWF was displayed inside an HTML page with a copyright notice and explanation that all material in the page was protected. Forget the fact that the .SWF used a combination of FlashVars and System.capabilities.playerType to ensure that the application displayed nothing unless it was inside the client-generated page containing the full copyright notice. The new popup window *had* to be displayed, otherwise it would be legal disaster. No, this person was not a lawyer. I like to resuse as much code as possible in between projects, but there is always at least one of these useless requirements added to an application. They always seem to be added just before an important deadline. Every such change takes a reasonable and possibly reusable code base and adds on hack after hack. The above case might seem to require new code in both the Controller and View classes. By breaking the application up into small, discreet steps, I was able to add the popup Window in an event handler in the driver, isolating the change from the Controller and View classes. The change was made quickly and preserved the existing Controller and View code base. This process makes it easier to reuse sections of View and Controller code in other applications. No matter how well you and your team plan and implement a project, some outside influence always manages to screw up your plans. One means to help isolate the code base from such influences is to segment the application into discreet steps and use event handlers in the driver to execute each step in sequence. When people want to get their 'stamp' on the application, the new code is placed inside an event handler in the driver, not inside the Controller. With luck, you might only need to add some accessor functions in the Controller to return data values. Application Steps For tutorial purposes, the application is broken into the following steps. 1) Load layout file - dispatch event on completion. 2) Load portfolio file - dispatch event on completion. 3) Initialize the primary application view - dispatch event on completion. 4) Load thumbnail images into container Following is a simple architecture diagram. It's not UML, but the diagram provides a high-level view of the application structure and is a prelude to what might be developed in UML.
Before discussing the application components, it is useful to decide on a preloading and error-handling strategy. |
||||||
©2006 Ultrashock.com - All rights reserved |