RAGE: Letting The Beast Out (aka An Introduction To Relative Action Group Execution)
I have this idea in my head that I have started to call Relative Action Group Execution or RAGE. The way I see web applications, there are two main tasks that need to be accomplished:
- Figuring out what needs to be done.
- Figuring out how to do what needs to be done.
For example, in FuseBox, the fuse action would determine what needs to be done (user.list, product.edit) while the circuits/fuses, the MVC framework, or whatever framework you are running, determines the HOW of what needs to be done. RAGE is a twist on the first part, the figuring out of what needs to be done.
Before I get into Relative Action Group Execution, let me just touch upon the problems I have with other fuse-action style notations. But I don't want to pick on FuseBox specifically, so I will just refer to a generic "action variable" that houses some sort of defining value for the system. If you think of a web application like it is a map then the action variable would be the coordinates of a particular action to execute. So, if your action variable was something like "user.editAddress" you would know that you are editing the address of a user.
This is good, but in my head, this is very incomplete as far as coordinates go. If anything, this provides ONLY information About coordinates, not the coordinates themselves. Meaning, yeah, we're editing a user's address, but what user? What address? To make up for this short coming, frameworks will add other defining values to the coordinates such as a user ID and address ID. Now, the coordinates for the above action require an action variable, a user ID, and an address ID.
That's THREE pieces of information required just to define what action is going to take place. And what happens if the action is more specific? What happens if we have a system where we are editing the emergency contact's address associated with a user's contacts? What would that even look like?
user.editContractEmergencyContactAddress??? How many IDs would need to be passed around? Even with something like nested fuse actions (of which I know very little) would this even get any better? user.contract.editContactAddress. Is that better? Does that limit the amount of information needed to define an action?
The problem with most action variables is that the action is, for some reason, separated from the item upon which it acts. Relative Action Group Execution, or RAGE, merges these two required sets of data together into one easy-to-use action variable. So, for the above example where a generic action query string might look like:
... the RAGE query string would look like:
Notice that this is all one variable within the query string.
The RAGE action variable is composed of chained action groups. A group consists of an item and an optional key separated by a colon (:). Each chained action group is separated by a period (.). Going back to the crazy example above that was:
The RAGE'ing version of this might look something like this:
To read this, it would state that we are editing the address of ID (1) that is related to the contact of ID (1) that is related to the contract of ID (3) that is related to the user of ID (34). While this might sounds like a mouthful, it actually makes life much more simple; no more passing around multiple IDs in different variables. No more worrying about what values are called (id vs. userID) - everything is in one place that doesn't even depend on a name.
Relative Action Groups
The idea behind relative action groups is that you don't really need to know where you are in the system, you just need to know who your relatives are. Take, for example, the list of addresses; you shouldn't have to care where you are in the application in any kind of absolute way, you only need to know where you are relative to you nearest relative action group: listing user addresses, listing company addresses, listing "places we made out" addresses. I am not explaining this very well but trust me, this is some good stuff. By making all navigation relative, you tremendously limit the amount of information that you need to keep track of.
So that's my quick little introduction to RAGE (Related Action Group Execution). It's what I have been developing as a navigational system and so far, it is kicking some butt. It's just too easy to use. I am hoping to show some code about this very soon including some ColdFusion components that will parse this out into a linked list of action objects (CFCs).
Very interesting approach (although seriously, RAGE?! - you need to get back to the gym before you start hurting people :->).
The nice thing about this approach is that it is keeping some very useful state information in terms of how you got there (you are actually editing Address 43, but we now know what contract and user you edited to get to that address - obviously depending on your admin schema you might also have just ended up editing an address WITHOUT going via user and contract.
You might (or might not!) want to generalize the format to support any primary key (e.g. User:firstname.lastname@example.org for cases that require that) which would make it similar to a REST inspired admin interface I was considering (http://www.pbell.com/index.cfm/2006/11/15/A-RESTlike-Administrative-API) but with the ability to store multiple object IDs for composed objects. Hmmm, definitely worth pondering!
I like your post on the REST type interface. I have to say I am very new to REST in general. In fact, when I wired up my first web service (Amazon) it was the first time I even looked up what REST meant :)
I thought about having more general identifiers, and in fact, it has gotten me in a corner once or twice, but I love the numeric ID. It just makes me feel warm and fuzzy inside. Plus, like 99% of my stuff comes out of a database so the ID is mostly numeric. Of course, just as in your example of the email address, its gets hairy when you need to get something without a numeric ID.... but hey, I am still fleshing it out.
What I am really liking about this is the whole "relative" part of the it. The action variable actually gets parsed into a an action group stack that can have circular linking because each module simply pops off a stack item and checks what it is supposed to do with it (which might be passing control back up to the parent module). It's not the easiest to explain, so hopefully I will get some code posted up in the next day or so.
Of course, I have very little experience in Frameworks of any kind (mine or others) so this might all end in a horrible failure... but aren't the most horrible failures the best to learn from :)
I think it is a really interesting approach and look forward to seeing how it turns out :->
Interesting post, coming from a non-framework/non-OO person (talking about me, not you). Actually I do think I use OO principles, but thus far I've avoided the frameworks because I like to have complete control over my apps, and I feel that frameworks too much control away from the developer.
However, I've been in a lot of debates over the last year where I felt like I didn't really know what I was talking about, so I'm planning on using Fusebox in a small community project I'm planning right now. If nothing else, I'll be able to point to that project as my experience with frameworks. But I suspect I'll actually be converted to the framework crowd, once I get my hands dirty.
Yeah, I am not a huge framework person, but I also feel that I do use some OOP stuff - it's just not the OOP that is involved with MVC and all that jazz. I want to use what's good... i just have not been able to wrap my head around all that stuff yet.
I think / hope 2007 is my year to blossom.