aodz

FrameworkQuest 2008 : Introduction

Posted on: January 16, 2009


I am thankful to Tony Hillerson for writing this post.
please find the original post here

FrameworkQuest 2008: Introduction
FrameworkQuest 2008 Part 2: Get Control with Cairngorm
FrameworkQuest 2008 Part 3: Agnostic Views with PureMVC
FrameworkQuest 2008 Part 4: IoC With Swiz
FrameworkQuest 2008 Part 5: Mate, the Pure MXML Framework
FrameworkQuest 2008 Part 6: The Exciting Conclusion

FrameworkQuest 2008

Part 1: Take a Step Back

Frameworks

Frameworks, frameworks, frameworks. We talk about them all the time. What’s the best one? Which one ticks the most boxes off the pattern checklist? What’s everyone using these days? We talk about frameworks so much that it deserves to be written like this:


FRAMEWORKS!!!

We Work Hard, So You Don’t Have To

This series of articles is scientifically designed to help you get an understanding of the major Flex Frameworks on the market today.

  • • What are your choices?
  • • How do they work?
  • • What do they preach, and is it hard to practice what they preach?
  • • How does Brand X stack up against my brand of choice?
  • • And the most important question: Does this framework make me joyful?

I could have gone about this quest multiple ways, but the way I chose was slightly more organic than the more obvious rundown of features, and I hope you get more out of this approach.

I’ve taken a simple application and built it five ways. Once with no framework at all, and once each with these Flex Frameworks:

  • • Cairngorm
  • • PureMVC
  • • Swiz
  • • Mate

All source code is available at http://github.com/thillerson/twitteria. To get the code, either check the project out using Git, or if you just want the source as a zip file, click the “download” button. The project targets Adobe’s AIR platform. I expect that you know how to work with and build AIR projects already, so I don’t take any time to explain that.

In the interest of full disclosure, I should let you know that I hadn’t used any of these frameworks before except Cairngorm, which I use pretty much every day. I did research and write a chapter on Cairngorm and PureMVC for Flex on Rails (shipping Q1 2009), so I was already familiar with PureMVC, but I’m most used to building with Cairngorm, and I had never worked with Swiz or Mate at all before this article was written.

At the end, in the last article in the series, I’ll put forward a subjective rating system to give you an idea of what I thought of each framework.

What Good is a Framework?

Let’s take a step back. Why do we use frameworks? Here’s a graphic whose idea I stole from a slide in Cal Henderson’s Djangocon Keynote thoughtfully entitled “Why I Hate

Django”. This graph shows, with the best science available to the author, why we use frameworks. No frameworks were harmed in the making of this graphic.

Speaking in terms of complexity, a very simple application has a small advantage in development speed over an application of similar complexity using a framework. There are rules and a little bit of red tape you have to cut through to use the framework, so for a dead-simple app skipping a framework is a win in development speed.

Frameworks start to show value when you want to do things that a lot of other people want to do, like call remote services, keep things clean and separated, and in general think about your app based on similarities to every other application out there. That’s what makes a pattern – common use.
Following the rules of the framework pays off in productivity. You have to think less about how you want to do what you want to do, because the framework has ready, commonly accepted answers for you.

As complexity goes up, development is still pretty speedy, especially in a team situation, because the organization the framework imposes is paying off more and more. It’s probably easy to remember where functionality is because you know where it fits into the framework’s notion of where things should be. Development without a framework is slower because you’re either mired in disorganization or you’re spending extra time building something like a framework.

Things get tricky once you get to the 80/20 rule, if your app gets more complex than most. Frameworks may even make it difficult to do some things you want because at this level of complexity you’re beyond the common cases the framework solves and the rules are making it hard to do what you want. At this point it may even be easier to do things with your homegrown solution because you’re building things the way you need them.

At the end of the graph I’ll freely admit that I’m making things up. Let’s call this end of the graph “the point where the framework catches up because the author is in favor of frameworks” or simply the Deus Ex Machina section of the graph. In any case, my gut tells me that frameworks still have something to give even when applications get really complex.

The point of this artificial graph is to show that we use frameworks because at most levels of complexity of an application, a framework makes us more productive.

TwitteRIA – Don’t Worry, Anyone Can Get It

Ok, now on to the fun. The app we’re going to build was suggested by Anthony Franco, President of my company, EffectiveUI. He won hands down in a battle royale on Twitter, the microblogging site, the Great Chatroom of The Internet, where I asked for ideas from anyone on what app to build for this article. Sometimes the simplest person can have a flash of brilliance, and he suggested that I build a Twitter client. The prize was a mention in this article, so here it is: Anthony, you’re the best looking boss I’ve ever had! Great hair, nice teeth, a class act all around!

The application that I’ve used to build with each of these frameworks is a simple Twitter client that implements these user stories:

  • 1. Retrieve authenticated user’s timeline
  • 2. Set authenticated user’s status
  • 3. Be exceptionally pleasing to the authenticated user’s eye

You can be your own judge on number three, but numbers one and two are simple enough to not get in the way, and complex enough to exercise the frameworks. So without further ado, I give you TwitteRIA. Some of you may have it already, so to speak. I know I do.

All five projects use a special version of Twitterscript, which you can get here: http://github.com/thillerson/twitterscript/. It’s a version of Peter Armstrong’s, which is here: http://github.com/peterarmstrong/twitterscript/, and in turn a version of the original, which is here: http://code.google.com/p/twitterscript/. Credit where credit is due: all I did in my version was add back in the ability to authenticate users safely. Due to Flash security limitations, this means you can only use the library in AIR projects if you need to authenticate. The swc is included in the lib directory of each project. Since the application is written for the AIR platform you’ll need to have either the AIR SDK or Flex Builder installed.

Now let’s go through the framework-less application one feature at a time. Try to keep a lookout for problems in the application that you think a framework may be able to help solve.

Logging In

Logging in with Twitterscript is not quite like logging in to any other services. All we need to do is call a method on an instance of the Twitter object we’re going to use to interact with Twitter. Because of that, all we need to do is capture the login credentials of a user in memory, and then go on to load the user’s timeline. To do this, in the root application file we have two views in a view stack, like so:

twitteria_raw/src/twitteria_raw.mxml #24-27 (formatted)

<mx:ViewStack
	bottom="0" left="0" right="0" top="30" 
	selectedIndex="{viewIndex}">

	<local:LoginView id="loginView" login="login()" />
	<local:MainView id="mainView"
		username="{loginView.username}" 
		password="{loginView.password}" />

</mx:ViewStack>

LoginView captures a username and password and exposes them as public properties that we can bind into MainView. If you said “That’s not very scalable, Tony!!” well, you’re right. It’s one problem we can help fix with a framework, but for now it works. Inside LoginView, when enter is pressed on the password field, this method runs:

twitteria_raw/src/LoginView.mxml #12-16

public function login():void {
 	username = usernameText.text;
 	password = passwordText.text;
 	dispatchEvent(new Event('login'));
}

This sets the public properties and then dispatches an event, which is listed here:

twitteria_raw/src/LoginView.mxml #3-5

<mx:Metadata>
	[Event(name='login', type='flash.events.Event')]

</mx:Metadata>

Back in the application file, we’ll catch that event and switch the index of the ViewStack to show MainView instead of LoginView with the help of a few constants:

twitteria_raw/src/twitteria_raw.mxml #7-15

private const LOGIN_VIEW:int	= 0;

private const MAIN_VIEW:int		= 1;

[Bindable]
private var viewIndex:int		= LOGIN_VIEW;

private function login():void {
 	viewIndex = MAIN_VIEW;
}

Pretty simple so far. Now, since the creation policy on the ViewStack is the default, “auto”, views will be created when they are displayed. MainView will be created with the username and password from LoginView bound into its username and password fields.

Loading the Timeline

Once MainView is created, it runs the init method:

twitteria_raw/src/MainView.mxml #20-37


private var twitterService:Twitter;
private var useDummyData:Boolean = true;

private function init():void {
 	twitterService = new Twitter();
 	twitterService.setAuthenticationCredentials(username, password);
 	twitterService.addEventListener(
 		TwitterEvent.ON_FRIENDS_TIMELINE_RESULT,
 		friendsTimlineLoaded
 	);
 	twitterService.addEventListener(
 		TwitterEvent.ON_SET_STATUS,
 		statusSet
 	);
 	reload();
}


private function reload():void {
 	if (useDummyData) {
  		currentTweets = new ArrayCollection(getDummyData());
  	} else {
  		twitterService.loadFriendsTimeline(username);
  	}
}

A few things are going on here. First, notice that we have a private member variable of type twitter.api.Twitter, which is the wrapper for all calls to the Twitter API. This class is provided by the Twitterscript library.

Next we have a very simple way of deciding to use dummy data instead of making calls to Twitter. This is important for a few reasons.

Consider what happens to development when Twitter is down. I know, I know, you’re probably saying “But Tony, in all my years on the web, I’ve never known Twitter to be down!”. Well, I’m here to tell you that it may happen one day, and your development effort should be prepared.

Another reason is that Twitter limits the number of messages you can send in an hour. Might as well make sure that doesn’t slow development either. A less important reason is that maybe you want to do a little development somewhere without Internet access. I want to be clear that the implementation here is a very simple, even dumb, way of doing this, but I’m going to use it later in the series to make a point, so bear with me.

The init method instantiates the Twitter object, sets the authentication credentials, and then sets up some event listeners for two types of event TwitterEvent.ON_FRIENDS_TIMELINE_RESULT and TwitterEvent.ON_SET_STATUS.

The reload method is what we call when we want to reload the timeline. Here’s where we use our simple method of switching in dummy data. If we’re using dummy data, we simply call the friend timeline callback method with some dummy data, but if not, we kick off a call to the actual service. When that gets back, the callback is executed:

twitteria_raw/src/MainView.mxml #47-49

private function friendsTimlineLoaded(te:TwitterEvent):void {
 	currentTweets = new ArrayCollection(te.data as Array);
}

The callback sets a private member variable, currentTweets to an ArrayCollection that wraps the array of status messages in the result object or dummy data as the case may be. On down in the view section, there’s a list that shows the objects in the collection:

twitteria_raw/src/MainView.mxml #90 (formatted)

<mx:List 
	id="statusList" width="100%" height="100%"
	styleName="statusList" 
	itemRenderer="TwitterStatusRenderer"
	dataProvider="{currentTweets}" />

The item renderer, TwitterStatusRenderer, displays a single twitter.api.data.TwitterStatus. Have a look at that if you’d like, but it’s pretty simple.

Not too much work for something pretty cool, eh? Of course there’s a lot more to a Twitter client like Twhirl or Twitteriffic, but it’s kind of neat to see status messages coming up with as little code as there is so far. But wait! There’s more! We can also update the current user’s status.

Setting Status

MainView has a TextInput that takes a status message, with a simple little method to tell the user how much of the 140 characters of Twitter message goodness they have left to them:

twitteria_raw/src/MainView.mxml #96 (formatted)

<mx:TextInput id="statusText" width="100%" maxChars="140"
	enter="setStatus()" keyUp="countCharactersLeft()" />

When the enter key is pressed, the setStatus method is called:

twitteria_raw/src/MainView.mxml #39-45

private function setStatus():void {
 	if (useDummyData) {
  		statusSet(null);
  	} else {
  		twitterService.setStatus(statusText.text);
  	}
}

Again, this method asks if we’re using dummy data or not, and calls Twitter if we’re not. When Twitter returns or the callback is force-called, the callback is executed:

twitteria_raw/src/MainView.mxml #51-55

private function statusSet(te:TwitterEvent):void {
 	statusText.text = '';
 	countCharactersLeft();
 	reload();
}

The status text and character count are cleaned up, and reload is invoked, which loads the timeline again. With any luck, Twitter will return the status message we just posted in the new timeline.

There it is, a simple, effective, Twitter client.

Next Up

So if what we have here is working, why do we need a framework? Well, the app as it stands has some problems.

  • 1. State Storage. We’re passing essential data from view to view, namely the username and password. If Flex’s binding didn’t make it so simple to code this, the code it would take on the distinct smell of Spaghetti Code
  • 2. Bloated Views. Look at MainView. Can you describe what its responsibility is? I think it would go something like this: MainView is responsible for keeping a reference to the Twitter service, deciding when to call it or create dummy data, responding when the timeline is loaded, putting the timeline data into a dataprovider, setting status messages, reloading the timeline when a status message is set, and displaying the currently loaded timeline. That’s way, way, way too much. That view is schizo, friends. It doesn’t know if it’s dealing with service interaction, dummy data, display, or a pleasant mix of everything all at once.

These problems are exactly the type of thing a good framework will help us address, and we’re going to start addressing them next time by looking at the old standby Flex Framework, Cairngorm.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

I have moved to a different location

check out my new home Flexout

calendar

January 2009
M T W T F S S
« Dec   Feb »
 1234
567891011
12131415161718
19202122232425
262728293031  

Blog Stat

  • 83,703 Hop's so far!!!

follow me

Archives

Linkedin Blogger Twitter Youtube Orkut

Top Clicks

  • None

latest flickr photos

top rated

%d bloggers like this: