Futurescale, Inc. PureMVC Home

The PureMVC Framework Code at the Speed of Thought


Over 10 years of community discussion and knowledge are maintained here as a read-only archive.

New discussions should be taken up in issues on the appropriate projects at https://github.com/PureMVC

Pages: [1]
Print
Author Topic: Help with Commands  (Read 23381 times)
JesterXL
Newbie
*
Posts: 2


View Profile Email
« on: February 07, 2009, 08:13:50 »

PureMVC n00b here.  Complex question, so short version and long version.

Short Version: What are commands supposed to do in PureMVC?  What do your commands typically do?

-----------------

Long Version

First, some context on why I ask...

I consider myself an expert in Cairngorm.  Back in 2006, Thomas Burleson from Universal Mind and I were arguing daily about the best way to allow View's to know what was going on in the Controller layer of Cairngorm long before the UM Cairngorm extensions were released.  If you looked at most of the examples of the time, they assumed all Commands really did is set data on the ModelLocator, or performed other application logic (or even business logic depending on how you define it).  As your app would increase in scope, a simple 1 line of setting the ModelLocator (singleton from which you bind View controls to) would no longer be the case.  Most applications I worked on, both those that had a heavy back-end usage, and even those that only used 1 or two services to save & update data still would have pretty complex commands.  To me, it clearly seemed like Cairngorm was doing its job.

However, even simple things like errors couldn't be easily handled by View's.  You'd see horrible examples of Alert dialogues being thrown in Business Delegate's or Commands.  There were decent attempts at keeping the View references clean, sometimes using interfaces, etc... but at the end of the day, it'd be tightly coupled to the View, or Views.

Then, Joe Berkovitz released MVCS, although he didn't mean for his 9 page DevNet article to imply "MVCS was a true framework".  Inevitably, it was.  It showed people that you can implement MVC almost to the letter, and it still works great.  One side effect, however, was if you look at Joe's Controllers, they clearly show how far abstracted away Cairngorm's Commands are from the View's.  MVCS controllers can dispatch events, thus giving you very intricate information of what is happening to the state if your app, a service... anything you deem worthy of dispatching an event for, and a View can optionally listen in, and react accordingly.  This becomes very important in regards to state.  If you Mediator code (usually a higher level View in Cairngorm) managing application state, using those events makes it really easy to correctly react.  In Cairngorm, however, there wasn't a way to do that.  So, we created callbacks so Commands could dispatch their state.  It was an extension on top of Cairngorm, and did require some learning time for those already familiar with Cairngorm, but at least it stayed out of your way, tucked underneath inheritance.  It's very similar to the UM Cairngorm Extensions of today.

Now, you could build View's with confidence they'd know if a login actually worked our not without binding to a bunch of singleton state variables.  Sometimes really complex things would happen, and binding to a variable wasn't enough; the context you needed could be contained in an Event.

So, Commands could call web services with context, update your data model, and adjust application state.  It worked great, although, the up-time to get started gave rise to code generators.  Once your project was underway, you really didn't need them anymore.

Enter PureMVC

When PureMVC came out, I saw some things I loved, and some things I hated.  After a harsh blog entry, I learned a lot, but still didn't know enough.  Putting my money where my mouth is, I used it on 2 client projects, one Flash for Hyundai's website, and one for a huge Flex product.  After both projects, I get everything about PureMVC... except Commands.

Coming from Cairngorm, Commands were the lifeblood of your application.  The Business Delegates got your data, you stored it a ModelLocator, a Factory potentially parsed your data... but nothing complicated at all.  All the hardcore code was either in your higher level Views, or Commands.  The Commands would ask for data, get it, and do stuff with it.

That doesn't seem to happen in PureMVC.  My Proxies basically get the data, modify it, and send notifications on if something important changes.  My Mediators either ferry requests so my Proxies can get updated, and in turn they funnel data back.  The system works as advertised... except Commands.  They basically don't do anything important.  The documentation talks about re-use, but since they themselves cannot listen for notifications, all my Commands end up doing is making sure a Proxy is in fact registered, a Mediator is in fact registered, and calling a method on a Proxy that the Mediator was more than capable of doing.  I've talked to another guy on Twitter who already had this issue, and just has his Mediators call the Proxies directly.  I'm liable to agree.  Without Commands having the ability to recognize HOW the data has changed, they really can't do all of the application logic... just half, and the half of initiating the operation.  The Proxies end up managing both the data model as well as that logic.  That's ok with me, but I remember the documentation on best practices clearly mentioning that you should really keep your Mediator's simple; listen to View events, and update them with notifications sent from Proxies.

In short, to me Commands seem useless beyond the required PureMVC plumbing of registering Mediators and Proxies... especially when you come from using Cairngorm.

Am I missing something?


« Last Edit: February 07, 2009, 08:24:03 by JesterXL » Logged
Lazarus404
Newbie
*
Posts: 4


View Profile Email
« Reply #1 on: February 08, 2009, 02:26:11 »

You're missing the point! Mediators should never contain business logic, and neither should proxies. That's you commands job. Mediators simply provide a PureMVC aware layer over your views. They should merely listen for notifications and update the view when requested... no more!

Lee McColl Sylvester
Logged
shauno


Email
« Reply #2 on: February 08, 2009, 05:16:34 »

I feel the question deserves more discussion. Looking at this FAQ http://puremvc.org/content/view/76/188/ I feel it's safe to say that Mediators can call methods on Proxies directly. Doing this has left me with very few Commands in my applications. Those Commands generally contain a bit of business logic to determine how to handle some commonly requested action - logic that I wouldn't want to put in my Mediators.
Logged
Peter
Full Member
***
Posts: 26


View Profile Email
« Reply #3 on: February 08, 2009, 07:17:05 »

If I look at the practical side and leave the theory to Cliff, I rather like this 'freedom'. I do a lot of short term 'marketing action' related sites (flash) where it is about speed of development and less about decoupling, life span of the project and maintenance. If a View calls the Model directly... well, so be it. Anything to get the job done... within the budget.

If however it's about a project with a longer life span, I won't allow that. A View - Mediator and its ViewComponent - should be taken out of the project easily and be replaced with another View. Here the View may only communicate with the core using notifications and commands will decide what to do next.
Also, when working with a team of developers, I can have developers working on Views only while others only work on the core.

I'm sure you will want to see more theory in the answers so let's wait for Cliff to answer.
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #4 on: February 08, 2009, 07:17:55 »

@JesterXL,

A quick read of the best practices doc will tell you that Commands are basically for coordinating complex activities like startup.

To go back in the day, in late 2004 I was picking up Cairngorm since it was the closest thing to the Java patterns I was used to, and began doing enterprise level stuff with it almost immediately for Adobe and UniversalMind. I didn't like the ModelLocator at all because it had no structure and would become bloated. So I wrote a package called Bach for model services. Some of those concepts made it into PureMVC in the form of a Model that Proxies are registered with as opposed to static ModelLocator props.

Several complete Cairngorm package naming schemes later, at MAX 2005 Anahiem,, I caught Joe's MVCS talk in and was intrigued by the crazy idea that there just might be another way to do this stuff. I got home and checked out his demo, and saw that that the tradeoff would be that I'd end up with a really fat controller. 

By 2006, I was over it. Writing gazillions of commands was getting to me my apps we're mostly composed of commands.

So I decided to rethink things. Bach showed up in a far more reasonable way as Proxy/Model. I liked the old Cairngorm ViewHelper / ViewLocator, classes, but didn't like doing code-behind with them ala .NET. We could ASDoc our MXML by then, so there was no need to pull a view's unique behavior out into another class, but a nanny-like class could spoonfeed it data and listen to its events so as to act on its behalf. GoF called this a Mediator. And Commands still seemed like a reasonable idea, even tough I didn't want to write so many of them, so I kept them for the Controller tier.

And finally, from my Java days, I remembered how my old pal the Facade could act as the front end to a complex system, giving you one place to do all the things you could do by importing the actors of the system and interacting with them directly. This seemed like a good way to 'roll up' the system into a single actor to work with.

Well in the final analysis, it turns out that the Mediator does a perfectly fine job of separating the View from the Model. Even though it is an actor of the 'View' tier, it dosent really introduce any  undesirable view/model dependency for the Mediator to retrieve a Proxy via the Facade and give it some data on behalf of its View component. Thus, the need for Commands has been (mercifully) minimized.

Yes, if you look at the classic MVC triangle you'll be convinced that this work should always be done by a cCommand or other official denizen of the controller tier, but MVC is a MetaPattern; it specifies no actors or particular implementation. In reality, the Mediator regularly performs the line or two of code that you'd otherwise write a command for. If you have that same few lines being performed by more than one mediator (or you need to do transformation of data befor poking it into a Proxy, you should consider refactoring it to a Command, let DRY be your guide there.

Doing my research of the prior art, I found tons of MVC implementations out there, all wildly different. Calling this implementation 'PureMVC' was my little jest as you can tell from my first article posted.

-=Cliff>
Logged
newtriks
Courseware Beta
Full Member
***
Posts: 23


 - newtriks
View Profile WWW Email
« Reply #5 on: February 08, 2009, 07:29:10 »

Hey Jesse,

I have heard this asked a lot of times and as a foreword I would like to say that this is my opinion and I am not the best at debating points to the finest detail, this is just how I interpret the whole command issue.  Also you have way way more experience with many different frameworks compared to myself so logic may differ?

I think the beauty of PureMVC is the way you can essentially utilise it to 'what suits you' to a degree, over time I have pushed out a lot of PureMVC projects and still adapt and change certain styles and techniques with certain logic, this I don't think is necessarily a negative and see most changes I make a positive progression.

In the beginning I took much the same principle as you mention below, using commands to essentially prep the model and view, check for mediator registration etc.  I am an advocate for referencing Proxies in the Mediators if it is to simply get some data, a reach in and grab situation.

Then Stef (www.flashcomguru.com) and I had some chats about this whole scenario and each time we spoke I found I was tending to handle more aspects within a Command and was removing certain logic from the Mediators and Proxies.  This then started solving a few issues I was having, primarily bloated Mediators and referencing the odd proxy within another proxy  :o

With my latest application it is one of the biggest I have built so far and I will use some of this project as examples into my logic.  There are lots of collation of data from the UI and processing of data received from remoting calls.   

Mediators I try to keep them simple, grab data from the views, dispatch it and stuff it right back in again, I also handle form/view resets, determine whether certain components within the view are selected/enabled and dispatch notifications to change view state etc.

Due to numerous Proxies for various remoting calls, I am receiving back data which needs to be amalgamated, filtered and ultimately stored.  This is where I have now really shifted logic to Commands.  Heres a really rough example. 

A booking engine has been sent a request for journeys and fares to populate a grid dependent on user defined journey times.  I would have 2 proxies. 

-The first has all the fares applicable to the search request times, each fare has a code used as a reference to retrieve further current info on that specific fare. 
-The second proxy loads the current fare information and using getter methods passes back the extra fare information dependent on the fare code. 

So I now need to filter these fares on certain current fare data and instead of having all this logic in one proxy (don't forget its using logic from 2 proxies) I use a Command.  The first proxy receives the fares, sends a notification, a filter command which references both Proxies then filters all the fares and returns the new array collection into the first proxy for storage.

Here's another example.  I have various TitleWindow popups which are presented in different formats i.e. Image/Text, Forms etc.  I have a PopManager utility which accepts the popup params including a reference to the Facade.  Anywhere in the application I can now call and open a popup i.e.
:
sendNotification( ApplicationFacade.HANDLE_POP, pObj, ResourceConstants.OPEN_POP ); and a HandlePopCommand will handle the logic of opening the correct style popup window (also closing it).  To do that I simply use switch statements on the body and type of the notification and the command then checks to see if the pops mediator is registered and then opens (creates) or closes the popup accordingly.

Here's one more example.  I have multiple view components which need to have all their data collated into one value object and then sent to a proxy for a remote request.  A command has references to the specific mediators and calls the mediators getter method bringing in all the view data, populating the value object and filtering the data according to the data it is receiving.  This prevents the Model receiving the data via multiple notifications and ensure an order to how the value object is populated.

On a final note, I do have a lot of commands on the slimmer bordering anorexic side which simply call different methods in a proxy dependent on the notification type i.e. if note.type() == reset a password, or reset a username etc.  I then go though the various proxy method calling from there, this could be done in the Proxy, but I am now more comfortable with the Commands handling this logic and cutting back on the proxy code.  Following the theme of logins, there maybe different proxies handling different accounts so one command to handle this logic and call the appropriate proxy is ideal for me.

Ok, that's my thoughts on this, hope that helps in some way?

Cheers,

Simon

[ Website ] www.newtriks.com
[ Blog ] www.nutrixinteractive.com/blog/
Logged
JesterXL
Newbie
*
Posts: 2


View Profile Email
« Reply #6 on: February 08, 2009, 08:41:25 »

Thanks everyone!  Cliff & Shauno really hit the nail on the head of what I was getting at.  My Cairngorm apps did end up having a lot of Command classes.  Additionally, I've had the same problem using MVCS.  I still use it today with smaller apps, but for the bigger ones, even multiple Controller classes gets challenging to manage, so I stick with another framework.  Additionally, my Commands really do what you said Cliff... they just initialize things.

What I was trying to avoid was having 2 Commands for what I usually used 1 for in Cairngorm.  I'd need to ask the server to do something, and depending on the result, do something else.  Since Commands cannot receive Notifications, I'd end up creating 2 Commands; 1 to make the request, and another to respond to it. 

Now, however, it sounds like my use of Mediator's & Proxies is correct and I shouldn't worry about not having as many Commands.
« Last Edit: February 08, 2009, 08:49:43 by JesterXL » Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #7 on: February 08, 2009, 09:11:38 »

Yes, that's it.

I think the challenge for those with experience in other frameworks is to leave the baggage at the door and try to see the spirit of the new one. It sounds like you naturally settled on the right balance for the basic actors.

And, of course what is there are just the basics. Enough to help you achieve MVC separation and that's it. This will inevitably leave you thinking, it should do this or it needs that. And that's where the utilities come in. Ala carte extensions for all sorts of things. So in that basin of stability your app eventually reached,if you think that its difficult to, for instance, represent application state (as opposed to view state), go check out the StateMachine utility. You may find that beyond the standard startup procedure, that your apps take on a whole new 'feel' inside as everything is organised around states and transitions.

-=Cliff>
Logged
Lazarus404
Newbie
*
Posts: 4


View Profile Email
« Reply #8 on: February 08, 2009, 04:27:34 »

I think, most often, your code dictates to you what should exist in a Command and what should exist in a Mediator. I for one have a set of rules :-
  • My Mediators will only read from proxies, not write, and certainly not call methods which will update the proxy data in any way
  • I look for reusability where possible. If a Mediator performs a non-display related action that other areas of your app will need (or may in future) react to, then that code should exist in a Command
  • PureMVC is an MVC framework, so MVC rules apply - and for a good reason

As you've already read, there are many ways you can use PureMVC, but reusability, readability and maintainability should surely always stand paramount to your decisions, else why not code from the hip?

Also, something else I was thinking, and which may help with your many Commands issue; I've been recently building a PureMVC extension for haXe (primarily for the PHP target), which I borrowed from Zend.  It's often conceivable that a Command may need to facilitate multiple actions. For example, a Command for building logic for a form may need to build the form itself, or the resulting thank you page (or somesuch). Having multiple commands isn't always the way. The best way I've found to do this is to introduce 'actions'. Essentially, some Commands would extend a ComplexCommand type, whereby the execute method parses data in the INotification parameter and based on its content, make a call to an action method also contained in the sub-Command class. This was useful for my PHP work as I'd provide a single Command for each page, but provide an action for the pages different states. Doing this also meant I didn't have to worry about my framework registering every single Command for every single page request.

It's food for thought "sucker" ;-)

Lee
 

Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #9 on: February 08, 2009, 06:58:04 »

ComplexCommands? Do they differ from MacroCommands? Or IAsyncCommands ?

Yes certainly there are uses for commands. For instance a keystroke or a menu item in one part of the view or a button elsewhere might all trigger the same logic. Then you get reuse if you push the common logic into a command. The is what I meant by letting DRY (don't repeat yorself) be your guide. But as far as a mediator updating a proxy with data from its view, if no othe part of the system needs to perform that update, then in what way does having the mediator update the proxy hamper reuse?

While seeking reuse, you are also battling complexity in an app (or seeking simplicity, if you're a 'glass is half full sort of person).

Governed by Einstien's maxim: 'as simple as possible, but no simpler', until I need that reuse, I'm happy to have one less class. As soon as I find that I want to do that same simple update from elsewhere, I refactor the update into a command.

There is a good reason to code ths way and not  according to unwavering textbook ideals: Performance.
Users want things to happen fast. That means we always want the shortest number of operations for any given task.

However we still want reusability, maintainability and good separation of concerns. Its an equation with a lot of variables but don't forget that we are probably writing this for a living, breathing and most likely impatient user (unless this is a headless processing app of some sort).

To test this out, open one of your apps that has the mediator send a note that triggers a command that retrieves and updates a proxy. Set a breakpoint in the mediator just before sending the note.

Debug the app and trigger the mediator's method that sends the note.

Step into the code line by line and count the number of steps until the proxy's update method is called.

Now, comment out the call to send the note in the mediator and instead, simply retrieve the proxy and call the update method.

Debug again and count the steps. Its a way shorter path. But that's not all.

Big performance gains are to be had if that call happens more than once and particularly if it happens frequently and in volume (such as in a game).

If you examine most of the PureMVC demos you see that mediators not only call proxies freely, but they often retrieve and cache a reference to their frequently accessed proxies in their onRegister methods.

So back to your mediator, if you will be interacting with this proxy frequently, retrieve the proxy and store it in a typed local property.

Now your mtehod that was sending a note, but we commented that out and are retrieving the proxy and calling its update method. Now you can drop the retrieveProxy call and simply call the update on the local reference to the proxy.

Debug that and count the steps. Waaaay shorter.

Now imagine a complex particle system in the view component is triggering this update a thousand times a second.

So multiply the number of steps it took to have the command do it by a thousand.

Now multiply the number of steps it took to do the update on a local reference to the proxy by a thousand.

The first number is going to be staggeringly larger than the second, guaranteed. 

My first programming job was in machine language with 2.5k of ram and a 1mhz processor. Like growing up poor, you 'learn the value of a cpu cycle'.

But the enterprise requires patterns that other developers can understand; all those -ilities you mentioned are necessary, too.

Balance.
-=Cliff>
Logged
Lazarus404
Newbie
*
Posts: 4


View Profile Email
« Reply #10 on: February 09, 2009, 11:59:56 »

Yes, I agree there are times when it's a requirement. In a recent game, I even went so far as to pass a proxy reference to a view component so that it would have the ability to bind to a speed value, and it was my only choice at the time. However, I think those times should be minimized to help maintain clarity. It can become a habit even when not needed
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #11 on: February 10, 2009, 07:33:53 »

I'm having a hard time imagining the scenario where binding to a proxy from a view component was the only option. The entire goal of the framework is that separation.

-=Cliff> 
Logged
Lazarus404
Newbie
*
Posts: 4


View Profile Email
« Reply #12 on: February 11, 2009, 04:46:53 »

It was the only option because I didn't anticipate the amount of speed drop. I already had a series of AS classes that I didn't want to rewrite into a mediator, and a lot of the code performed various tweening algorythms. Binding the view code to the proxy was the only way I could get the code to run smoothly, especially as the proxy was updated quite regularly by the framework. It did save me about 3 hours of work, and wouldn't have been reused at any time.
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #13 on: February 11, 2009, 06:22:08 »

>>I already had a bunch of AS classes I didn't want to rewrite into a mediator

The mediator shouldn't do anything more than participate in the "fireman's carry" of the data into the view. The notification process is rarely slower than binding. I still don't buy it. It might've saved time in coding, but I don't think it would have slowed anything down had you actually implemented the mediator. Particularly if you followed the ordinary pattern of having the mediator cache references to its frequently used Proxies, thereby eliminating the Proxy retrieval each time the mediator responds to an update note from the proxy.

-=Cliff>
Logged
Pages: [1]
Print