By Peter Bell

IBO Sample Code

I created a project for the Iterating Business Object some time back but never got a chance to upload code as my iterating business object is firmly embedded into my in-house framework so it doesn't really exist as its own bean.

After some pressure I finally uploaded a ZIP file to the project. It is just a single cfc with all of the key methods and I haven't had a chance to test it on its own, but it should give a pretty good idea of my implementation for anyone who wants to do something like this.

Two design decisions that are most arguable (IMO):

  • There is a question as to whether a business object should really know how to iterate itself - it might make more sense to have a separate iterator or at least to compose the iterator. While true in practice, when you try to implement this (without actually creating an array of beans) the implementation gets a little messy. I think a cogent argument could be made for decorating business objects with an iterator instead of having base business object methods for iteration, but this is working for me, so I'm not in a rush to change it purely for architectural purity (although I may play with that fairly soon).
  • The next() iterator method is both a command and a query, incrementing iterator and returning a boolean with a 0 if there isn't a next record. I think there is something to command query separation, but this simplifies my iterator interface allowing for the code snippet below to work, so I'm happy with the hack.

<cfset ObjectList.reset()>
<cfloop condition="#ObjectList.next()#">
#ObjectList.get("Title")#<br />
</cfloop>

Of course, you could argue with the whole generic getter/setter approach as making the API of the bean less explicit, but for my use case there's no way I'm going to generate a bunch of dumb getters and setters to bulk up a code base that human beings really aren't supposed to be looking at most of the time anyway.

Then there is the question of why bother with this at all rather than just a collection of actual business objects. Answer is instantiation costs for displaying lists and by having a performant approach to instantiation what appears to be a collection of business objects it means I can ALWAYS use the same approach rather than having to start with queries and then refactor my views and other code as I find a business object has more calculated properties than I realized.

Thoughts?

Comments
Pete, I have no problem the fact that Next() is both a command and query method. In fact, I would argue that this keeps it consistent with ColdFusion query loops. Think about the query loop:

<cfloop query="qData">
#qData.value#
</cfloop>

Here, the CFLoop tag is both a conditional command (move to next row) and a query (*stores* current row data into qData object). Basically, your IBO follows in the footsteps of the query loop.
# Posted By Ben Nadel | 8/13/07 5:54 PM
Thanks - that makes me feel better!
# Posted By Peter Bell | 8/13/07 7:41 PM
Peter,

I've embraced the concept of an IBO for some time. For specific use cases, it's a great a approach. My own Recordset (http://recordset.riaforge.org/) implementation has a similar API with regard to next() being both a command and query. The major difference with Recordset is the absence of generic getter and setter methods.
# Posted By Paul Marcotte | 8/14/07 12:51 PM
Hi Peter
Not to sound like one of the people that egged you into uploading your iterator but I am looking forward to giving it a try. Today was the 1st time I came across a decent reason to use a business object in a real project and made me think to check in on this topic of yours. Anyway, won't be using your cfc for a while as this job will be done by the time I figure out how to use it but I like the idea...might have to break out my Java books :) I'll go back to your other posts...anyway, thanks 4 releasing some code ;)
# Posted By Devon Burriss | 8/14/07 2:56 PM
NP at all, principle should be pretty easy though. Basically you get a query from the db, use the loadquery method, then reset() and iterate over the bean. Let me blog some sample code. If it takes more than an hour to get you're reading too much into it! (although to be fair I've done plenty of jobs where i couldn't afford to spend an extra hour . . .).
# Posted By Peter Bell | 8/14/07 3:04 PM
@Devon and Peter

When I first read about the concept of an IBO I thought it would take a while to comprehend. Consequently I put it off initially, only to realize that when I did pursue it again it only took 20 minutes to understand and implement.
# Posted By Aaron Roberson | 8/15/07 1:43 AM
Hey Pete,

I've been playing with the concept of an IBO over the last week or so and thus far I'm really liking it. I do have a question for you. Are you using the IBO for form pages? A single 'row' representing the form data? I really like the idea of standard get/set methods regardless of how the data is used (form vs list), but I think behavior is different between the two (at least in some use cases).

I'm thinking about mixing in either a bean (form pages) or iterator (listings, etc) implementation into standard objects so they can take on either (or both for that matter) implementations.

Any thoughts on this? I have some messy code I can send you if you'd like to see an example to help clarify.
# Posted By Andrew | 9/6/07 11:01 AM
I use the IBO for pretty much everything. The generic getters and setters work well for forms as well as anything else. Only different is I decorate the core IBO with methods to displayField() and displayCaption() to keep my form displays very simple. It also means that if I have a form for editing n-instances, it'll work out of the box without me having to write additional code as the IBO is designed to handle n-records (where n can be 1 or more than one).

Glad you're enjoying it!
# Posted By Peter Bell | 9/6/07 11:09 AM
Thanks for the reply Peter!

I'm having a little trouble on form vs listing pages. Shouldn't a form have 1 to n instances and a listing page have 0 to n instances? I think thats where my biggest problem lies.

With a form page, I want the IBO to be populated with at least 1 instance. It might be an empty instance where the properties hold default values, but it still exists (i.e. record count is 1 or more)

However on listing pages, where I'm using the IBO as an iterator, I don't want it to contain any records upon creation. I want it to be empty.

Does this come up for you? or am I thinking to narrowly? I might still be stuck on "form pages use beans, listing pages use queries"
# Posted By Andrew | 9/6/07 12:00 PM
While it is true that in a form an IBO will usually contain 1 instance and occasionally n instances, both are valid values within the range of 0..n. For instance, if you have a list that you KNOW will always have between 7 and 21 records, that doesn't mean you can't use an IBO because IBO is 0..n and the list will never have less than 7 records. Similarly you can use an IBO for a form every if the form always has a single record - you don't HAVE to if your form will always have a single record, but it works fine for me and keeps the architecture simple and flexible.
# Posted By Peter Bell | 9/6/07 12:06 PM
Gotcha, and I agree with you.

I think I will try to populate the IBO based on its use, perhaps in a factory of sorts. If I know it must have exactly 1 and always one, I can create that instance when I ask for the IBO. Thanks for your input Peter, I appreciate all of your replies.
# Posted By Andrew | 9/6/07 12:22 PM
Hi Peter,

I have been looking at your IBO object on RIA and wondered what the class properties were. I understand class level properties/funcs etc in java, but dont understand how they fit in here.
Do you use them to associate other properties with the IBO e.g. totalNumberOfRecords say if you had an IBO that contained only a paged set of data and the web page wanted to display total records count as well as the specific paged set?

Also I notice that you havent provided getters for the properties lists provided in the constructor i.e. allowing you to iterate over the properties of the object and set or get them without knowing what they are before hand- do you find you dont need this? I suppose even if you provided this there are still those properties that are actual defined methods which wouldnt be accounted for.

Cheers for you hard work
# Posted By Ade | 10/13/07 9:10 AM
Hi There,

You've pretty much got it. There are some properties I found I wanted my IBO to expose that weren't specific to a single incstance (object), but rather to a general class. For instance, lets say you just got an IBO, but it's a generic admin list screen so you don't even know what object types are in the IBO (are they articles? pages? users?). If the service code that created the IBO did an IBO.ClassSet("Title", "Article"); then your view code could just say #IBO.ClassGet("Title")# Administrator. I find there is a bunch of such information that I end up needing to pass around with a rich IBO if I use very generic templates, and the class properties allows me to do that.
# Posted By Peter Bell | 10/13/07 10:08 AM
BlogCFC was created by Raymond Camden. This blog is running version 5.005.