IBO Sample Code
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.
<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?



<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.
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.
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 ;)
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.
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.
Glad you're enjoying it!
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"
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.
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
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.