Swiz tidbit: RemoteMethodMediator

I'm on vacation for a few days, and Ava and Dale are taking a nap...so I went for a walk and thought up a component for playing around with in Swiz. Instead of using Swiz.executeServiceCall() to invoke methods on RemoteObjects, I cooked up a "RemoteMethodMediator." Its source code is attached.

I'll post a video about it next week, but the gist is that I love messaging, and I only want to work in events (vs. callback functions that usually just dispatch events). Instead of assigning result / fault callbacks, RemoteMethodMediator lets you tell Swiz "Hey, whenever you get a result from Service.doSomething(), dispatch the "SomethingController.GOT_SOMETHING" event and place "resultEvent.result" in "event.something." Then, any methods with GOT_SOMETHING mediated to them are called and simply passed the value.

Whew, yeah, that's going to need a video on Monday. For the curious, Here's the example of how it works when applied to the stock list example:

In Beans.mxml:

<mx:RemoteObject
    id="stockPriceService"
    destination="ColdFusion"
    source="ExampleService"
/>


<rpc:RemoteMethodMediator
    remoteObject="{ stockPriceService }" methodName="getStockPrices"
    resultProperty="stockPrices" resultEvent="{ StockController.STOCK_REQUEST_COMPLETE }"
    faultEvent="{ StockController.SERVER_REQUEST_FAILED }"
/>

In StockController.as:

[Mediate( event="userWantsStockPrices" )]
public function loadStockPrices() : void
{
    Swiz.dispatch( StockController.STOCK_REQUEST_STARTED )
    
    stockService.getStockPrices()
}

[Mediate( event="stockRequestComplete", properties="stockPrices" )]
public function stockPricesReceived( prices : Array ) : void
{
    stockQuotes.source = prices
}


[Mediate( event="serverRequestFailed" )]
public function serverError() : void
{
    Alert.show( "Oops! Server died!" );
}

Swiz in 20 minutes video - bye-bye, boilerplate!

I was asked today at work if I could do a quick walkthrough of the Swiz framework via Connect. In the end, we decided that I should recorded a screencast that anyone can view, available below. Swiz is a darn-near magical framework for Flex that gives you the benefits of dependency injection, event-driven development, and separation of concerns without the boilerplate or heavy reliance on base class functionality present in other frameworks. Going further, it's darn simple to learn: 20 minutes of example and a quick skim of the feature list should be all you need to begin being effective. If there's two things to get from the following video, they are:
  1. Swiz manages your dependencies in the POJO-vein of Spring/ColdSpring
  2. Swiz lets you write plain, non-framework AS3 code that's wired together with terse metadata
Enjoy!

Swiz in 15 minutes from Joe Rinehart on Vimeo.

Comparing Swiz and PureMVC

I'll soon be a developer on a good-sized PureMVC project, so I thought it'd be good to...well...learn PureMVC.  I've diddled with its sample code and read its documentation, but largely avoided it in the past.  My brain works more in the lighter-weight Spring/POJO mindset of Swiz, so that's largely where I've stayed.  To get myself up to speed, I decided I'd port the EmployeeAdmin example PureMVC app to Swiz.  This'll give me a bit of a Rosetta stone for figuring out what goes where, and it looks to be one of the more discussed examples on the PureMVC forums.

Conclusion

Conclusion first?  Well, I didn't want you to have to read all of this if you didn't want to.

After factoring the same model code between a few different architectures, I don't really have a "Yes, use framework X!" opinion.  Swiz is more "my style," but it's like a chainsaw:  very effective at both getting the job done and causing a bloody mess.  PureMVC is wordier and more prescriptive, but this rigidity could help larger teams of more varied experience.  I don't like the amount of boilerplate and interfaces-for-interfaces-sake in PureMVC, but it's certainly an appropriate tradeoff for giving a development team a common language.

In my typical style of overreaching metaphors that'd make Dr. Phil proud, it's power tools vs. hand tools.  I can build the same thing with the same fundamental architecture with either, but a lot of the end choice has to do with workers and materials.

Basic Architecture


Swiz and PureMVC both provide Model View Controller implementations.  Swiz encourages you to write vanilla AS3 classes sprinkled with Swiz-specific annotations, using a dependency injection container (similar to Spring) to resolve dependencies.  PureMVC encourages implementation of its interfaces (except for on the view tier), using a central concrete Facade with which dependencies are registered.

Event Mechanisms

Both rely on application-level (non-UI hierarchy) events for communications between model, view, and controller, with PureMVC implementing its own Observer implementation and Swiz relying on native Flash events.  The idea of notifications (events outside of the UI hierarchy) is the foundation of both frameworks.

Opinion:  If I were to be locked in a dungeon to write software for the rest of my life and could take one design pattern with me, it'd be the Observer pattern, so any framework that makes multi-observer notifications a core concept is peachy with me.  That does eliminate Cairngorm, which I don't consider a great loss.

View and Controller Communications Differences

Compared to Swiz, PureMVC architectural style recommends a higher level of decoupling between controllers and views via Mediators, which act as a traditional view controller in collaboration with a view.  In PureMVC, a Mediator knows about a UI component, manipulating its state and listening for events and re-dispatching application-level notifications as needed.  It's important to note that this collaboration is one way:  the Mediator knows about the view, but not vice-versa.  The UI component itself knows nothing of PureMVC.  The direction of coupling is from the Controller ("Mediator") to the View.

Nothing prevents identical architecture in Swiz, but Swiz developers typically couple views directly to controllers, a more coupled but traditional MVC decision.  In Swiz, a view generally dispatches application-level notifications directly.  Instead of a mediator maintaining a reference to a view, a Swiz view generally maintains a reference to a controller, using its exposed properties to maintain its data via bindings.   In Swiz, the Controller isn't highly coupled to its View.  Instead, the direction of coupling is from the View to the Controller.

Opinion:  In the Web world, I've tended towards frameworks that use a Controller tier that is less coupled to the view (Model-Glue, Mach-ii, Fusebox) instead of vice-versa (Coldbox, anything ending in "rails").  This lets me have more re-usable controller logic rather than more portable view code, so I prefer the Swiz approach.  It lets me work the way I want, but doesn't block me from using PureMVC-style architecture if so desired.  I can't recall ever moving views between frameworks anytime other than porting examples.

Command Implementations

Many RIA developers use Command pattern implementations to define complex business logic or state changes.  A command, simply put, is a stateless script.  PureMVC provides for this by allowing a developer to map Commands to notification names.  When the notification is dispatched, all mapped commands are executed.  

Swiz does not provide a specific way to write concrete Command implementations, instead favoring mapping of Controller methods to notification names.

Opinion:  Not much of one, because I don't like most uses of the Command pattern.  I understand the temptation of commands (one file of source code can contain all logic for a use case), but I think that's also their flaw.  I think they're great if they're kept small, but that they usually wind up being a library of scripts that contain most of the application's logic -  all too often domain logic that belongs in the model to begin with.  

Model Differences

One of the first problems in RIAs addressed by frameworks is that of model location.  As soon as you've written a RIA that's more than a few components large, you've probably realized that passing all needed data down the UI hierarchy tree through tag attributes is a fairly lousy and brittle way to maintain state.  Both PureMVC and Swiz solve this more elegantly than the classic ModelLocator idea.

In PureMVC, a Proxy class provides methods by which Controller-level classes (Mediators and Commands) may access and manipulate model state.  These proxies generally maintain the reference to the model, and the proxy is interrogated for state when needed.  For examples, a Proxy holding Users may have a "proxy.users" property that is an ArrayCollection.  A mediator may then update the list of users in a view named "userList" via "userList.users = proxy.users".

Because of the switch in coupling direction in Swiz-style programming, this obviously changes.  Typically, a Swiz application's Controllers maintain a reference to model data.  Views may then bind to the controller directly.  (Remember, Swiz favors coupling view components to controllers.)

In both frameworks, the idea of a "delegate" can be implemented.  A delegate typically acts as a surrogate for accessing remote APIs, such as RemoteObjects or other Web services.  A delegate serves to hide this implementation from the rest (pun intended) of the application.  In PureMVC, Proxies can act as delegates by defining (or acquiring references to) RemoteObjects and manually using Flex's native Responder, result, and fault mechanics to execute calls against remote services.  Swiz, rooted in Java and ColdFusion-focused Flex development, allows you to speak to simple services directly from a Controller, provided helper functions to simplify handling success and failure conditions.  Further, it provides helper classes (MockResultEvent) to allow developers to more easily simulate the presence of a server in prototyping and unit testing situations - a feature unique to Swiz (to my knowledge).

Opinion:  I prefer KISS approaches when possible, so I prefer Swiz.  I just don't quite see the need to develop and register framework-specific singletons that contain my model data in addition to singleton controllers.  Instead, I'd rather just have controllers that contain the data directly.  I'll admit it's a tighter coupling, but in neither case does the model know squat about the controller or view tiers, so "pure" MVC is maintained.


Groovy ate my Actionscript's semicolons!

I think I've been writing too much Groovy.  I was reworking some navigation in the Broadchoice Workspace this morning, and noticed that I had stopped using semicolons entirely.

It's a small thing, but I'm finding the code is just easier on the eyes.  At first, with Groovy, I had a hard time without semicolons - my brain is just programmed to see them.  After some adjustments, though, I'm living a happier life with less punctuation in my code (ha!  take that, perl and Ruby lovers!).

Powerful MXML Bindings with Ternary (?:) Operators

One thing I've found myself doing more and more often in Flex applications is using Ternary operators within data bindings. Frequently, if I find myself with an event handler that updates visual state based on nothing more than a condition, I can replace the AS3 function entirely with such a binding.

A example over on the Flexexamples blog that was posted earlier today shows a good "before" picture of the situation. A change handler is assigned to a checkbox, and based on the state of the checkbox, an error string is set / nulled:

<mx:Script>
<![CDATA[
private function checkBox_change(evt:Event):void {
    if (checkBox.selected) {
        checkBox.errorString = "";
    } else {
        checkBox.errorString = "You must click here to continue";
    }
}
]]>

</mx:Script>

<mx:CheckBox
    id="checkBox"
    label="I have read and agreed to your license"
    errorString="You must click here to continue"
    change="checkBox_change(event);"
    width="100%"
/>

Full code available at Flexexamples.

What's the Ternary operator?

It's a shortcut to a conditional operator that uses a ?: combination as a quick "if / then / else" to return one of two values. It can replace the following code:

if (foo == bar)
{
    result = "success";
}
else
{
    result = "failure";
}

With this:

result = (foo == bar ? "success" : "failure");

What's important about it in this context is that it's legal to use it within a data binding expression.

Putting it all together

By using a ternary operator in a binding expression to control the CheckBox's error string, we can replace the AS3 event handler in the Flexexample code entirely, leaving us with nothing but MXML:

<mx:CheckBox
    id="checkBox"
    label="I have read and agreed to your license"
    errorString="{checkBox.selected ? null : checkBoxErrorString}"
    width="100%"
/>

Other uses

I find myself often using this to control whether or not a control is enabled/disabled while a server-side operation takes place:

<mx:Panel
    title="Edit User: John Doe"
    enabled="{this.saveStatus != AsynchonousStatus.WAITNG}"
/>

I'll also use it to show / hide elements when a full-bore state may not be necessary:

<mx:HBox>
    <mx:Button label="Home" />
    <mx:Button
        label="User Management"
        includeInLayout="{currentUser.isAdministrator}"
        visible="{currentUser.isAdministrator}"
    />

</mx:HBox>

Conclusion

Data binding allows us to work declaratively, and by using it to evaluate expressions as well as update data, we can avoid a good deal of manual event handling.

Photoshop Express: Novice User Experience

I am by no means a designer. I do like to take pictures now and then, retouching them and sharing them with friends and family. While I've got CS3, it's an intimidating and complex product for my needs. This probably places my in the demographic targeted by Photoshop Express: nondesigners who want to do a little retouching and sharing.

I fired up the beta this morning, and here's the summary of my experience.

No custom loader?

If it's this high profile of a RIA, I'd expect a more branded version of the stock Flex application loader, even if it's just the Ps glyph over the progress bar.

Better-than-average Flex form validation

I'm not a huge fan of default Flex form validation, where you just glow the incorrect fields. I love how the signup form alerts you with what's wrong then returns you to the form with the incorrect fields highlighted, still showing intelligent messages on focus. The glowing fields did omit passwords not matching, though - probably a quick fix!

And is it a coincidence that my captcha contained "PDF"?

Verify account? What the heck?

Why am I taken to an HTML page asking me to verify my account instead of having this shown in the main Flex app? Why does this link take me to another HTML page that then links me to the Flex app? Kind of a wonky workflow that could've been done without ever leaving the app...

Quick Start -> Upload Photos

Oh my, this is slick. Someone really thought through getting a new user started. You want to get started immediately? Click Quick Start to drop to your library and be immediately prompted to upload a photo. Select a photo (or photos) and you get a great Flex UI showing you progress of your uploads. 54% and waiting...

Opening a photo

Ok, I see my photo..click. Nothing. We're so used to the Web that we've become single-click beings. Double-click...ok, now I'm editing. I guess I could've used the "Photo Options" or "Edit Photo" button, too, but some sort of action on single click would be nice.

Autocorrect and other basic tools

I expected to click "Autocorrect" and get a corrected image. What I got instead was a great surprise - it gives you its best guess as well as thumbnails of a few other correction candidates. Absolutely great for a nondesigner like myself! Rollover a thumb, and it'll show it to you in the large space. Click and hold "View Original" at any time to see what you started with. Sliiiick.

Ok, I'm all corrected and balanced...let's share this out so you can see what I've done.

Sharing Photos

Where's the Share button? Can't find it on the editing screen. Let's try Saving to see where I go...

Nothing saying "Share," but there's an E-Mail Photo and Create Album option. Maybe an Album is shareable to you?

Select two images (edited and an original copy I uploaded), create an album, and "Share Album," and it looks like we're good to go. Maybe a changing "Create Album" to "Create and Share Albums" would be good.

Anyhow, I'm now sharing the Album on My Gallery, but I'm not sure how to give you a URL to it. I could e-mail friends, but I'd rather have a link.

Ah, ok. Once in your gallery, you can choose an Album, click "Link" or "Embed," and you get some bits. Might be nice to just show these options on the prior screen as well as on the Album viewer itself.

Embed is cool! Here's a preview and link to the album

Summary

Absolutely great tool when it comes to allowing a nonphotographer / designer like myself to tweak pictures and catalog my photos. It took me a bit to learn how to use it, but I won't be forgetting what I found. I think there's a bit of room for making things easier on the user when it comes to sharing, but I dig it.

Flex "RadioButton" ListItemRenderer

I'm becoming an ever increasing fan of the way the Flex visual components were built. Yeah, some things are private when protected would be nice, but for the kind of data-focused work I do I find myself rarely getting stuck. On top of that, building Flex widgets is the perfect 3:00AM brain exercise for when our 3 month old daughter wakes me up.

Anyhow, I needed a better way to show long lists of radio buttons in a UI. Using a repeater just kind of stank - I wanted something that worked like a normal list, but showed a RadioButton beside each item. Thirty minutes later, I was in business:

I decided to blog it as it's a dead simple example of how to extend a base Flex component, add additional visual children, and control both the layout and data-focused aspects through the UIComponent "lifecycle" methods and Flex events.

Here's the code for the renderer:

package com.firemoss.controls.list
{
    import mx.controls.RadioButton;
    import mx.controls.listClasses.BaseListData;
    import mx.controls.listClasses.ListBase;
    import mx.controls.listClasses.ListItemRenderer;
    import mx.events.ListEvent;
    
    public class RadioButtonListItemRenderer extends ListItemRenderer
    {
    
        /**
         * Radio button shown at left of control.
         */

        private var radioButton:RadioButton;
        
        /**
         * List owning this renderer.
         */

        private var list:ListBase;
        
        /**
         * Override createChildren() to create a radio button.
         */

        override protected function createChildren():void
        {
            super.createChildren();
            
            // Create our radio button and add it to the display list.
            
            this.radioButton = new RadioButton();
            this.addChild(this.radioButton);
        }
        
        /**
         * Override updateDisplayList to position radio button
         * and shift label.
         */

        override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
        {
            // Shift what super thinks of width by our radio's width...
            
            super.updateDisplayList(unscaledWidth - this.radioButton.width, unscaledHeight);
            
            // For my purposes, a hard width is fine.            
            
            this.radioButton.width = 25;
            
            // Place our radio
            
            this.radioButton.x = 6;
            this.radioButton.y = this.height / 2 - this.radioButton.height / 2;

            // Slide that label over
            
            this.label.x = this.radioButton.width;
            
        }
        
        /**
         * Override the listData setter to add listener for changes to the owner (List selection change)
         */

        override public function set listData(value:BaseListData):void
        {
            super.listData = value;
            
            // If we're in the right condition
            
            if (value.owner is ListBase)
            {
                // Remove event listeners from any prior assigned list
                
                if (this.list)
                {
                    this.list.removeEventListener(ListEvent.CHANGE, ownerChangeHandler);
                }
    
                // Keep the list around
                
                this.list = value.owner as ListBase;
                
                // Watch the list for changes to its selection
                
                this.list.addEventListener(ListEvent.CHANGE, ownerChangeHandler, false, 0, true);
            }
        }
        
        
        /**
         * When the list's selection changes, update the state of the radio button.
         */

        private function ownerChangeHandler(event:ListEvent):void
        {
            // If the list has a selection and it's this renderer's data, check the button
            
            this.radioButton.selected = (this.data != null && this.data == this.list.selectedItem);
        }
        
    }
}

Enjoy, and happy listing!

Custom Flex ToolTips made easy with CustomToolTip

Over the past year, I've spent a good deal of my time reconciling what designers create with what Flex provides. One of the items I run into most frequently is the need for a seriously custom tooltip: images, formatted fonts, etc.

Until today, my approach matched many others, handling the toolTipCreate event and setting the tooltip to use manually. This got a bit repetitive, so I've wrapped up the logic in a CustomToolTip class (attached to this blog entry, download it here) that makes it a declarative process.

You simply state the component creating the tooltip (the "source") and what class to use (not instance, but class!) as a ToolTip (the "renderer"):

<tooltip:CustomToolTip source="{someButton}" renderer="{com.myapp.SomeToolTip}" />

<mx:Button id="someButton" label="Some Button with a Custom Tooltip" toolTip="someTooltipText" />

When the button is moused over, a new instance of com.myapp.SomeToolTip will be created.

If your renderer class implements ICustomToolTip (in the attached .zip), it'll have the source's instance set into its "source" property. This allows you to place a custom tooltip on something like an itemRenderer and access its underlying "data" property.

Flex 3 SDK and BlazeDS in Subversion Repos!

How cool is this? It looks like Adobe's taking their Open Source stance pretty seriously. If you want to get your hands on BlazeDS or the Flex 3 SDK, they're using straight-up Subversion repositories that you can directly access!

For example, I'd like to look into why circular references are such a bear to serialize / resolve. Now, I can geek to my heart's content looking at the serialization code directly in the repo!

Silverlight 2: Looks good!

Odd for me to say something positive about Silverlight. I tried 1.0, and sort of gave up. After reading Scott Guthrie's blog entry about Silverlight 2.0, I might have to give it another shot - I like C#, but just can't stand ASP.NET.

What I really like about the Silverlight 2.0 screenshots shown is the the darn thing looks good. Frankly, out of the box Flex looks pretty lousy next to it. It's got clean scroll bars, good-looking buttons, and I don't see anything that's the weird-shade-of-blue-green-not-found-in-nature that's all over default skinned Flex apps.

Odd to see a Microsoft product that's graphically more pleasing than something from Adobe. Maybe Flex 4 (or a 3.01) could bring about a real skin update that makes our default applications look halfway decent?

[top] [More Entries]