Showing posts with label ActionScript. Show all posts
Showing posts with label ActionScript. Show all posts

Tuesday, July 22, 2008

ActionScript: Literal XML

One feature of ActionScript I really like is the ability to use XML within the language. In ActionScript there's no need to use strings to represent XML, you can use XML inline just as you would any other literal (numbers, strings, etc).

Recently I was working on some dynamic code that needed to update based on an XML response. We were just getting started on the card, so instead of worrying about the service, how it was triggered, etc, we added a button to the interface that called the response parsing method and passed in an XML literal as an argument. The code is similar to what's shown below.

parseResponse(<user><firstName>Jay</firstName></user>);

Sure, we had to change the code later and make a real service call, but this quick solution let us keep focusing on the task at hand instead of how to get the XML. In a language like Ruby we could have used a builder or just a string, and given such a small amount of XML it would have been fine. However, the actual XML we were working with was significantly larger than the example and would have been a decent mess of a multiline string or several builder calls. Being able to write XML natively was significantly easier.

The beauty of literal XML is the simplicity. I don't have to represent it in any way other than what it actually is -- XML.

If you aren't a fan of all the angle brackets, that's okay, ActionScript has you covered there also. You can add elements and attributes as you would expect to be able to if you prefer method calls.

var request:XML = <smart_list/>;
request.sort.order = "highest";
request.sort.field = "Average Position";
request.max_results = 10;
request.toXMLString(); // "<smart_list><sort><order>highest</order><field>Average Position</field></sort><max_results>10</max_results></smart_list>"

If you only ever use XML similar to the above syntax, then there may be little value in literal XML, but I don't think you're usage would be limited to the above syntax.

I write tests, a lot of them. I prefer to see the actual XML in my tests, instead of the builder versions of XML. I don't like angle brackets any more than the next programmer, but I strongly prefer testing with expected literals. I find my resulting tests to be more readable and reliable. If you've ever had a test fail because of whitespace issues in your XML, you should know what I mean by reliable.

Literal XML also ensures XML compliance at compile time and encourages IDEs to provide syntax highlighting. Two things that aren't essential, but are definitely nice to have.

ActionScript is the first language I've used with literal XML support, and I'm very happy with the experience. As programmers we spend a lot of time hiding other languages with object relational mappers (orm) and builders, but literal XML is a refreshing step in the other direction. The creators of ActionScript have embraced the fact that XML isn't going anywhere. They built first class support for XML in the language itself instead of hiding the problem with a framework, and that helps me significantly more than any orm or builder ever has.

Tuesday, July 08, 2008

ActionScript: Calling a function by name

In Ruby I can call a method using it's name (as a string) using send.

def hello
"hello world"
end

send "hello" # => "hello world"

This type of behavior is helpful in scenarios where I store method names as values and execute those methods based on user actions.

In Flex I can store Objects in Views, so I generally don't need this capability. However, I recently wanted to execute a function based on what MenuItem was clicked. The menu was composed of MenuItems that were defined by XML. I couldn't figure out how to get a function into the XML, so i ended up putting the function name as an attribute of each MenuItem. From there, the only trick was figuring out how to call a function on an object if you have the name of the function stored as a string.

It turns out, it's very easy, and exactly what you do in Javascript. All you have to do is pass the string in brackets to the object that has the function defined.

this["methodName"]();

If you're interested in the context, the code below is similar to what my application required.

<mx:MenuBar id="myMenuBar" labelField="@label" itemClick="menuHandler(event);">
<mx:XMLList>
<menuitem label="Submit" handler="submit"/>
<menuitem label="Reset" handler="reset"/>
</mx:XMLList>
</mx:MenuBar>

private function menuHandler(event:MenuEvent):void {
this[event.item.@handler](event);
}

private function submit(event:MenuEvent):void {
// do submit logic
}

public function reset(event:MenuEvent):void {
// do reset logic
}

Tuesday, June 10, 2008

Flex: Objects in Views

Imagine the following requirement:
The application needs a combo box that has the following options:
  • delete
  • mark as spam
  • bounce
When delete is selected the current email (the one being viewed) needs to be moved from the inbox to the trash.

When mark as spam is selected the current email should be tagged as spam.

When bounce is selected the server should send a reject message to the server where the email originated.
Assume you are using the web. The traditional approach is to create a drop down with unique values that can be used on the server side (generally as a case statement). The unique values are strings, which represent keys, which are used to determine what the correct course of action is. This scenario works, and is familiar to most web developers, but it's not the most elegant solution.

Flex offers you a better solution. The Flex ComboBox allows you to set the dataProvider to an array of anonymous objects which can contain pretty much whatever you need. Even if you don't know Flex and ActionScript, the following code should still be readable, and interesting.

function init() {
comboBox.dataProvider = [{label: "delete", command:DeleteCommand}, {label: "mark as spam", command:MarkAsSpamCommand}, {label: "bounce", command:BounceCommand}];
comboBox.addEventListener("change", function(){ new comboBox.selectedItem.command().execute(); });
}


function init() {
comboBox.dataProvider = [{label: "delete", execute:delete}, {label: "mark as spam", execute:markAsSpam}, {label: "bounce", execute:bounce}];
comboBox.addEventListener("change", function(){ comboBox.selectedItem.execute(); });
}

function delete() {
// delete implementation
}

function markAsSpam() {
// mark as spam implementation
}

function bounce() {
// bounce implementation
}

This is one of the things I really like about Flex. Since I'm not tied to HTML and strings, I can put whatever I like in the view. The first example keeps all the logic out of the view and simply creates a new command and executes it immediately. It's nice and clean without worrying about converting from strings to classes. The second solution relies on functions to handle processing. In this case you could be doing something as simple as showing or hiding components in the view (not something you'd need a class for).

Either way, I'm working with first class concepts, instead of string representations of first class concepts. The result is cleaner code that's easier to work with.

Tuesday, June 03, 2008

ActionScript: The difference between Object and * (an asterisk)

If you've ever wondered what the difference is between the following two statements, you aren't alone.

var result:Object = sendRequest();
var result:* = sendRequest();

It's fairly hard to Google for the explanation, but Subhash Chandra Gupta recently pointed me to a good example.

The full article can be found in the Flex 3 Help.

The difference is that * (an asterisk) signifies that the object can be any type and typing something as an Object will require you to cast if you are compiling in strict mode. Here's a greatly simplified example to demonstrate.

function returnOne():Object {
return 1;
}
var one:Number = returnOne(); // compiler error in strict mode

function returnTwo():* {
return 2;
}
var two:Number = returnTwo(); // no compiler error in strict mode

Tuesday, May 13, 2008

ActionScript and Essence vs Ceremony

Over two years ago I started working primarily with Ruby. Since those days I haven't written a line of C# or Java, and I've often wondered if I would be annoyed by the ceremony that both C# and Java generally require.

I've recently been working a bit with Flex.Overall, I've enjoyed working with something new, and I can definitely see the appeal of RIA in general. It's been fairly easy to get started with Flex because it feels very similar to working with HTML and Javascript.
MXML, an XML-based markup language, offers a way to build and lay out graphic user interfaces. Interactivity is achieved through the use of ActionScript, the core language of Flash Player that is based on the ECMAScript standard. --Wikipedia Flex Information
ActionScript might be based on the ECMAScript standard, but it feels a lot more like Java than Javascript.

[Disclaimer: My experience with ActionScript is very limited, so there may be a better way that I'm not aware of]

I was working with a few MXML views the other day and I ran into a situation that made me think about essence and ceremony. The following example code is a simplified example of what I was working on.

<?xml version="1.0"?>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:ComboBox id="typeCombo"/>
<mx:Box id="typeDetailsBox"/>
</mx:HBox>

<!-- ~/views/OptionOne.mxml -->
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Label text="You chose option 1"/>
</mx:HBox>

<!-- ~/views/OptionTwo.mxml -->
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Label text="You chose option 2"/>
</mx:HBox>

The intent of the simplified example is to change what's inside the typeDetailsBox based on what's selected in the typeCombo.

To solve this in ActionScript I wrote code similar to the following.

public static const Option1:String = "1"; 
public static const Option2:String = "2";

public function init():void {
typeCombo.dataProvider = new ArrayCollection([{label:Option1, data:Option1}, {label:Option2, data:Option2}]);
typeCombo.addEventListener("close", function(e:Event):void{ doTypeSelected(); });
doTypeSelected();
}

public function doTypeSelected():void {
if (typeDetailsBox.numChildren > 0) {
typeDetailsBox.removeChildAt(0);
}
switch (typeCombo.selectedItem.data) {
case Option1:
typeDetailsBox.addChild(new OptionOne());
break;
case Option2:
typeDetailsBox.addChild(new OptionTwo());
break;
}
}

The code is easy enough to follow, but it feels much more verbose than what I prefer. I like being able to pass classes around as objects, so if I could, I'd probably make the classes themselves the "data" for the drop down. If that wasn't an option, I'd prefer an eval method that let me do the following.

public function init():void {
typeCombo.dataProvider = new ArrayCollection([{label:"1", data:"new OptionOne()"}, {label:"2", data:"new OptionTwo()"}]);
typeCombo.addEventListener("close", function(e:Event):void{ doTypeSelected(); });
doTypeSelected();
}

public function doTypeSelected():void {
if (typeDetailsBox.numChildren > 0) {
typeDetailsBox.removeChildAt(0);
}
typeDetailsBox.addChild(eval(typeCombo.selectedItem.data));
}

Unfortunately, ActionScript seems to be a language a bit more concerned with ceremony than I am.

Don't read this as a dismissal of Flex or ActionScript. Whether or not to use a language is a very complicated question and I wouldn't ever base my answer on a switch statement or the ability to eval. Like I said before, working with Flex has been a largely enjoyable experience, but, I must admit, after working 7 years with high ceremony languages and the past 2 with a low ceremony language, I know which I prefer.