<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" 
      xmlns:thr="http://purl.org/syndication/thread/1.0">
  <link rel="alternate" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html" />
  <link rel="self" type="application/atom+xml" href="http://www.insideria.com/atom.xml" />
  <id>tag:www.insideria.com,2009://34/tag:www.insideria.com,2008://34.33983-</id>
  <updated>2009-11-16T15:21:31Z</updated>
  <title>Comments for FrameworkQuest 2008 Part 3: Framework Agnostic Views with PureMVC (http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html)</title>
  <generator uri="http://www.sixapart.com/movabletype/">Movable Type 4.21-en</generator>
  <entry>
    <id>tag:www.insideria.com,2008://34.33983</id>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://blogs.oreilly.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=34/entry_id=33983" title="FrameworkQuest 2008 Part 3: Framework Agnostic Views with PureMVC" />
    <published>2008-12-16T14:00:00Z</published>
    <updated>2009-03-13T14:49:54Z</updated>
    <title>FrameworkQuest 2008 Part 3: Framework Agnostic Views with PureMVC</title>
    <summary>Last week we took a look at how to clean up our Twitter client by using Cairngorm to separate the concerns according to the time honored MVC architectural pattern. Now we&#8217;re going to see how it feels to work with...</summary>
    <author>
      <name>Tony Hillerson</name>
      
    </author>
    
    <category term="Adobe Feed" />
    
    <category term="Features" />
    
    <content type="html" xml:lang="en" xml:base="http://www.insideria.com/">
      <![CDATA[<p>Last week we took a look at how to clean up our Twitter client by
using Cairngorm to separate the concerns according to the time honored MVC
architectural pattern. Now we&#8217;re going to see how it feels to work with <a
href="http://puremvc.org/"><span style='color:#000099'>PureMVC</span></a>, an
ActionScript framework that wants to make it easier to do just that.</p>



<p>PureMVC was created by <a
href="http://puremvc.org/component/option,com_contact/Itemid,3/"><span
style='color:#000099'>Cliff Hall</span></a>, and is maintained in a few
different forms by a <a href="http://puremvc.org/content/view/51/1/"><span
style='color:#000099'>community of developers</span></a>.</p>



<p>Notice that PureMVC is an ActionScript framework. More
specifically, there is an ActionScript 2 and two ActionScript 3 versions of
PureMVC, one regular and one multi-core, which can work with Flex with Modules
for instance. That&#8217;s one thing that PureMVC makes clear is that it has no
dependencies on the Flex Framework, which means that it&#8217;s flexible enough to
work with Flash projects as well as Flex. In fact PureMVC also has ports in the
works or already developed for Java, C#, ColdFusion, Ruby, and others, so it
tries to be a language independent take on an MVC framework.</p>



<p>Being framework independent means that unlike Cairngorm, PureMVC
doesn&#8217;t rely on Flex binding. Not only that, but PureMVC wants to make sure
that framework code doesn&#8217;t make it outside any of the classes that aren&#8217;t
clearly framework oriented. This certainly applies to view classes, so PureMVC
uses Flash events instead of a framework specific event type. This encourages
the development of views as black box components, which encourages a loosely
coupled architecture (which is also possible with Cairngorm) as well as a
framework independent view (which is not, strictly speaking, possible with
Cairngorm).</p>



<p>A little bit about the framework. PureMVC has a <span class=Code><span
style='font-family:Monaco'>Controller</span></span>, a <span class=Code><span
style='font-family:Monaco'>Model</span></span>, and a <span class=Code><span
style='font-family:Monaco'>Facade</span></span>, all singletons.<span
style="mso-spacerun: yes">&nbsp; </span>The <span class=Code><span
style='font-family:Monaco'>Controller</span></span> has an API for sending and
receiving <span class=Code><span style='font-family:Monaco'>Notifications</span></span>,
which are event-like messages that any PureMVC object, except, by convention, <span
class=Code><span style='font-family:Monaco'>Proxies</span></span>, can
subscribe to. <span class=Code><span style='font-family:Monaco'>Proxies</span></span>
never receive, they only send, <span class=Code><span style='font-family:Monaco'>Notifications</span></span>.
The <span class=Code><span style='font-family:Monaco'>Model</span></span> keeps
a set of named <span class=Code><span style='font-family:Monaco'>Proxy</span></span>
objects, which are responsible for a particular type of data in the model. For
instance an application that has <span class=Code><span style='font-family:
Monaco'>User</span></span> objects would probably have a <span class=Code><span
style='font-family:Monaco'>UserProxy</span></span> that handled requests for
users and managed a collection of users. The <span class=Code><span
style='font-family:Monaco'>Model</span></span> and <span class=Code><span
style='font-family:Monaco'>Controller</span></span> are unseen, and only
accessed through the <span class=Code><span style='font-family:Monaco'>Facade</span></span>.
The <span class=Code><span style='font-family:Monaco'>Facade</span></span> has
an API for working with both the Model and Controller, sending <span
class=Code><span style='font-family:Monaco'>Notifications</span></span>,
looking up <span class=Code><span style='font-family:Monaco'>Proxies</span></span>,
and so forth. Your application implements the <span class=Code><span
style='font-family:Monaco'>Facade</span></span> class either by implementing
the interface or extending a <span class=Code><span style='font-family:Monaco'>Facade</span></span>
class that PureMVC provides. That brings up another point about PureMVC. Every
part of PureMVC implements an interface, which is also provided so that you
could replace any part of PureMVC with your own implementation if you wanted.</p>



<p>Let&#8217;s look at a flow of events in a PureMVC application.</p>

<img src="http://www.insideria.com/upload/2008/11/puremvc.gif" alt="puremvc.gif"/>


<p>When a user interacts with the view, a Flash event is dispatched
from the view. A <span class=Code><span style='font-family:Monaco'>Mediator</span></span>
responsible for that view has already registered for interesting events and
when it receives this one, it may do view specific logic. Most likely, it will
also send a <span class=Code><span style='font-family:Monaco'>Notification</span></span>
which any other PureMVC objects may elect to receive. Keep that point in mind -
that&#8217;s a very loosely coupled architecture. Any number of other <span
class=Code><span style='font-family:Monaco'>Mediators</span></span> or <span
class=Code><span style='font-family:Monaco'>Commands</span></span> can listen
for a certain notification and do whatever it is they do.</p>



<p>The <span class=Code><span style='font-family:Monaco'>Controller</span></span>
is what gets called when a <span class=Code><span style='font-family:Monaco'>Notification</span></span>
is sent, and it tells anyone interested in those types of <span class=Code><span
style='font-family:Monaco'>Notifications</span></span> that they have some new
mail. It&#8217;s also possible to register a <span class=Code><span style='font-family:
Monaco'>Command</span></span> to a certain type of <span class=Code><span
style='font-family:Monaco'>Notification</span></span>, and if one is found,
it&#8217;s instantiated and executed. This is typically the case in service calls.
The <span class=Code><span style='font-family:Monaco'>Command</span></span>&#8217;s
job is then to get reference to a <span class=Code><span style='font-family:
Monaco'>Proxy</span></span> through the <span class=Code><span
style='font-family:Monaco'>Facade</span></span> and ask it to take some
appropriate action. The <span class=Code><span style='font-family:Monaco'>Proxy</span></span>
can either interact directly with some service if necessary, or as is sometimes
done, a Cairngorm-style <span class=Code><span style='font-family:Monaco'>BusinessDelegate</span></span>
can be invoked instead. PureMVC is flexible on this point, and some developers
find it desirable to have this service encapsulation for the same reasons as we
already described last time - it helps cushion the application from change.</p>



<p>Once the service returns to the <span class=Code><span
style='font-family:Monaco'>Proxy</span></span> directly or through a <span
class=Code><span style='font-family:Monaco'>Delegate</span></span>, it sends a <span
class=Code><span style='font-family:Monaco'>Notification</span></span>, which a
<span class=Code><span style='font-family:Monaco'>Mediator</span></span> or
another <span class=Code><span style='font-family:Monaco'>Command</span></span>
can receive. If the <span class=Code><span style='font-family:Monaco'>Mediator</span></span>
listens for that <span class=Code><span style='font-family:Monaco'>Notification</span></span>,
it&#8217;s because something needs to change on the view in response to the new state
of the data in the <span class=Code><span style='font-family:Monaco'>Proxy</span></span>,
and the <span class=Code><span style='font-family:Monaco'>Mediator</span></span>
is responsible for changing the view. It may do this by wiring data in a data
provider directly to a property on the <span class=Code><span style='font-family:
Monaco'>Proxy</span></span>.</p>



<p>So, a few differences from what we&#8217;ve seen with Cairngorm are:</p>



<p style='margin-left:.25in;text-indent:-.25in;mso-list:l1 level1 lfo2;
tab-stops:list .25in'><![if !supportLists]>

<p>1.<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp; </span><![endif]>No
framework code in the views.<o:p></o:p></p>

<p style='margin-left:.25in;text-indent:-.25in;mso-list:l1 level1 lfo2;
tab-stops:list .25in'><![if !supportLists]>

<p>2.<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp; </span><![endif]>No
singleton model, instead a set of <span class=Code><span style='font-family:
Monaco'>Proxies</span></span><o:p></o:p></p>

<p style='margin-left:.25in;text-indent:-.25in;mso-list:l1 level1 lfo2;
tab-stops:list .25in'><![if !supportLists]>

<p>3.<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp; </span><![endif]>No
Flex Binding, instead all views are encapsulated from the framework by <span
class=Code><span style='font-family:Monaco'>Mediators</span></span>.<o:p></o:p></p>



<p>Now that we've heard the dry details, let's take a tour of our
app.</p>



<p class=Sub-heading>PureMVC TwitteRIA</p>

<p>As mentioned, most PureMVC actions go through the <span
class=Code><span style='font-family:Monaco'>Facade</span></span> we created, <span
class=Code><span style='font-family:Monaco'>ApplicationFacade</span></span> in
this case, and most access to the <span class=Code><span style='font-family:
Monaco'>Facade</span></span> is through helper methods on <span class=Code><span
style='font-family:Monaco'>Mediator</span></span>, <span class=Code><span
style='font-family:Monaco'>Proxy</span></span>, or <span class=Code><span
style='font-family:Monaco'>Command</span></span>. One time you&#8217;ll probably act
directly on the <span class=Code><span style='font-family:Monaco'>Facade</span></span>
instance is at application startup, like we do here:</p>



<p><b>twitteria_puremvc/src/twitteria_puremvc.mxml #8, 16<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
creationComplete="<span class="quote">facade.startup(this)</span>"
...
<span class="category1">private</span> <span class="category1">var</span> facade:ApplicationFacade = 
                     ApplicationFacade.getInstance();</pre>
</code>

</div></div> 


<p>We get a reference to the instance of the <span class=Code><span
style='font-family:Monaco'>Facade</span></span> and call <span class=Code><span
style='font-family:Monaco'>startup</span></span>, passing the instance of the
  view, when the application is complete. Let&#8217;s go through the startup phase and
see what happens there. </p>



<p><b>twitteria_puremvc/src/com/insideria/twitteria/ApplicationFacade.as
#23-30<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
override protected <span class="category1">function</span> initializeController():<span class="category1">void</span> {
     <span class="category1">super</span>.initializeController(); 
     registerCommand(STARTUP,        StartupCommand);
     registerCommand(LOG_IN,              LogInCommand);
     registerCommand(SET_STATUS,          SetStatusCommand);
     registerCommand(LOAD_TIMELINE,  LoadTimelineCommand);
}</pre>
</code>

</div></div> 


<p>First of all, when <span class=Code><span style='font-family:
Monaco'>ApplicationFacade</span></span> is first instantiated, <span
class=Code><span style='font-family:Monaco'>initializeController</span></span>
is called by the framework. Here we register commands to string constants.
Later on, when we send <span class=Code><span style='font-family:Monaco'>Notifications</span></span>
created with these strings, the commands will be created and executed. For
instance, here&#8217;s the one for <span class=Code><span style='font-family:Monaco'>STARTUP</span></span>.</p>



<p><b>twitteria_puremvc/src/com/insideria/twitteria/ApplicationFacade.as
#10<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="category1">public</span> <span class="category1">static</span> const STARTUP:<span class="category2">String</span> = "<span class="quote">startup</span>";</pre>
</code>

</div></div> 


<p>And now when we call <span class=Code><span style='font-family:
Monaco'>startup</span></span> we send a notification with the <span class=Code><span
style='font-family:Monaco'>STARTUP</span></span> string, which will cause a <span
class=Code><span style='font-family:Monaco'>StartupCommand</span></span> to be
executed. When we send the notification we also send along a reference to the
application.<span class=Code><span style='font-family:Monaco'><o:p></o:p></span></span></p>



<p><b>twitteria_puremvc/src/com/insideria/twitteria/ApplicationFacade.as
#31-33<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="category1">public</span> <span class="category1">function</span> startup(app:twitteria_puremvc):<span class="category1">void</span> {
      sendNotification(STARTUP, app);
}</pre>
</code>

</div></div> 


<p><span class=Code><span style='font-family:Monaco'>StartupCommand</span></span>
is a <span class=Code><span style='font-family:Monaco'>MacroCommand</span></span>,
which means it executes a set of sub-commands which we add in the framework
called <span style='font-size:11.0pt;font-family:Monaco'>initializeMacroCommand</span>.</p>



<p><b>twitteria_puremvc/src/com/insideria/twitteria/controller/StartupCommand.as
#5-10<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="category1">public</span> <span class="category1">class</span> StartupCommand <span class="category1">extends</span> MacroCommand {
     override protected <span class="category1">function</span> initializeMacroCommand():<span class="category1">void</span> {
          addSubCommand(ModelPrepCommand);
          addSubCommand(ViewPrepCommand);
      }
}</pre>
</code>

</div></div> 


<p>The <span class=Code><span style='font-family:Monaco'>ModelPrepCommand</span></span>
sets up the model:</p>



<p><b>twitteria_puremvc/src/com/insideria/twitteria/controller/ModelPrepCommand.as
#9-16<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="category1">public</span> <span class="category1">class</span> ModelPrepCommand <span class="category1">extends</span> SimpleCommand {
      override <span class="category1">public</span> <span class="category1">function</span> execute(note:INotification):<span class="category1">void</span> {
            facade.<span class="category2">registerProxy</span>(<span class="category1">new</span> TimelineProxy());
            facade.<span class="category2">registerProxy</span>(<span class="category1">new</span> StatusProxy());
            facade.<span class="category2">registerProxy</span>(<span class="category1">new</span> UserProxy());
       }
}</pre>
</code>

</div></div> 


<p>And the <span class=Code><span style='font-family:Monaco'>ViewPrepCommand</span></span>
sets up the <span class=Code><span style='font-family:Monaco'>Mediators</span></span>
that control the views.</p>



<p><b>twitteria_puremvc/src/com/insideria/twitteria/controller/ViewPrepCommand.as
#12-18<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="category1">public</span> <span class="category1">class</span> ViewPrepCommand <span class="category1">extends</span> SimpleCommand {
      override <span class="category1">public</span> <span class="category1">function</span> execute(note:INotification):<span class="category1">void</span> {
            <span class="category1">var</span> app:twitteria_puremvc = note.getBody() 
                 as twitteria_puremvc;
            facade.registerMediator(
                 <span class="category1">new</span> ApplicationMediator(app)
            );
            facade.registerMediator(
                 <span class="category1">new</span> LoginViewMediator(app.loginView)
            );
            facade.registerMediator(
                 <span class="category1">new</span> MainViewMediator(app.mainView)
            );
       }
}</pre>
</code>

</div></div> 

<p>Let&#8217;s analyze those two commands. First of all, note that they
both extend <span class=Code><span style='font-family:Monaco'>SimpleCommand</span></span>.
Doing that gives them access through the <span class=Code><span
style='font-family:Monaco'>ApplicationFacade</span></span> singleton, which is
registered by the framework and provided to all framework classes. That lets
the commands register proxies and mediators easily. Registering those guys lets
anyone with access to the facade get a reference by name. We&#8217;ll look at that in
a bit.</p>



<p>One more thing to note is how we get the <span class=Code><span
style='font-family:Monaco'>STARTUP</span></span> notification passed to each
sub-command. Since we attached the reference to the application to the note, we
can grab that off the body and get a reference to the view items that each <span
class=Code><span style='font-family:Monaco'>Mediator</span></span> needs to
mediate.</p>



<p>Whew! That was a lot, and it all took place before the user even
sees the view. Now that<span style="mso-spacerun: yes">&nbsp; </span>all that
is in place we can finally look at logging in.</p>



<p class=Sub-heading>Logging In</p>

<p>One other big difference in the root application from the Cairngorm
version is an omission on the <span class=Code><span style='font-family:Monaco'>ViewStack</span></span>.</p>



<p><b>twitteria_puremvc/src/twitteria_puremvc.mxml #26<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
&lt;mx:ViewStack id="<span class="quote">mainViewStack</span>" bottom="<span class="quote">0</span>" left="<span class="quote">0</span>" right="<span class="quote">0</span>" top="<span class="quote">30</span>"&gt;</pre>
</code>

</div></div> 

<p>There&#8217;s no binding to tell the stack which child to show. To see
where the <span class=Code><span style='font-family:Monaco'>ViewStack</span></span>
is actually controlled, we look at the <span class=Code><span style='font-family:
Monaco'>ApplicationMediator</span></span>. When the Mediator is created in the <span
class=Code><span style='font-family:Monaco'>ViewPrepCommand</span></span> and
passed the application instance, the constructor keeps that reference.</p>



<p><b>twitteria_puremvc/src/com/insideria/twitteria/view/ApplicationMediator.as
#15-17<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="category1">public</span> <span class="category1">function</span> ApplicationMediator(viewComponent:twitteria_puremvc) {
     <span class="category1">super</span>(NAME, viewComponent);
}</pre>
</code>

</div></div> 


<p>Passing the app reference along with the <span class=Code><span
style='font-family:Monaco'>NAME</span></span> constant sets the <span
class=Code><span style='font-family:Monaco'>viewComponent</span></span>
property for this mediator and also registers with the <span class=Code><span
style='font-family:Monaco'>Facade</span></span> using <span class=Code><span
style='font-family:Monaco'>NAME</span></span>, which is an arbitrary string:</p>



<p><b>twitteria_puremvc/src/com/insideria/twitteria/view/ApplicationMediator.as
#10<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="category1">public</span> <span class="category1">static</span> const NAME:<span class="category2">String</span> = "<span class="quote">ApplicationMediator</span>";</pre>
</code>

</div></div> 



<p>Using that string lets anyone look the mediator up by that name.
It&#8217;s also usual to set up a little helper lookup to bring back the <span
class=Code><span style='font-family:Monaco'>viewComponent</span></span> as a
typed object of the type we know it to be:</p>



<p><b>twitteria_puremvc/src/com/insideria/twitteria/view/ApplicationMediator.as
#33-35<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
protected <span class="category1">function</span> <span class="category2">get</span> app():twitteria_puremvc {
     <span class="category1">return</span> viewComponent as twitteria_puremvc
}</pre>
</code>

</div></div> 


<p>When the <span class=Code><span style='font-family:Monaco'>ApplicationMediator</span></span>
is registered, a framework method is called to set up the mediator.</p>



<p><b>twitteria_puremvc/src/com/insideria/twitteria/view/ApplicationMediator.as
#33-35<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
override <span class="category1">public</span> <span class="category1">function</span> listNotificationInterests():<span class="category2">Array</span> {
     <span class="category1">return</span> [
           ApplicationFacade.VIEW_TIMELINE
      ];
}</pre>
</code>

</div></div> 


<p>One method the framework calls is <span style='font-size:11.0pt;
font-family:Monaco'>listNotificationInterests</span>. This should return a list
of strings that the mediator is interested in receiving. Then, whenever any
notification with those types are sent through the facade, this mediator will
get notified. Notification happens when the framework calls <span
style='font-size:11.0pt;font-family:Monaco'>handleNotification</span>.<span
style='font-size:11.0pt;font-family:Monaco'><o:p></o:p></span></p>

<p class=MsoNormal><span style='font-size:11.0pt;font-family:Monaco'><![if !supportEmptyParas]>&nbsp;<![endif]><o:p></o:p></span></p>

<p><b>twitteria_puremvc/src/com/insideria/twitteria/view/ApplicationMediator.as
#25-31<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
override <span class="category1">public</span> <span class="category1">function</span> handleNotification(note:INotification):<span class="category1">void</span> {
     <span class="category1">switch</span> (note.getName()) {
            <span class="category1">case</span> ApplicationFacade.VIEW_TIMELINE:
                 app.mainViewStack.selectedIndex = MAIN_VIEW;
            <span class="category1">break</span>;
      }
}</pre>
</code>

</div></div> 


<p>This method gets called when any notification that the mediator
is interested in gets sent. The usual process is to switch on the notification
name and then do the right thing.<span style="mso-spacerun: yes">&nbsp;
</span>In this case, when the <span class=Code><span style='font-family:Monaco'>VIEW_TIMELINE</span></span>
note comes through, we want to switch the <span class=Code><span
style='font-family:Monaco'>ViewStack</span></span> index to the <span
class=Code><span style='font-family:Monaco'>MAIN_VIEW</span></span> constant,
which just like the Cairngorm implementation and just like the no-framework
implementation, points to the right index to show <span class=Code><span
style='font-family:Monaco'>MainView</span></span>. So that&#8217;s how the <span
class=Code><span style='font-family:Monaco'>ApplicationMediator</span></span>
does what it do, as they say. When does the <span class=Code><span
style='font-family:Monaco'>VIEW_TIMELINE</span></span> notification get sent?
Let&#8217;s look at the <span class=Code><span style='font-family:Monaco'>LoginView</span></span>
to see.</p>



<p><b>twitteria_puremvc/src/com/insideria/twitteria/view/components/LoginView.mxml
#4-16<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
&lt;mx:Metadata&gt;
     [Event(<span class="category2">name</span>="<span class="quote">login</span>", <span class="category2">type</span>="<span class="quote">flash.events.Event</span>")]
&lt;/mx:Metadata&gt;

&lt;mx:Script&gt;
&lt;![CDATA[
     <span class="category1">public</span> <span class="category1">static</span> const LOGIN:<span class="category2">String</span> = '<span class="quote">login</span>';

     <span class="category1">public</span> <span class="category1">function</span> login():<span class="category1">void</span> {
           dispatchEvent(<span class="category1">new</span> Event(LOGIN));
      }
]]&gt;
&lt;/mx:Script&gt;</pre>
</code>

</div></div> 


<p>The first thing you may notice is that we&#8217;re back to dispatching
a regular Flash event when enter is pressed on the password field:</p>



<p><b>twitteria_puremvc/src/com/insideria/twitteria/view/components/LoginView.mxml
#27<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
enter="<span class="quote">login()</span>"</pre>
</code>

</div></div> 

<p>Who&#8217;s listening? The <span class=Code><span style='font-family:
Monaco'>LoginViewMediator</span></span>, which as also set up in the <span
class=Code><span style='font-family:Monaco'>ViewPrepCommand</span></span>. When
the mediator is created, it adds itself as an event listener for this type.</p>



<p><b>twitteria_puremvc/src/com/insideria/twitteria/view/LoginViewMediator.mxml
#15-19<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="category1">public</span> <span class="category1">function</span> LoginViewMediator(viewComponent:LoginView) {
     <span class="category1">super</span>(NAME, viewComponent);
 
      view.addEventListener(LoginView.LOGIN, login);
}</pre>
</code>

</div></div> 


<p>So when the view dispatches that event, the mediator&#8217;s login
method will be called.</p>



<p><b>twitteria_puremvc/src/com/insideria/twitteria/view/LoginViewMediator.mxml
#15-19<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="category1">private</span> <span class="category1">function</span> login(event:Event):<span class="category1">void</span> {
      <span class="category1">var</span> credentials:<span class="category2">Object</span> = {
                 username:view.usernameText.<span class="category2">text</span>,
                 <span class="category2">password</span>:view.passwordText.<span class="category2">text</span>
       };
      sendNotification(ApplicationFacade.LOG_IN, credentials);
}</pre>
</code>

</div></div> 


<p>The login method gets a little ad-hoc object together and sends
it along with a notification. We could change that to be a typed object, but
for now a hash is good enough. The note name is in the <span class=Code><span
style='font-family:Monaco'>LOG_IN</span></span> variable on the facade, and if
you&#8217;ll remember, that was registered to the <span class=Code><span
style='font-family:Monaco'>LoginCommand</span></span>. </p>



<p><b>twitteria_puremvc/src/com/insideria/twitteria/controller/LoginCommand.as
#11-19<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
override <span class="category1">public</span> <span class="category1">function</span> execute(note:INotification):<span class="category1">void</span> {
      <span class="category1">var</span> userProxy:UserProxy = 
           facade.retrieveProxy(UserProxy.NAME) as UserProxy;
      <span class="category1">var</span> timelineProxy:TimelineProxy = 
           facade.retrieveProxy(TimelineProxy.NAME) as TimelineProxy;
      <span class="category1">var</span> credentials:<span class="category2">Object</span> = note.getBody();
 
      userProxy.username = credentials['<span class="quote">username</span>'];
      userProxy.<span class="category2">password</span> = credentials['<span class="quote">password</span>'];
      sendNotification(ApplicationFacade.LOAD_TIMELINE);
}</pre>
</code>

</div></div> 


<p>The <span class=Code><span style='font-family:Monaco'>UserProxy</span></span>
simply stores the username and password; have a look at it if you want. With a
more complex login process it would get a little more complex too, but that&#8217;s
enough for here. Again, notice that the username/password hash is on the body
of the <span class=Code><span style='font-family:Monaco'>Notification</span></span>.
At the end of the command, we send out another notification, signaling that
log-in is complete and it&#8217;s time to load the timeline.</p>



<p class=Sub-heading>Loading The Timeline</p>

<p>To load the timeline, we call on the <span class=Code><span
style='font-family:Monaco'>TimelineProxy</span></span> in the <span class=Code><span
style='font-family:Monaco'>LoadTimelineCommand</span></span>, which was
registered to the <span class=Code><span style='font-family:Monaco'>LOAD_TIMELINE</span></span>
notification type.</p>



<p><b>twitteria_puremvc/src/com/insideria/twitteria/controller/LoadTimelineCommand.as
#10-13<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
override <span class="category1">public</span> <span class="category1">function</span> execute(note:INotification):<span class="category1">void</span> {
      <span class="category1">var</span> timelineProxy:TimelineProxy =
           facade.retrieveProxy(TimelineProxy.NAME) as TimelineProxy;
      timelineProxy.reload();
}</pre>
</code>

</div></div> 


<p>The <span class=Code><span style='font-family:Monaco'>reload</span></span>
method goes like this:</p>



<p><b>twitteria_puremvc/src/com/insideria/twitteria/model/TimelineProxy.as
#22-25<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="category1">public</span> <span class="category1">function</span> reload():<span class="category1">void</span> {
      <span class="category1">var</span> delegate:TwitterDelegate = <span class="category1">new</span> TwitterDelegate(<span class="category1">this</span>);
      delegate.loadTimeline();
}</pre>
</code>

</div></div> 


<p>Notice that the <span class=Code><span style='font-family:Monaco'>TimelineProxy</span></span>
implements <span class=Code><span style='font-family:Monaco'>IResponder</span></span>,
and that I&#8217;ve chosen to use the Business Delegate pattern. Nothing from here to
the service changed from the Cairngorm implementation except that it&#8217;s a <span
class=Code><span style='font-family:Monaco'>Proxy</span></span> instead of a <span
class=Code><span style='font-family:Monaco'>Command</span></span> calling the
delegate. These choices aren&#8217;t mandated by PureMVC, but it&#8217;s flexible enough to
allow this way of doing things. I&#8217;m not sure I like the <span class=Code><span
style='font-family:Monaco'>Proxy</span></span> being an <span class=Code><span
style='font-family:Monaco'>IResponder</span></span> because that limits it to
only one set of <span class=Code><span style='font-family:Monaco'>result</span></span>/<span
class=Code><span style='font-family:Monaco'>fault</span></span> methods and
only one call on the delegate. That could be changed to a more flexible event
listener approach, but for now I chose to keep things pretty similar to how
they were.</p>





<p><b>twitteria_puremvc/src/com/insideria/twitteria/model/TimelineProxy.as
#27-32<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="category1">public</span> <span class="category1">function</span> result(result:<span class="category2">Object</span>):<span class="category1">void</span> {
      <span class="category1">var</span> stati:<span class="category2">Array</span> = result as <span class="category2">Array</span>;
      currentTweets = <span class="category1">new</span> ArrayCollection(stati);
      sendNotification(ApplicationFacade.VIEW_TIMELINE);
      sendNotification(ApplicationFacade.TIMELINE_LOADED);
}</pre>
</code>

</div></div> 

<p>When the delegate returns to the result method, we fire off two
notifications: <span class=Code><span style='font-family:Monaco'>VIEW_TIMELINE</span></span>
and <span class=Code><span style='font-family:Monaco'>TIMELINE_LOADED</span></span>.
Why two? One lets the application know to change view states, and the other
lets the application know that there&#8217;s new data in the <span class=Code><span
style='font-family:Monaco'>TimelineProxy</span></span>. Those may happen
concurrently here, but they don&#8217;t always have to. If you remember back a bit, <span
class=Code><span style='font-family:Monaco'>VIEW_TIMELINE</span></span> was a
notification that the <span class=Code><span style='font-family:Monaco'>ApplicationMediator</span></span>
was interested in. When this notification makes it there, that mediator
switches the index in the <span class=Code><span style='font-family:Monaco'>ViewStack</span></span>
to show the <span class=Code><span style='font-family:Monaco'>MainView</span></span>,
as you saw above. Who&#8217;s interested in the <span class=Code><span
style='font-family:Monaco'>TIMELINE_LOADED</span></span> notification? That
would be the <span class=Code><span style='font-family:Monaco'>MainViewMediator</span></span>.</p>



<p><b>twitteria_puremvc/src/com/insideria/twitteria/view/MainViewMediator.mxml
#33-39<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
override <span class="category1">public</span> <span class="category1">function</span> handleNotification(note:INotification):<span class="category1">void</span> {
     <span class="category1">switch</span> (note.getName()) {
            <span class="category1">case</span> ApplicationFacade.TIMELINE_LOADED:
                 view.currentTweets = getTimelineProxy().currentTweets;
            <span class="category1">break</span>;
      }
}</pre>
</code>

</div></div> 


<p>When the <span class=Code><span style='font-family:Monaco'>MainViewMediator</span></span>
gets the <span class=Code><span style='font-family:Monaco'>TIMELINE_LOADED</span></span>
note, it sets the <span class=Code><span style='font-family:Monaco'>currentTweets</span></span>
property to the <span class=Code><span style='font-family:Monaco'>TimelineProxy</span></span>&#8217;s
<span class=Code><span style='font-family:Monaco'>currentTweets</span></span>.
This is how the framework gets around binding the view to the model - the
mediator hooks the properties on a proxy directly to the view.</p>



<p>Now the view is on the <span class=Code><span style='font-family:
Monaco'>MainView</span></span> and the tweets are loaded into the list. It&#8217;s
time to set the status.</p>



<p class=Sub-heading>Setting Status</p>

<p>Just as the <span class=Code><span style='font-family:Monaco'>LoginView</span></span>
dispatches a plain-old-flash-event when you hit enter, the <span class=Code><span
style='font-family:Monaco'>MainView</span></span> dispatches an event when the
status is set by pressing enter in the status field</p>



<p><b>twitteria_puremvc/src/com/insideria/twitteria/view/components/MainView.mxml
#4-23<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
&lt;mx:Metadata&gt;
     [Event(<span class="category2">name</span>="<span class="quote">setStatus</span>", <span class="category2">type</span>="<span class="quote">flash.events.Event</span>")]
&lt;/mx:Metadata&gt;

&lt;mx:Script&gt;
&lt;![CDATA[
     <span class="category1">import</span> mx.collections.ArrayCollection;

     <span class="category1">public</span> <span class="category1">static</span> const SET_STATUS:<span class="category2">String</span> = '<span class="quote">setStatus</span>';

     [Bindable]
     <span class="category1">public</span> <span class="category1">var</span> currentTweets:ArrayCollection; <span class="linecomment">// &lt;TwitterStatus&gt;</span>

     <span class="category1">private</span> <span class="category1">function</span> setStatus():<span class="category1">void</span> {
           dispatchEvent(<span class="category1">new</span> Event(SET_STATUS));
           statusText.<span class="category2">clear</span>();
      }
]]&gt;
&lt;/mx:Script&gt;</pre>
</code>

</div></div>
<p>The <span class=Code><span style='font-family:Monaco'>MainViewMediator</span></span>
  has an event listener, <span class=Code><span style='font-family:Monaco'>setStatus</span></span>,
that handles that event.</p>



<p><b>twitteria_puremvc/src/com/insideria/twitteria/view/MainViewMediator.mxml
#41-43 (formatted)<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="category1">private</span> <span class="category1">function</span> setStatus(event:Event):<span class="category1">void</span> {
      sendNotification(
           ApplicationFacade.SET_STATUS,
           view.statusText.<span class="category2">text</span>
      );
}</pre>
</code>

</div></div> 


<p>The <span class=Code><span style='font-family:Monaco'>SET_STATUS</span></span>
notification corresponds to the <span class=Code><span style='font-family:Monaco'>SetStatusCommand</span></span>.</p>



<p class=MsoNormal><b>twitteria_puremvc/src/com/insideria/twitteria/controller/SetStatusCommand.as
#10-13 (formatted)<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
override <span class="category1">public</span> <span class="category1">function</span> execute(note:INotification):<span class="category1">void</span> {
      <span class="category1">var</span> statusProxy:StatusProxy =
           facade.retrieveProxy(StatusProxy.NAME) as StatusProxy;
      statusProxy.setStatus(note.getBody() as <span class="category2">String</span>);
}</pre>
</code>

</div></div> 


<p>The <span class=Code><span style='font-family:Monaco'>StatusProxy</span></span>
calls out to the <span class=Code><span style='font-family:Monaco'>TwitterDelegate</span></span>
just like the Cairngorm <span class=Code><span style='font-family:Monaco'>SetStatusCommand</span></span>
used to.</p>



<p class=MsoNormal><b>twitteria_puremvc/src/com/insideria/twitteria/model/StatusProxy.as
#19-22<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="category1">public</span> <span class="category1">function</span> setStatus(statusText:<span class="category2">String</span>):<span class="category1">void</span> {
      <span class="category1">var</span> delegate:TwitterDelegate = <span class="category1">new</span> TwitterDelegate(<span class="category1">this</span>);
      delegate.setStatus(statusText);
}</pre>
</code>

</div></div> 


<p>And when the result comes back, it sends out just the <span
class=Code><span style='font-family:Monaco'>LOAD_TIMELINE</span></span>
notification, which as we saw above, kicks off the timeline load sequence.</p>



<p class=MsoNormal><b>twitteria_puremvc/src/com/insideria/twitteria/model/StatusProxy.as
#24-26<o:p></o:p></b></p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="category1">public</span> <span class="category1">function</span> result(result:<span class="category2">Object</span>):<span class="category1">void</span> {
      sendNotification(ApplicationFacade.LOAD_TIMELINE);
}</pre>
</code>

</div></div> 

<p>Play around with the application, in dummy data mode and out.
Kick it around and see if you can think of anything to add. There are a lot of
moving parts to PureMVC, so think through the flows a bit again, just to make
sure you have an idea of what each piece does.</p>



<p class=Sub-heading>Next Up</p>

<p>Well folks, that's PureMVC. Some key parts again are that nothing
from the framework enters the view components (except once, in the root
application), the model is broken up into many <span class=Code><span
style='font-family:Monaco'>Proxies</span></span>, views that need framework action
are acted upon by <span class=Code><span style='font-family:Monaco'>Mediators</span></span>,
<span class=Code><span style='font-family:Monaco'>Commands</span></span>
generally tell a <span class=Code><span style='font-family:Monaco'>Proxy</span></span>
to do something, and communication between all the parts is done through <span
class=Code><span style='font-family:Monaco'>Notifications</span></span>.</p>



<p>It may strike you that you have to do a lot by hand to get
everything working together with PureMVC. If you'd like your framework to take
a little bit more initiative for you, then you might want to see what the Swiz
way of doing things looks like. That's just what we're going to do next time,
so watch this space! <span style='font-size:10.0pt;font-family:"Times New Roman";
color:windowtext'><o:p></o:p></span></p>

<p style="padding-top: 15px; border-top: 1px solid #ccc;">Read the rest of FrameworkQuest 2008: 

<ul>

<li><a href="http://www.insideria.com/2008/12/frameworkquest-2008-introducti.html" target="_blank">Part 1 - Introduction</a></li>
<li><a href="http://www.insideria.com/2008/12/frameworkquest-2008-part-2-get.html" target="_blank">Part 2 - Get Control with Cairngorm</a></li>
<li>Part 3 - Framework Agnostic Views with PureMVC</li>
<li><a href="http://www.insideria.com/2008/12/frameworkquest-2008-part-4-ioc.html" target="_blank">Part 4 - loC with Swiz</a></li>
<li><a href="http://www.insideria.com/2008/12/frameworkquest-2008-part-5-mat.html" target="_blank">Part 5 - Mate, the Pure MXML Framework</a></li>
<li><a href="http://www.insideria.com/2009/01/frameworkquest-2008-part-6-the.html" target="_blank">Part 6 - The Exciting Conclusion</a></li>
</ul></p>
<p  style="border-bottom: 1px solid #ccc; padding-top: 15px; margin-bottom: 15px;"></p>
]]>
      
    </content>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2008://34.33983-comment:2048993</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2008://34.33983" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html#comment-2048993" />
    <title>Comment from Alistair McLeod on 2008-12-16</title>
    <author>
        <name>Alistair McLeod</name>
        <uri>http://weblogs.macromedia.com/amcleod/</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://weblogs.macromedia.com/amcleod/">
        <![CDATA[<p>Hi Tony,</p>

<p>I'm very much enjoying your series. I have one small comment:</p>

<p><i>..as well as a framework independent view (which is not, strictly speaking, possible with Cairngorm).</i></p>

<p>It is entirely possible to keep framework code out of views in Cairngorm applications, and that's what we definitely advocate. We typically dispatch our CairngormEvent from our presentation model objects, which are quite similar to the PureMVC Proxies. Views should not contain any framework dependent code.</p>

<p>I'd also clarify that Cairngorm does not have singleton models, but does provide a singleton ModelLocator as the root of your domain model (though there's nothing forcing you to use it).  We'd typically not access the ModelLocator directly from the views, and definitely not deep within a component hierarchy.</p>

<p>Looking forward to hearing your thoughts on Swiz.</p>]]>
    </content>
    <published>2008-12-16T15:40:25Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2008://34.33983-comment:2048997</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2008://34.33983" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html#comment-2048997" />
    <title>Comment from Tony Hillerson on 2008-12-16</title>
    <author>
        <name>Tony Hillerson</name>
        <uri>http://thillerson.blogspot.com</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://thillerson.blogspot.com">
        <![CDATA[<p>@Alistair - Again it seems like my style of working with Cairngorm is outdated. All the examples I learned from 3 or so years ago looked more like my code here, so it seems like I haven't kept up to speed with new thought in the framework. Can you give any other resources (besides the ones you already have, e.g. <a href="http://weblogs.macromedia.com/amcleod/archives/2008/12/max_milan_-_fle.html)">http://weblogs.macromedia.com/amcleod/archives/2008/12/max_milan_-_fle.html)</a> out there on the web to the readers here showing a better way to learn about Cairngorm?</p>]]>
    </content>
    <published>2008-12-16T16:06:56Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2008://34.33983-comment:2049032</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2008://34.33983" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html#comment-2049032" />
    <title>Comment from kevin on 2008-12-16</title>
    <author>
        <name>kevin</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>Great series Tony.  As a relatively new user to Flex and Cairngorm it's very useful to have a basic shootout of the major frameworks available and I think you're getting the job done.</p>

<p>Alistair, it's also interesting to hear your thoughts on Cairngorm and it's uses. Though, one major struggle I (and it seems many others) have had to date is finding the best ways to use Cairngorm with practical examples.</p>

<p>I read through the presentation you posted last week which looks great but is less effective without you speaking along with it and seeing your demos :)</p>

<p>Any chance you could consider giving this presentation on AdobeTV?  I feel there's a lack of content there for people who are interested and trying to build larger applications 'the right way'.</p>

<p>Some aspects I'm particularly interested in are examples of best use of the Presentation Model, and the best way to notify Views or other Components when a service returns a Result/Fault (so as to trigger more events as an example).</p>

<p>Cheers</p>]]>
    </content>
    <published>2008-12-17T00:36:47Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2008://34.33983-comment:2049043</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2008://34.33983" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html#comment-2049043" />
    <title>Comment from Greg Jastrab on 2008-12-16</title>
    <author>
        <name>Greg Jastrab</name>
        <uri>http://blog.smartlogicsolutions.com</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://blog.smartlogicsolutions.com">
        <![CDATA[<p>Great series Tony, there have been so many <i>Which Framework is Best</i> conversations/flamewars on various forums/blogs, so this is will be a valuable resource.</p>

<p>A few comments:<br />
<ul><br />
 <li>Small typo it seems: you reference your LoginViewMediator class with an MXML extension instead of AS</li><br />
 <li>In your <b>MainViewMediator.mxml #33-39</b> snippet you have the Mediator getting a reference to the Proxy.  This violates the MVC principle and MVC purists will say it is not condoned.  Solution in my next points...</li><br />
 <li>While PureMVC doesn't offer a way to take advantage of binding in your views with curly braces, there's nothing stopping you from binding via ActionScript.  I generally have a command that retrieves references to a corresponding Proxy and Mediator, and passes an ArrayCollection from Proxy into a method on the Mediator.  In that method I will bind the ArrayCollection to the dataProvider of some List-based component using BindingUtils.bindProperty.  Now any modifications to the ArrayCollection in commands will get pushed down into the views via binding, and the MVC best practice is kept intact.</li><br />
 <li>Instead of making my Proxy an IResponder, I'll make my Command an IResponder, which addresses your concern in the paragraph before <b>TimelineProxy.as #27-32</b>.  So if this application needed to retrieve a list of Friends to push into a proxy, I'd have a GetFriendsCommand which implemented IResponder, and in the result method I'd add the parsed Friend objects into an ArrayCollection on a Proxy.</li><br />
</ul></p>

<p>And finally, a shameless, but related plug.  I released a generator for PureMVC a little over a week ago.  You can find a blog post about it at <a href="http://bit.ly/puremvc-gen">http://bit.ly/puremvc-gen</a>  <b>NOTE:</b> There is a bug right now that is causing some problems in Windows, but I hope to have it fixed this week.</p>]]>
    </content>
    <published>2008-12-17T05:06:49Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2008://34.33983-comment:2049062</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2008://34.33983" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html#comment-2049062" />
    <title>Comment from Greg Jastrab on 2008-12-17</title>
    <author>
        <name>Greg Jastrab</name>
        <uri>http://blog.smartlogicsolutions.com</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://blog.smartlogicsolutions.com">
        <![CDATA[<p>Apparently making the Command an IResponder isn't best practice, but I'm not entirely satisfied with throwing it on the Proxy quite yet...</p>]]>
    </content>
    <published>2008-12-17T16:08:11Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2008://34.33983-comment:2049063</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2008://34.33983" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html#comment-2049063" />
    <title>Comment from shaun on 2008-12-17</title>
    <author>
        <name>shaun</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>@Greg Jastrab: Indeed. Commands in PureMVC are stateless, they should execute and die immediately. See: <a href="http://puremvc.org/content/view/80/188/">http://puremvc.org/content/view/80/188/</a></p>

<p>Also, a Command that does nothing more than retrieve a Proxy and call a method on it, is not really recommended either. See: <a href="http://puremvc.org/content/view/76/188/">http://puremvc.org/content/view/76/188/</a></p>]]>
    </content>
    <published>2008-12-17T16:20:03Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2008://34.33983-comment:2049065</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2008://34.33983" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html#comment-2049065" />
    <title>Comment from Tony Hillerson on 2008-12-17</title>
    <author>
        <name>Tony Hillerson</name>
        <uri>http://thillerson.blogspot.com</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://thillerson.blogspot.com">
        <![CDATA[<p>@Greg - cool.. thanks for the link, and thanks for the correction. Re: binding, If you're using Actionscript binding you may as well use curly brace syntax, though, because the point of not using binding is to not have the Flex dependency. Again, I think that's a small win at best.</p>

<p>Thanks to everyone providing corrections to my code or my method of using these frameworks if I'm off a bit - again, I'm mostly used to using Cairngorm, so I'm not trying to show my expertise in these frameworks, just show how each one of these compares to eachother on a small project when you're coming up to speed with them. Then again, Alistair schooled me on how I was using Cairngorm, so maybe I know nothing! Nothing at all!</p>

<p>Anyhow, I'm glad the series seems to be helpful all the same.</p>]]>
    </content>
    <published>2008-12-17T16:56:38Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2008://34.33983-comment:2049142</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2008://34.33983" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html#comment-2049142" />
    <title>Comment from Alistair McLeod on 2008-12-18</title>
    <author>
        <name>Alistair McLeod</name>
        <uri>http://weblogs.macromedia.com/amcleod/</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://weblogs.macromedia.com/amcleod/">
        <![CDATA[<p>@Tony, good question, and one where i don't have an immediate answer I'm afraid. </p>

<p>Since donating Cairngorm to the community, real world projects have taken over the time of our consultants, so getting the time to provide the documentation and sample we'd want to just hasn't materialized.</p>

<p>However, some of our team here are starting to get some stuff together, so hopefully we'll be able to start providing more in the new year.</p>

<p>In particular, one of my colleagues, Tom Sugden, is the co-author of a new book coming out next year, where a lot of the latest best practices (including the refactored Cairngorm Store) are described. However, we hope to get more out there before that is published.<br />
</p>]]>
    </content>
    <published>2008-12-18T15:46:59Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2008://34.33983-comment:2049887</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2008://34.33983" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html#comment-2049887" />
    <title>Comment from Ansury on 2008-12-30</title>
    <author>
        <name>Ansury</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>Alistair,</p>

<p>With all due respect, if there's no examples or documentation available showing a better (best practice) way of using Cairngorm, then whatever the common practice out there right now is still "the standard way" to use it.  I understand your comments and points about better practices possible (or even established within certain circles), but these points aren't relevant when Cairngorm is compared to alternatives that do provide "best practice" samples and documentation.  </p>

<p>i.e. Given two table saws, one with diagrams and an instruction manual, the other without (or with outdated/incorrect instructions)... I'll take the one with documentation and keep my fingers. ^_^</p>]]>
    </content>
    <published>2008-12-30T19:51:54Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2008://34.33983-comment:2050979</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2008://34.33983" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html#comment-2050979" />
    <title>Comment from Yann on 2009-01-14</title>
    <author>
        <name>Yann</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>Just to inform community that a new tool has been released by Kap IT Lab: consoles for pureMVC and cairngorm. It becomes really essential as soon as you start to use it.</p>

<p>You can see them here:<br />
<a href="http://lab.kapit.fr/display/puremvcconsole/PureMVC+Console">http://lab.kapit.fr/display/puremvcconsole/PureMVC+Console</a><br />
and here:<br />
<a href="http://lab.kapit.fr/display/cairngormconsole/Cairngorm+Console">http://lab.kapit.fr/display/cairngormconsole/Cairngorm+Console</a><br />
</p>]]>
    </content>
    <published>2009-01-14T16:56:42Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2008://34.33983-comment:2050980</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2008://34.33983" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html#comment-2050980" />
    <title>Comment from Yann on 2009-01-14</title>
    <author>
        <name>Yann</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>Just to inform community that two new tools have been released by Kap IT Lab: consoles for pureMVC and cairngorm. It becomes really essential as soon as you start to use it.</p>

<p>You can see them here:<br />
<a href="http://lab.kapit.fr/display/puremvcconsole/PureMVC+Console">http://lab.kapit.fr/display/puremvcconsole/PureMVC+Console</a><br />
and here:<br />
<a href="http://lab.kapit.fr/display/cairngormconsole/Cairngorm+Console">http://lab.kapit.fr/display/cairngormconsole/Cairngorm+Console</a><br />
</p>]]>
    </content>
    <published>2009-01-14T17:06:51Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2008://34.33983-comment:2059601</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2008://34.33983" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html#comment-2059601" />
    <title>Comment from Fletch on 2009-05-14</title>
    <author>
        <name>Fletch</name>
        <uri>http://www.saltwebsites.com/</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://www.saltwebsites.com/">
        <![CDATA[<p>@Alistair: I agree with Ansury.</p>

<p>I do definitely appreciate your chipping in on the discussion, that's cool. But essentially Ansury is right. What you're saying is that if we want to learn Cairgnorm we have two choices:<br />
1. Use it badly / in a way that Adobe discourages, but that is easy to do and all over the internet (possibly in some [outdated] official doco too?)<br />
2. Spend a good deal of time trying to find the gems of info that explain how to use it well and then hoping that we have acheived this correctly.</p>

<p>If more doco comes out of Adobe which clearly establishes best practices that would be great.</p>]]>
    </content>
    <published>2009-05-14T07:58:08Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2008://34.33983-comment:2068291</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2008://34.33983" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html#comment-2068291" />
    <title>Comment from Darren on 2009-07-14</title>
    <author>
        <name>Darren</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>@Fletch and @Ansury,</p>

<p>Well, I agree with Alistair and disagree with both of you. What you are doing is criticising the documentation and not the framework as Alistair is quite right to point out. Anyone who is familiar with the benefits of DI will naturally use this pattern to keep their dependencies out of their view components regardless of which framework is utilised. They won't need to be told how to do this. So the critcism should be 'good framework, poor documentation' rather than 'flawed framework'. I would say that most people who own a Callaway Big Bertha golf driver can't use it properly - is this an inherent problem with the golf driver?</p>]]>
    </content>
    <published>2009-07-14T23:36:21Z</published>
  </entry>

</feed
