The Dopefly Tech Blog

<< The Dopefly Tech Blog Main page

The Easy Super-Bean

posted under category: ColdFusion on June 9, 2009 at 1:00 am by MrNate

With CF being OO enough, beans can have a super-type, a common base that all beans share, like genetics for business objects. It's easy to make one.

<cfcomponent extends="superbean">
But what do we put in there?

My biggest hatred about beans is the getters and setters. It's a lot of typing. If you have snippets, that helps. If you have a bean generator, that's better. It's also a big problem if you have to change them (think: adding logging, validation, etc.), or worse re-generate after you've added custom code. So the way to fix the whole lot of these is employing ColdFusion 8's OnMissingMethod.

I know we've seen it before. My favorite probably comes from Kevin Roche's Abstract Object post. That's basically what I'm playing with.

In my playing around, I've got a base bean with an onMissingMethod defined that will catch getters and setters. Here's an illustration:

Illustration of bean hierarchy - generic base bean with concrete type

The _genericGet() and _genericSet() methods were added so that any extending bean can, say, overwrite just the setter for all the properties in a bean or a parent type of another bean. In fact, I would recommend that overriding coders "decorate" the _generic methods, calling the super-action before or after any custom operations.

Benefits of this design, other than the obvious lack of need to type getters and setters, is that the concrete bean can hold any property, plus, I can rename the getters and setters to obj.Name("Nathan").name(); which would return Nathan - somewhat of a jQuery style trick. Another cool thing is that if you wanted to create your own getter or setter for a property, the _generic methods will search for your function and call that instead.

To illustrate:

(in component user, extends BasicGenericBean)
function getName(){return "Bob"}

(Outside, calling methods on the object)
user.setName("Nathan");
user.getName(); // returns Bob

Also, I added an init() constructor method that will populate the bean's properties with any arguments passed in.

Taking the design further, I wanted to let the developer specify what properties the bean has via the cfproperty tag.

<cfcomponent extends="GenericBean">
<cfproperty name="Name" type="string" />
</cfcomponent>

user.setName("Nathan");
user.setNumberOfGoats(16); // throws error: NumberOfGoats does not exist in User.

Then, I thought about adding some optional subtypes for the generic bean. What if I want to track the history of changes to the bean, so it would be easier to do a database update? What if I wanted to put the database update right in there, in a very generic way? This is completely possible.

Illustration of bean hierarchy - base bean, history tracking bean, database enabled bean, with concrete types

So there's my design, something to play with at least, and maybe base your model on too. Download the files all together in 1 zip with some test front-ends just to see them in action. CF8+ only! Download Nathan's Super Beans.


No Comments Posted Yet! - Too old to comment!