I am currently in the process of re-building www.subdelay.com in order to accommodate some of the changes I mentioned earlier and also to make the site more maintainable and easier to expand upon than the current version.
The original site was created in Flash 7, meaning that everything was done in "good old" Actionscript 2. The second incarnation of Actionscript never really had a good structure for keeping code organized and this paired with the fact that I at the time to be honest didn't really know what I was doing and was picking up things as I went has resulted in a...shall we say less than pretty codebase, that wouldn't be much fun to try and clean up and re-use at this point.
Hence the decision to completely rewrite the site, and in an effort to keep things a bit systematic I have been using Flex for the task this time around. Also, while the original site uses PHP as its backend, with all the Ruby work I have been doing lately it only seemed natural to have the new version run on Ruby on Rails.
I am however a newcomer to Flex and have been relying on the book Flex on Rails
for support. The book does a fairly good job of explaining how to plug a Flex frontend into a Rails app, but there is one thing that has been bothering me a bit about the whole process.
Although the book touches upon the virtues of keeping things "DRY" on the Rails side of things by employing "convention over configuration" and making good use of the refactoring techniques that seem so natural when using Ruby, from reading the book it seems that these principles don't apply when writing the Actionscript 3-based Flex code.
In the case of subdelay.com I am using the Cairngorm framework, and from reading through the examples in the book, it seems that the way to do things is to:
- Create a "delegate" for every resource you have (for subdelay.com this might be "Artists"," Tracks", "Albums", "Cart" etc).
- Create an "event" for every user gesture/application event ("PlayTrackEvent","EmptyCartEvent","LoadAllAlbumsEvent","LoadAllArtistsEvent", etc)
- Create a corresponding "command" for each event that tells the program how to react whenever an event occurs (thus we have "PlayTrackCommand", "EmptyCartCommand" and so on)
Now, each of these are represented by a separate file with a separate class definition, and to me this just seems like an unnecessary amount of similar code divided among an unnecessarily large number of files that you have to keep track off for something that seems like it should be much simpler.
The part where it gets particularly weird for me is when creating the delegates. You are basically creating a class for each resource you want to access on the Rails side, but the code in these files end up being almost completely identical since all they do is expose the typical REST-based methods ("index","show","create","destroy","update") for different Rails controllers with only a few variations for the controllers that have additional non-standard methods defined (such as the method "recent" in my case, for loading only the most recent albums). Using subdelay.com as an example you then end up with a file structure that looks something like this:

This just didn't seem right to me, so I went ahead and had a go at replacing all the individual delegate classes with one generic "RestfulDelegate" class, which works with any Rails-based resource I care to throw at it and contains the 5 basic REST methods as well as a 6th generic method that allow the use of any custom methods as needed.
When calling out to your delegates from a Cairngorm ICommand you would usually write something like
var delegate:AlbumsDelegate = new AlbumsDelegate(this);
and have AlbumsDelegate hardcoded to use the "albums" service. Instead, when using RestfulDelegate you simply write:
var delegate:RestfulDelegate = new RestfulDelegate(this,'albums');
Passing in "albums" as the second argument ensures that the right service is selected (configured in Services.mxml) and therefore only one class is required for all resources exposed in the Rails app, and I don't have to create a new file for every new resource I add. Having the generic "send" method also allows me to deal with situations where I have added custom methods to a controller. So for example the "recent" method found in the AlbumsController can be called in the following way:
public function execute(e:CairngormEvent):void {
var delegate:RestfulDelegate = new RestfulDelegate(this,'albums');
delegate.send('recent',{limit:5});
}
I guess I could even have gone as far as to replace all the other methods with this one method to even further reduce code, but for the time being I kinda like the idea of having the basic bread/butter methods hard coded.
It's all very basic but I am wondering, is there something I am missing here? Am I doing something that will get me in trouble later?? :o I realize there might be some sense in having a separate delegate for each resource if you are planning on replacing the Rails backend for that resource with an external API or something like that at a later stage, but apart from that I don't really see the advantage of having to deal with all those files and classes.
I am currently trying something similar to reduce the amount of code repetition required for events and commands, but haven't yet figured out the best way to go about it. Will let that be the subject of a future post I guess!