Upload
gavin-williamson
View
213
Download
0
Embed Size (px)
Citation preview
2007 Adobe Systems Incorporated. All Rights Reserved.11
Joe BerkovitzVP of Engineering
Allurent, Inc.
with James Echmalian
Practical PatternsIn Flex
2007 Adobe Systems Incorporated. All Rights Reserved.2
Goals
Highlight the benefits of a pattern-driven, MVCS-based code organization.
Examine a few Design Patterns in a typical Flex application.
Share some practical, useful design and implementation ideas.
2007 Adobe Systems Incorporated. All Rights Reserved.3
Practical Patterns…
A Design Pattern is: A template for a solution to a
recurring type of problem. Not a library or framework
Benefits: Vocabulary for thinking and
talking about problems Combines technique and
rationale Helps communication
2007 Adobe Systems Incorporated. All Rights Reserved.4
…In Flex!
Patterns are usually described in a language-neutral way.
However… I want to look at patterns that harmonize with the distinctive features of Flex 2: MXML Events and data bindings Flex Framework Classes AS3 language
2007 Adobe Systems Incorporated. All Rights Reserved.5
Note on Frameworks
What’s a Framework? Examples: Flex, Cairngorm, PureMVC Prefab architecture and design Benefit: solves a set of problems Caveat: adds constraints, treats problems as
"already solved" This presentation is framework-neutral. We're looking at the stuff out of which MVC
frameworks are built (and you can build one!)
2007 Adobe Systems Incorporated. All Rights Reserved.6
About Allurent
Flex applications for e-commerce Emphasis on the “Rich” in “RIA” Supporting code samples are
roughly based on Allurent's internal approaches and frameworks.
2007 Adobe Systems Incorporated. All Rights Reserved.7
Tenets of Good Code
1. Well-organized: Classes have clear roles and responsibilities Modular – think of components on a circuit board
2. Simple, legible: How well can skilled programmers understand it?
3. Flexible, extensible: How much effort is required to revise its
organization? How much effort is required to add new features?
2007 Adobe Systems Incorporated. All Rights Reserved.8
M, V, C, and sometimes S
The Model-View-Controller-Service super-pattern is a backdrop for this presentation.
Proven principle for UI code organization. Model: represents state. View: presents and interacts. Controller: manages and mediates. Service: communicates.
Provides overall strategy, but not specific tactics. See my "Blueprint for Flex Apps" article:
http://www.adobe.com/devnet/flex/articles/blueprint.html
2007 Adobe Systems Incorporated. All Rights Reserved.9
The Power of MXML
<mx:Button id="loginButton" click="request = new URLRequest();request.url=LOGIN_URL; request.method = URLRequestMethod.POST; request.data = { userName: userName.text, password: password.text }; loader=new URLLoader(request); loader.addEventListener('complete', handleLogin); inProgress=true;" enabled="{!inProgress && userName.text != '' && currentState=='loginState' || currentState=='registerState'}" label="{currentState == 'loginState' ? 'Log In' : 'Register'}"/>
Simple? Legible? Flexible? Modular?
2007 Adobe Systems Incorporated. All Rights Reserved.10
MXML vs. MVCS
Beware the power of MXML! It encourages monolithic organization.
Keep control logic out of View classes. Instead, factor into external Controller classes.
Keep model properties out of View classes. Instead, bind to properties of a Model object.
What % of MXML code contained in Script block?
2007 Adobe Systems Incorporated. All Rights Reserved.11
MVCS From 5,000 meters
View
Service
Model
Controller
rendersmodelstate
invokesoperations
updatesmodel data
initiatesremote calls
2007 Adobe Systems Incorporated. All Rights Reserved.12
MVCS From 4,999 meters
View
Service
Model
Controller interacts with user
notifies modelchanges
rendersmodelstate
invokesoperations
managesview state
updatesmodel data
initiatesremote calls
notifiesof completion
2007 Adobe Systems Incorporated. All Rights Reserved.13
Example of an MVCS Sequence
View
invokes user gesture
invokes
responds
presents
updates with service results
Model Controller Command
notifies
Service
creates
executes
presents
updates for user feedbacknotifies
2007 Adobe Systems Incorporated. All Rights Reserved.14
On to Patterns
Presenting patterns: “What’s my motivation?” Diagram Condensed code samples Benefits, gotchas
We will discuss: View Patterns Model Patterns Controller Patterns Putting it all together.
2007 Adobe Systems Incorporated. All Rights Reserved.15
FacesController
FacesView
Problem: View to Controller Relationship
Why does a View need to invoke a Controller? To transmit a user
request for some action To notify of UI state
changes
There are multiple Controllers! Some are view-specific, some are application-wide.
View
SearchBar
FacesView
AppView
AppController
FacesController
Controller
2007 Adobe Systems Incorporated. All Rights Reserved.16
Explicit Invocation with Singletons
<mx:Panel . . . > <mx:Button id="searchButton" click="FacesController.search(targetInput.text)" . . ./>. . .</mx:Panel>
Bad Assumption: there is exactly one controller in the application Bad Remedy: propagate references to all controllers into all views
that might need them
2007 Adobe Systems Incorporated. All Rights Reserved.17
Problem: View to Controller Relationship
How does a View class invoke the right Controller? Method calls? Event dispatching?
2007 Adobe Systems Incorporated. All Rights Reserved.18
Problem: View to Controller Relationship
How does a View class locate its Controller? Local reference?
Problem: multiple views, multiple references. Singleton?
Problem: sacrifice flexibility. Controller adds the event listeners it needs.
Problem: complexity vs. breakage of encapsulation.
2007 Adobe Systems Incorporated. All Rights Reserved.19
Pattern: "Chain of Command"
View may dispatch an event with no specification of who handles it.
“Implicit Invocation” Application is responsible for
adding event listeners. Event framework twists:
Events bubble up to top of view hierarchy (AS3 feature).
All events are of a single “type”. A “kind” property tells what the view is asking for.
View
SearchBar
FacesView
AppView
AppController
FacesController
Controller
event bubbling
event bubbling
2007 Adobe Systems Incorporated. All Rights Reserved.20
Handling Asynchronicity: "Command"
Controller is called in response to user gestures
Hands off asynchronous work to a Command object that invokes Service, handles results and errors when they arise
DocumentService
FacesController
SearchCommand
updatesmodel data
UIEventevent fromView determines
which Command tocreate and execute…
2007 Adobe Systems Incorporated. All Rights Reserved.21
Implicit Invocation: Event Dispatch
<mx:Panel . . . > <mx:Metadata> [Event(name="uiEvent",type="UIEvent")] </mx:Metadata>
<mx:Button id="nextButton" click="dispatchEvent(new UIEvent(UIEventKind.NEXT))" . . ./>. . .</mx:Panel>
Assumption: UIEvent’s constructor enables bubbling by default.
2007 Adobe Systems Incorporated. All Rights Reserved.22
Implicit Invocation: Event Handling
Thanks to event bubbling, only ancestor Views require an event listener.
Event metadata permits a listener to be added via MXML:
<RootView id="view" width="100%" height="100%" model="{model}" uiEvent="dispatcher.handleUiEvent(event)" />
2007 Adobe Systems Incorporated. All Rights Reserved.23
Implicit Invocation: Pros and Cons
Pros: View class independent of Controller types. View class can reach the right Controller from anywhere in
component hierarchy. Modular development / testing. Single event channel for logging / metrics.
Cons: Requires switch logic on Controller side. Requires “marshalling” of command into event and
“demarshalling” on controller side. Issue: how to keep event kinds unique across applications.
2007 Adobe Systems Incorporated. All Rights Reserved.24
Code Interlude #1
Source files: “UIEvent.mxml” “UIEventKind.mxml” “FacesView.mxml” “SearchBar.mxml”
2007 Adobe Systems Incorporated. All Rights Reserved.25
The View-Model Relationship
View keeps strongly typed reference to its Model:
[Bindable]public var model:Model;
Model is set by Controller, or: By parent MXML document, like this:
<MyChild model=“{model}”/>
Or like this:
<MyChild2 model=“{model.somePiece}”/>
Through IDataRenderer if necessary:
<mx:Binding source=“data as Model” destination=“model”/><mx:Binding source=“model” destination=“data”/>
2007 Adobe Systems Incorporated. All Rights Reserved.26
Goal: No-Fuss Bindings
<mx:Text text="{model.summary}" . . . />
<mx:LinkButton id="splitButton" label="{model.splitButtonLabel}" visible="{model.splitEnabled}" includeInLayout="{model.splitEnabled}" . . . />
<mx:Repeater id="rows" dataProvider="{model.gridData}">
<mx:Repeater id="cols" dataProvider="{rows.currentItem}">
<mx:Image source="{cols.currentItem}“ . . ./> </mx:Repeater></mx:Repeater>
2007 Adobe Systems Incorporated. All Rights Reserved.27
Display Model: A Proxy for its View
“Display Model” object contains: Display state properties Control state properties Complete support for the View.
From a Controller's perspective, the Display Model “stands for” its View
All changes to state of display are effected through changing bound properties of Display Model
2007 Adobe Systems Incorporated. All Rights Reserved.28
Designing Display Models
Get extended mileage out of data bindings! Consider patterns:
Adapter Pattern – need Model Y, have Model X, write an X-Y Adapter.
Patterns for simplifying complex binding expressions.
Patterns for binding currentState to fire off Transitions.
2007 Adobe Systems Incorporated. All Rights Reserved.29
A Model OrganizationC
on
troller
Views
Display Models
456123
Business Models
456123
123 456
2007 Adobe Systems Incorporated. All Rights Reserved.30
Display Model vs. Business Model
Display Model: Display data,
formatted to support the View
Control state Structure based on
View hierarchy Supports bindings
Business Model: Raw business data
from server – structure dictated by web services
Structured for efficient transport
Does not support bindings
2007 Adobe Systems Incorporated. All Rights Reserved.31
Derived Models: "Adapter" Pattern
Motivations: Underlying model sometimes requires radical restructuring for
view to be written simply. Want to isolate View developer from model mismatch Need to give Controller control over flow of data Want to keep Controller logic as general as possible.
Summary: Create an "Adapter" that wraps a more basic model and
exposes what the view wants to see
2007 Adobe Systems Incorporated. All Rights Reserved.32
Summarizing Model AdapterC
on
troller
View
Display Models
Business Models
45612345
average length # of occurrences
4 2
There are {model.count} numberswith average length of {model.avgLen}.
2007 Adobe Systems Incorporated. All Rights Reserved.33
Problem: Complex View Interactions
What’s a complex View interaction? A change in View state involving multiple components. No change in Model, no Service invocation, so... No need to invoke Controller. Beyond the capability of Effects or Transitions alone. Examples:
Zooming, panning Input form validation
Problems: Managing state of interaction requires a mini-Controller. MXML seduces us into piling script into a View class!
2007 Adobe Systems Incorporated. All Rights Reserved.34
One Solution: “Smart Container”
Subclass a Container class; add logic for hiding and revealing some of its children.
<mx:Canvas …> <mx:Script> // state variables here
private function handleStart():void { /* control logic here */ }
private function handleComplete():void { /* yadda yadda */ }
</mx:Script>
<mx:Button id="startButton" label="Start“ click=“handleStart()”/>
<mx:Image id="theImage" source="{_displayBitmap}" width="700" height="700“ complete=“handleComplete()”/>. . .</mx:Canvas>
2007 Adobe Systems Incorporated. All Rights Reserved.35
Smart Container Reconsidered
Advantages: Solves the problem. Conceptually works – a container manages its children
Problem: logic is not reusable. Locked into a superclass. Locked into a container-component relationship. Must specify component types at compile time (or use
delayed instantiation).
Resist using inheritance to add behaviors to view classes.
2007 Adobe Systems Incorporated. All Rights Reserved.36
A Better Solution: View Mediator
Push the behavior out into a Mediator class: Is not a UIComponent Encapsulates logic and state of an interaction Associated with a number of client components May expose bindable properties for client components.
Parent MXML document: Associates Mediator with components Binds Mediator properties to properties of components.
Advantages: flexibility and reusability Types of participating components are flexible. Relationships in view hierarchy are flexible.
2007 Adobe Systems Incorporated. All Rights Reserved.37
View Mediator: Illustrations
<mx:Canvas …>
<mx:Button id="startButton“ label="Start"/>
<AnimationMediator startControl="{startButton}" targetContainer="{this}" targetLoader="{theImage}"/>
<mx:Image id="theImage“ source="{_displayBitmap}“ width="700" height="700"/>
. . .</mx:Canvas>
View
ViewRole2
ViewRole3
ViewRole1
Mediator
state
ViewRole4
events/bindings
events/bindings
2007 Adobe Systems Incorporated. All Rights Reserved.38
Code Interlude #2
Source files: “FacesView.mxml” “FaceOpenCloseMediator.as”
2007 Adobe Systems Incorporated. All Rights Reserved.39
Putting It All Together
Motivations: Need to build software system consisting of many different,
interconnected modules. Need flexible configuration. Mixture of visual and non-visual modules.
Solution: Develop configurable MVCS components. Use MXML to stitch them together.
Related Patterns: “Inversion of Control”
2007 Adobe Systems Incorporated. All Rights Reserved.40
Summary and Conclusions
MVCS and Design Patterns are useful tools for sharing best practices in design and implementation.
Data bindings, AS3 events and MXML suggest some interesting, new variations on well-worn patterns.
Things to do: Read more about MVCS and Design Patterns Share pattern ideas with fellow developers Spend more up-front time on analysis & design Build great Flex applications!
Latest presentation materials:http://joeberkovitz.com/max2007/