Model-View-ViewModel in Silverlight and Flex
Last year I have been working a lot on Flex applications, and because of this I usually take my experience from Flex development and apply it to Silverlight. One example is the PureMVC framework that we use at Nascom for most RIA applications we build. The framework also has ports towards other technologies and one of these is the C# Silverlight port. I recently checked it out but they seem to have trouble keeping up with the speed of Microsoft's Silverlight releases.
So let's see if I can bring some of the patterns I learned while developing Silverlight into the world of Flex. One specific pattern that I want to talk about is the Model-View-ViewModel pattern. It's a specialization of the PresentationModel design pattern introduced by Martin Fowler specific for the Windows Presentation Foundation (WPF). Yeah, but what about the MVC pattern? Doesn't that already cover all our problems? In the MVC pattern, the model is the data, the view is the user interface, and the controller is the programmatic interface between the view, the model, and the user input. This pattern, however, does not seem to work well in declarative user interfaces like Windows Presentation Foundation (WPF) or Silverlight because the XAML that these technologies use can define some of the interface between the input and the view (because data binding, triggers, and states can be declared in XAML). And for the same reason it also applies to Flex, and even more to Flex4 because MXML will become more declarative in the future.
So what is the Model-View-ViewModel? The pattern is an adaptation of the MVC pattern in which the view model provides a data model and behavior to the view but allows the view to declaratively bind to the view model. The view becomes a mix of XAML and C#, the model represents the data available to the application, and the view model prepares the model in order to bind it to the view.
Probably most Silverlight developers out there are already familiar with this pattern, but I created two small sample applications (one in Silverlight 3 and one in Flex4 beta 2) to compare both technologies and give you an idea how it works. Both applications do exactly the same thing. They load an XML file with data (Phones) and display this data using data binding. You can change the amount so that you can see the total price changing. Yeah, this is definitely no rocket-science (doh, should have used rockets!) , but it works. The Silverlight client loads the XML file using LINQ. LINQ is pretty cool and powerful, but it still takes more code to parse an XML file in Silverlight than it does in Flex using e4x.
You can download the source files for the Silverlight 3 and Flex4 demos here.
Model-View-ViewModel in Silverlight 3
Model-View-ViewModel in Flex 4 (right click to view source)
What do you think? I find this pattern easy to use in applications that depend heavily on data binding like Silverlight and maybe also Flex. But I think I will still be using PureMVC for my next big Flex Project.
FlexMonkey 1.0 released (adding AIR support)
This week the guys from Gorilla Logic released FlexMonkey version 1.0 beta. I have been testing the previous version on one of my Flex applications and now that they have released it as an AIR application I will definitely start using it more and more for future projects.
So, what exactly is it?
FlexMonkey is an Adobe AIR application used for testing Flex- and AIR-based applications. Providing the functionality to record, playback and verify Flex UI interactions, FlexMonkey also generates ActionScript-based testing scripts that you can easily include within a continuous integration environment.
How does it help a developer like me build better applications? Well, you need to test your application right, and in the end you always end up doing the same actions over and over again. FlexMonkey can record those repetitive actions so you can replay this if you need to test. From those recorded actions, FlexMonkey can generate AS3 code that you can add to your project. And if you use some kind of continuous integration solution (like Cruise Control, Hudson, ...), these test cases can be plugged in and automatically executed. FlexMonkey supports Fluint and FlexUnit 4 for unit test creation and has support for Ant and Hudson. The source code is available on Google Code.
You can read more about testing your Flex application in this article on Adobe Developer Connection or check out this introduction video. It should give you an impression of what the application can do.
Congratz guys and keep up the good work!
Timy – Time tracking in 7th gear using Adobe AIR
Recently my company (Nascom) released beta, an Adobe AIR desktop client that we have been using internally for more than a year now. The application has a long history and was initially built to gain knowledge about Adobe AIR and to make time tracking using Basecamp easier to do. I don't know if any of you use Basecamp for time tracking but it is not the easiest thing to do. Probably most of you use Basecamp for the project management and collaboration features, but you can also use it for time tracking. The web interface doesn't provide you with a quick overview of projects and todo items.
The main idea was that if we had a simple way of adding hours to a project for a certain day, we could loose less time filling in our time sheets. Development started before Adobe AIR was released and at the time this seemed the perfect technology for such an application. We could leverage the power of Adobe AIR because it uses SQLite for local data, shows notifications, and runs in the system tray so that we don't forget to fill in out time sheets. The application is built using Flex 3 and the Cairngorm framework. Credits for the design of the application go completely to Kristof who did a great job.
One of the biggest reasons for using Adobe AIR, is that the Basecamp API doesn't allow you to get the data that's necessary for the Timy projects tab in one API call. You need to first get all the projects, and then for all the projects the to-do lists, and then you can get the to-do items. If you work in a company that does a lot of projects this can take a while to retrieve. That's why the application synchronizes this data (projects, to-do lists and to-do items) with a local cached SQLite database. Only when the app detects that there is a new (or removed) project it asks the user to synchronize again. Does this make any sense? Well it did for us and that's why we released this application as it is. If you might find a use for it or not, it was still fun to develop.
We also track the usage of the AIR application in real-time itself using Pubblegum. So if you see some extra outgoing API calls, then this is what is going on. We don't log any sensitive data, only basic actions like: open, error, sync, login and close. We also send along the version number to see which versions are running in the field. You can compare it with Google Analytics for Adobe AIR applications with offline support.
But before you get all enthusiastic and start installing the app, you should now a few things. Timy is a Basecamp client, so if you are not a Basecamp user then Timy is of no use for you. You also need to use Basecamp in certain way, and enable time tracking on your to-do lists. It's pretty easy to do, but if you don't work like this, there will be no tasks for your users. Also important to know is that we see the to-do item for a project as a profile (ex. Development, Design, Html, ...) and not individual tickets, tasks or to-do items that you can check off. This is very important. But you can still use both normal to-do items and time tracking enabled to-do items because Timy only looks at time tracking enabed to-do lists.
You can read more about how to configure your Basecamp projects in the "get started" section, and you can find more info on how to use Timy in the "documentation" section of the site. I don't normally read these kind of pages either, but I would strongly suggest to read the get started page. If you have any feedback for the app please add it to the feedback forum or drop me a comment here.
Bidirectional (two-way) data binding in Flex 4
I use data binding a lot when writing Flex applications. One of the new features in Flex 4 is bidirectional, or two-way data binding. This blog post shows you a simple example that demonstrates the difference between one-way and two-way data binding syntax.
The first example is the most commonly used data binding scenario. It uses the curly braces syntax. In the example a String variable myName binds to a TextInput field. However if you change the value in the input field, the underlying String variable is not changed. This is because this kind of data binding is only one-way. There is a way to achieve bidirectional data binding in Flex 3 and you can find more info in this article, but I will not go into detail about that in this post.
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:String id="myName">Alain</mx:String>
<mx:TextInput id="nameInput" text="{myName}"/>
</mx:Application>
For example in Flex 3 the DataGrid component had two-way data binding enabled if you made it editable. In Felx 4 it has become very easy to achieve bidirectional binding. The following example is based on the same scenario as the previous one, only now the underlying String value is updated.
<s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Declarations>
<fx:String id="myName"/>
</fx:Declarations>
<s:layout>
<s:VerticalLayout/>
</s:layout>
<s:TextInput id="nameInput" text="@{myName}"/>
<s:SimpleText text="{myName}"/>
</s:Application>
That's basically it. The @{} syntax makes sure that the myName variable is changed and because the SimpleText label is also binded to the myName variable the value is also updated.
These are pretty simple examples, but you can find more information about the Flex 4 data binding techniques in the following articles:
Useful actionscript libraries part 2
A while ago I wrote a blog post about a list of useful actionscript libraries on Google Code. So this is a follow up post, and an addition to the previous list. Not all projects are hosted on Google Code, so hence the slightly different title.
Here's the list:
- AlivePdf is a client side AS3 PDF generation library for Adobe Flash, Flex and AIR. It can also be used to display PDF files.
- HydraMVC is the result of a total rewrite of the PureMVC API exclusively for Flex, allowing Flex developers to take advantage of the PureMVC paradigm while leveraging native Flex features. Currently we mostly use the PureMVC framework, but this could be interesting for big Flex applications.
- FlexMonkey is a testing framework for Flex apps that provides for the capture, replay and verification of Flex UI functionality. FlexMonkey can record and playback Flex UI interactions, and generates ActionScript-based testing scripts that can easily be included within a continuous integration process.
- Open Flash Chart is a library that contains a number of frequently used charts like line, bar, pie, scatter charts and some more.
- Merapi is a Java™ application, intended to run on a user's (client) computer. Merapi connects other Java™ applications on the user's computer to Adobe AIR™ applications that the user has installed. In May, Merapi has officially become Open Source!
- Efflex is a library with a list of effect that can be used in Flex applications. Here's a list of available effects: Slide, CoverFlowPapervision3D, FlipPapervision3D, GridZoom, Grid, List, Squash, FadeZoom, Fade,TileFade, MovieClipEffect,...
- Spring Actionscript aims to bring Inversion of Control to ActionScript for use in Flex, AIR and even Flash applications. It contains an IoC container, based on that of Spring, a reflection API, extensions for the Cairngorm and PureMVC frameworks and several interesting utilities.
- The last one is actually not an actionscript library, but still very interesting if you are into application development using Flex. flex-mojos is a collection of maven plugins to allow maven to compile, optimize, test and ... Flex SWF, Flex SWC, Air SWF and Air SWC.We are currently using it for Flex projects that rely heavy on a Java back-end.
Some of the libraries I have used or played with already, and others I still need to checkout. Hope you find something useful here.
Flex 4: Create a simple Unit Test in Flash Builder
One of the new features of Flash Builder is the support for FlexUnit (the Unit testing framework for Flex applications). You could use FlexUnit in the past, but as from Flash Builder it's a piece of cake to create Test classes for your own code. You just need to follow these simple steps.
NOTE: This demo needs the latest beta version of Flash Builder. Be aware that this is still a beta version and the following could still change in future versions of Flash Builder.
Before we start we need to create a new Flex Project. After creating your project you need to create a class with some functionality that we can use in this example. The typical classes to unit test are classes that have a public interface and have a complicated implementation. When you change something inside the class implementation, the public methods still works as expected. But for the sake of simplicity we will create a very simple class with some simple behaviour.
{
/**
* Class that does something.
*
* @author alain
*
*/
public class MyObject
{
/**
* The constructor
*/
public function MyObject()
{
}
/**
* Returns the numeric vallue five
* @return 5
*/
public function giveMeFive():int
{
return 5;
}
/**
* Returns the letter A
* @return "A"
*/
public function sayA():String
{
return "B";
}
/**
* Returns always true
* @return true
*/
public function alwaysTrue():Boolean
{
return true;
}
}
}
Alright, now we have a Class that we can test. To create a new Unit Test you select New > TestCase Class and the following window should appear:
Enter the Name of the TestCase Class (in this case: MyTestClass), select the Class to test (in this case: MyObject) and select Finish. Flash Builder now generates several items. First a new folder name flexUnitTests is generated. Also a new mxml file named flexUnitCompilerApplication.mxml is generated. This file is necessary because the Unit Tests need a swf application that can be started and the tests can be executed. The last and most important file that's been generated is the TestCase itself. The only thing you now need to do is implement the actual test methods. In the following code example the test methods are implemented:
{
import flexunit.framework.Assert;
import flexunit.framework.TestCase;
import net.hufkens.MyObject;
public class MyTestClass extends TestCase
{
// Reference declaration for class to test
private var classToTestRef : net.hufkens.MyObject;
public function MyTestClass(methodName:String=null)
{
super(methodName);
}
//This method will be called before every test function
override public function setUp():void
{
super.setUp();
classToTestRef = new MyObject();
}
//This method will be called after every test function
override public function tearDown():void
{
super.tearDown();
}
public function testGiveMeFive():void
{
Assert.assertEquals(classToTestRef.giveMeFive(), 5);
}
public function testSayA():void
{
Assert.assertEquals(classToTestRef.sayA(), "A");
}
public function testIsTrue():void
{
Assert.assertTrue(classToTestRef.alwaysTrue());
}
}
}
If we now right-click the project and select Execute FlexUnit Tests we get the following message:
It says we need to create a Test Suite, otherwise Flash Builder can't execute the tests. To create a new Test Suite you select New > TestSuite Class and the following window should appear:
Now select Execute FlexUnit Tests again and your Test are executed. As you can see, one of the tests has failed. A quick view in the source of sayA() method reveals the problem. Fix the problem and all the tests should succeed now.
That's all there is to it. Flash Builder makes it a lot easier to create Unit Tests for your libraries and components. This is a good thing, so you should definitely check it out.
Flex 4: DataGroup and ItemRenderers
Today the beta's of Flash Catalyst and Flash Builder became available for download on Adobe Labs. This means that we can now start to play with the new Flex 4 SDK. There has been some controversy lateley about the pro's and cons of Flex namespaces. I was in the pro camp as you can see in this post I made some time ago. But enough about this discussion
If you want to have more information about the new Flex 4 SDK and what has changed you can go to the following articles:
- What's new in Flex 4 SDK beta by Matt Chotin (Flex 4 SDK Product Manager)
- Differences between Flex 3 SDK and Flex 4 SDK beta by Joan Lafferty
- Overview of Flex 4 by Sean More
- Flex 4 & Custom Layouts by Andrew Trice
- What's new in Flash Builder 4 beta by Tim Buntel (Flash Builder Product Manager)
For my first blog post about Flex 4 I want to show you one of the new components, and that's the spark.components.DataGroup component. Why? Because I have been using the old mx.core.Repeater a lot and there is no repeater in the new spark components.
In the old days of Flex 3 you could use the Repeater class when you needed a very specific view for customizing a list of data. It would look something like this:
<mx:Repeater id="myRepeater">
<mx:dataProvider>
<local:Person firstName="Alain" lastName="Hufkens"/>
<local:Person firstName="Hugh" lastName="Hefner"/>
<local:Person firstName="Jimi" lastName="Hendrix"/>
</mx:dataProvider>
<mx:HBox>
<mx:Label text="{myRepeater.currentItem.firstName}"/>
<mx:Label text="{myRepeater.currentItem.lastName}"/>
</mx:HBox>
</mx:Repeater>
</mx:VBox>
This example here is pretty simple, but it gives you a list that displays the persons showing the first and last name. You could extend this with the person's photo or address.
With the new DataGroup component you need a different approach and you need to work with ItemRenderers, something that already existed in the Flex 3 SDK. The next code snippets show you how to do this:
The first example uses the spark.skins.default.DefaultItemRenderer that can be used for very simple lists. By default the list outputs the toString() of an Object or in this example shows the String from the DataProvider.
<s:layout>
<s:VerticalLayout gap="1" />
</s:layout>
<s:dataProvider>
<s:ArrayCollection>
<fx:String>Frog</fx:String>
<fx:String>Cat</fx:String>
<fx:String>Mouse</fx:String>
</s:ArrayCollection>
</s:dataProvider>
</s:DataGroup>
The next example uses the spark.skins.default.DefaultComplexItemRenderer. This ItemRenderer renders different Graphical and complex components. You can have a Component like a Button, DropDownList, ... next to a graphical object like a Rect, Ellipse, ... next to each other.
<s:SolidColor id="fillColor" color="#fff000"/>
</fx:Declarations>
<s:DataGroup itemRenderer="spark.skins.default.DefaultComplexItemRenderer">
<s:layout>
<s:HorizontalLayout/>
</s:layout>
<s:dataProvider>
<s:ArrayCollection>
<s:Button label="Button" />
<s:Rect fill="{fillColor}" width="20" height="20"/>
<s:Ellipse fill="{fillColor}" width="20" height="20"/>
<s:DropDownList />
</s:ArrayCollection>
</s:dataProvider>
</s:DataGroup>
That's all pretty cool but it's not what I needed. I just needed something that can present my Person object. So in this case we need to create a Custom ItemRenderer. This is a very easy thing to do and the end result is a lot better then the Repeater solution.
<s:layout>
<s:VerticalLayout/>
</s:layout>
<s:dataProvider>
<s:ArrayCollection>
<local:Person firstName="Alain" lastName="Hufkens"/>
<local:Person firstName="Hugh" lastName="Hefner"/>
<local:Person firstName="Jimi" lastName="Hendrix"/>
</s:ArrayCollection>
</s:dataProvider>
</s:DataGroup>
And this is the code for the PersonItemRenderer:
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/halo">
<fx:Declarations>
<s:SolidColor id="normalColor" color="#000000"/>
<s:SolidColor id="hoveredColor" color="#FF0000"/>
</fx:Declarations>
<s:states>
<s:State name="normal"/>
<s:State name="hovered"/>
</s:states>
<s:layout>
<s:HorizontalLayout/>
</s:layout>
<s:Ellipse fill="{normalColor}" fill.hovered="{hoveredColor}"
width="10" height="10" />
<s:SimpleText text="{data.firstName} {data.lastName}"
color.hovered="#FF0000"/>
</s:ItemRenderer>
You can see the demo (including source) here.
Retrieve Basecamp data with BasecampAS3Lib
One of the projects I am currently working on is an open source Actionscript library that wraps the Basecamp REST API in an easy to use AS3 classes. The project is called BasecampAS3Lib an can be found on Google Code. The project is still in development and I did some serious refactoring yesterday.
At this point the services can only retrieve data from Basecamp and you can already experiment with the ProjectService, CategoryService and TodoListService classes. The other services still need to be implemented. But this post will give you a sneak peak on how simple it can be to retrieve data (in this case project data) from Basecamp with this lib.
NOTE: This code only works in an Adobe AIR application (see below for more details why).
<mx:WindowedApplication
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:basecamp="net.hufkens.basecamp.*"
xmlns:services="net.hufkens.basecamp.services.*"
layout="absolute" viewSourceURL="srcview/index.html">
<mx:VBox width="100%" height="100%">
<mx:HBox width="100%">
<mx:Label text="url:"/>
<mx:TextInput id="apiurl" width="100"/>
<mx:Label text="username:"/>
<mx:TextInput id="username" width="100"/>
<mx:Label text="password:"/>
<mx:TextInput id="password" width="100"/>
<mx:Button label="get projects"
click="getProjects()"/>
</mx:HBox>
<mx:DataGrid dataProvider="{projects}"
width="100%" height="100%"/>
</mx:VBox>
<basecamp:BasecampAPI id="api"
url="{apiurl.text}"
username="{username.text}"
password="{password.text}"/>
<mx:ArrayCollection id="projects"/>
<mx:Script>
<![CDATA[
import net.hufkens.basecamp.events.BasecampEvent;
private function getProjects():void {
api.projectService.addEventListener(
BasecampEvent.GET_LIST, handleGetList);
api.projectService.addEventListener(
BasecampEvent.FAIL, handleFail);
api.projectService.getList();
}
private function handleGetList(event:BasecampEvent):void {
projects = new ArrayCollection(event.data as Array);
}
private function handleFail(event:BasecampEvent):void {
Alert.show(event.data as String);
}
]]>
</mx:Script>
</mx:WindowedApplication>
However there is still an issue with the authentication. Apparently using basic authentication from a Flash/Flex application is not that trivial as it would sound. A while ago I wrote a blog post about this (read it here), but this approach only works when you run it from an AIR application. The same code doesn't work when running from a url on a web site.
So, if you have any suggestions or a solution for the basic authentication issue please let me know.
Tracking AIR applications with pubblegum
I don't have a lot of experience yet with tracking AIR applications developed with Flash or Flex. Adhese has a service called pubblegum that can be used directly from Flash without calling an external Javascript (which is the case with Google Analytics). So we decided to give it a try.
What exactly is pubblegum?
Whether it is Adobe® Flash®, Adobe® Air®, Microsoft® Silverlight®, Javascript or something as basic as an image. Pubblegum tracks your content in real-time from within the file and reports all available info, from custom interactions to URLs where your content was published.
Cool is that they have a specific API for AIR applications built in Actionscript 3 and the API also takes care of the fact that your application can be disconnected. If you want to use it, you can send them a mail to get a free trial. In our case we used the specific API for tracking user actions in the AIR application. And it is fairly easy to use. You only need to include the com.adhese.pubblegum.PubblegumAir class in your source code (a .swc file for Flex projects would also be nice guys) and write these two lines of code:
new PubblegumAir("companyID", "campaignID", "creativeID", true);
api.action("action");
The first variable is provided by Adhese and should be your company name/identifier, the second and third parameter can be chosen freely. The last parameter specifies whether you are tracking an application. So true tells the API, that the client is an application.
That isn't all that bad is it, and on top of that you get a nice dashboard where you can analyze your results.






