Widgetized
May 19th, 2008Most Flex / Flash developers I know are using some flavor of MVC to build their applications. It’s greatest strengths are scalability, and rapid development in team environments. But when I came to MVC I had hoped I would also find that the code I had written for one project would be more reusable in projects down the line. And although MVC Frameworks take a big step in this direction, there are still a lot of gotchas that can make it difficult to dig out a class or two from a project you worked on a few months ago and use it in your current project.
Widetized development is a methodology and a thought process that can be applied on top of what ever frameworks or conventions you have adopted already. It doesn’t limit your applications to be used only as widgets.
I have a bad track record for predicting what pieces of code are going to be useful in the future. Most of the classes I build to be reused never are, and the classes I write as specialty one-offs end up being used over and over again. Widgetized development allows you to take a piece of code that was never intended to be used outside of the application is was written for and use it anywhere without rewriting it.
Here are some key principals that you can start using today that will make it much easier to take whatever you are working on right now and use it for something completely different a month from now.
Standardize the Data Model:
I have gotten up on this soapbox many times in the past, but your Models and VO’s are usually the the biggest hurdle. Most likely your current project has a data structure that is very specific to it’s own needs. If you have taken my past advice, you at least have a flat data structure that is not necessarily modeled to look anything like the source it came from but rather it is modeled to make it as easy as possible for your app to get the info it needs. You may even have gone as far as to implement my suggested list of basic methods every data model should have: addItem(), addItemAt(), getItemAt() ,getItemIndex(), removeAll(), removeItem(), removeItemAt(), sortOn(), and toArray().
But how much easier would it be if your data model was a standard library class that you decide to use for every project. Deciding to treat data models with the same level of standardization as the rest of the application will end of saving you a lot of work if that app, or a piece of it, has to fit into another application. If the data model is universal, you will be able to take a piece of your app to another and have it work directly with the data in the data rather than working through a data translation layer.
Outsource the Delegates:
The data model is the lowest level a widgetized application should be concerned with. Dealing with services and delegates should be compartmentalized as this is the one part of any application will not be reusable. The operations behind querying servers, gathering data, and translating the results into data models is very specific. If you build your app such that it does not depend explicitly on any services, service locators, or delegates, it will be easier to take the app ( minus the service interactions ) and stick it in to a new app that will no doubt have it’s own service handling and data gathering classes.
If you are using a Command-based Controller that is typical of MVC frameworks, consider having you commands call their Delegates through an Interface and passing in the actual Delegate class in through the event that triggered the Command.
Alternatively you can limit your commands to strictly setting state variables on your model. If your application is simple enough, having your wigetized command set State.loading = true; could be enough to signal your main application to load in the data in whatever way it knows how. This approach has it’s drawbacks when your application becomes complex and you need some granularity in the way your data gets loaded. Soon you will be stuck with a state object that has 20 different state flags describing 20 different load processes.
Whatever way you accomplish this, your widetized app should have a way of signaling when it needs data and responding when it gets data. And you should figure out a way to do so in a standard way so you can plug it into any future application.
Avoid Frameworks that make excessive use of the Singleton… I’m talking to you Caringorm:
Not that I have anything against one of the most common frameworks in our community, but I have never been comfortable with the number of Singleton classes this framework ( and most frameworks ) uses. The purpose of using a Singleton is to make sure that there can be one and only one of that particular class. Many of the more popular frameworks instead use the Singleton as a way of having a global level class. This can backfire on you if you are not careful.
Take for example a recent problem I encountered when I had a Caringorm based video player and I wanted to use in in an application where there needed to be multiple instances of the video player on stage at once, each with it’s own video source and it’s own controls. Since I was using Cairngorm which uses a Singleton for it’s FrontController, ModelLocator, and CairngormEventDispatcher classes, all of a sudden all of the instances of the video player were forced to share a Data Model and State ( through references through the ModelLocator ) and all responded to each others events ( through the CaringormEventDispatcher and FrontController classes ). It turned out that clicking play for one video player made them all start playing… not good.
Singletons act on a global domain level. That’s why it’s important to make sure that the use of Singleton classes truly passes the ‘there can be one and only one’ test ( a test that obviously the Cairngorm Singleton classes do not pass). Widgetized development is all about the possibility of having multiple instances. Be very weary about using any framework that makes liberal use of Singletons, and if you must, consider extending or modifying them so that you be sure you do not have collisions when your widgetized app is instantiated multiple times.