Remote Synthesis
Search my blog:
Viewing By Entry / Main
Sep 12, 2008

CFArgument: The Iterating Business Object

This is the first entry in a planned series of discussion between myself and Peter Bell where we will discuss hot topics in the ColdFusion community (thus the label CFArgument). Today's topic is Peter's own iterating business object, which has been the source of some discussion lately.

Peter Bell:
An Iterating Business Object is a ColdFusion specific design pattern allowing you to write OO code without worrying about the performance overhead of creating arrays of objects in ColdFusion. In ColdFusion, if you're not using an IBO, you're not really writing OO code.

Brian Rinaldi:
An IBO is a workaround to a ColdFusion specific performance issue, and that is the high cost of object instantiation. That issue has improved in ColdFusion 8, but when dealing in large sets of objects the cost can still be a killer. That doesn't mean that the IBO isn't a reasonable workaround, but without this issue the IBO has no intrinsic value. For example, if they fix performance on object creation in ColdFusion 9, the IBO ceases to be useful.

Peter Bell:
I agree that if object instantiation was faster, the IBO wouldn't be necessary. I certainly wouldn't propose using an IBO in Java or Groovy, but what I think is pernicious is the frequent use of Gateway objects that return recordsets rather than objects. Many CF developers will return a single record as an object and a collection of records as a recordset. To me that makes no sense. If you have a User object and you want to have a getAge() that calculates the age from the date of birth, that method is equally necessary (and should therefore be equally available) whether you're looking at one user or a hundred. Same for products with a getDiscountedPrice() or other potentially complex calculations.

I would argue that the lack of consistent use of IBOs means that many developers end up with pseudo-OO code which has all of the costs of OO programming (more files, more typing) but few of the benefits (encapsulating data and associated methods into objects) because they can't encapsulate custom getter logic in their beans since they are using recordsets for displaying collections of objects instead of an IBO. They are doing this because of the fear of the cost of the object instantiation. That to me is the problem with not using an IBO.

Brian Rinaldi:
We agree that using straight query results isn't optimal in all cases. I also agree that the IBO is a reasonable response, even though it does force you to repeat yourself a bit, putting logic in both the bean and the IBO. It would seem to me there are potential solutions to this that don't require code repetition. Also, one can argue that in many cases, simple recordset data meets the requirements. Nonetheless, neither case is optimal for remoting with Flex.

Peter Bell:
The thing I love about the IBO is that you don't need to repeat yourself at all. The way I use the pattern a business object is simply a collection of n-beans where n=1. At first I thought this was a little hacky (let's be frank - the IBO *is* a little hacky - violating the single responsibility principle if nothing else, by duct taping an iterator onto your business objects), but having used it in a bunch of projects, I find that it works really well.

With an IBO, I can load up one record and treat it as a business object or n-records and use it as an iterator. Perhaps the most useful way of thinking of an IBO is as a base class that your business objects can extend to allow your custom getter, setter and validation logic to be written as if you were writing a regular business object in Java. However, instead of creating an array of such objects plus a separate iterator, with the few base methods in an IBO, you simply load up an array, recordset, struct or collection of value lists into the IBO and then get all of the benefits of an array of business objects with an iterator - with almost none of the instantiation cost.

The only cost is the slightly bitter taste at having to stick iterator logic in a base business object which I agree is hacky. But it just works so darned well!

There were two other points you made as well that I'd like to respond to briefly.
If you genuinely have recordsets with no custom getter logic, I agree that an IBO might be overkill. My problem is that my simple business objects often get more complex over time so I have found for my use case using IBOs consistently gives me the room to expand and no real extra complexity upfront. I'd much rather use IBO's for everything or nothing than have to try to decide on a business object by business object basis which one was likely to become complex over time.

As for Flex, the trick would be to have a simple routine that would loop through all of the getters of an IBO for each instance, creating a collection of named structs. That gives the strongly typed VO's in Flex without the cost of creating an array of objects. I haven't had a need to write this yet, but it'd be pretty simple to add an asFlexVOs() method to the IBO - whether it was done in the IBO or handled by a composed object.

Brian Rinaldi:
Well, I think we can both agree that the best solution to this issue would be for Adobe to remove the high cost of object instantiation. I think things like the IBO, while useful to solve a problem, continue to solidify the idea that ColdFusion isn't designed for real OO development.

Peter Bell:
I agree. And there are some problems that an IBO doesn't solve. For example, very few ColdFusion applications have a truly rich object model with things like an Address value object for handling Billing and Shipping addresses composed within an Order object because the cost of object instantiation makes it impractical. It is interesting to see that some CF developers are moving to Groovy for their model and others are looking at other implementations such as Railo where object instantiation appears to be much faster. Hopefully amongst all of the great new features in CF 9 there will be some engineering time left over to address the issue and make ColdFusion a compelling language for creating dynamically typed OO applications on the JVM.

Comments
Ben Nadel
I like the back and forth, but I have a problem with Brian's statement:

"That doesn't mean that the IBO isn't a reasonable workaround, but without this issue the IBO has no intrinsic value. For example, if they fix performance on object creation in ColdFusion 9, the IBO ceases to be useful."

I think this same thing could be said about many design patterns. A design pattern is a proven solution to a problem - but, if you take away the problem, the solution ceases to be useful; this is not IBO specific.


Brian Rinaldi
@Ben - I sort of agree with you except that this is a solution (workaround is a better term) for a "flaw" in the underlying software. Somehow I feel that it is pretty loose with the term design pattern to qualify workarounds as design patterns (though I may be wrong about that)


Peter Bell
@Ben/Brian, It's an interesting discussion. There was some noise a few months back on the blogosphere arguing that most java design patterns are simple reflections of flaws in the language design when compared to Ruby :-)

Design patterns cover a wide range of types of solutions from something really specific like the IBO to something *really* generic like Model-View-Controller. At the end of the day, if it's a useful solution to a recurring problem, I don't think it really matters. If you have the problem, the solution is available for your use. I wouldn't use MVC for a headless signal processing application and I wouldn't use Singletons in Ruby. Doesn't mean they aren't both useful when building web apps in ColdFusion.


tony petruzzi
I agree with brian when he saids that an IBO is a workaround to the poor performance of object creation in cf and that problem needs to be addressed. let's face facts, object creation has gotten better since cf6 but it's light years behind other languages like ruby.

i do agree with peter when he states its wrong how most people will return an object for a single record and a query result for a collection of records (currently cfwheels does this). i to don't see the benefit in doing this, but understand that it's for performance reasons.


Josh Nathanson
Is it not true that the object instantiation penalty (hereafter referred to as OIP) is the result of the "webby-ness" of ColdFusion? In other words, the penalty is there because each function in ColdFusion gets compiled into its own class file, and I'd imagine they chose this architecture because it improves speed in other non-OO areas? Thus it was a compromise in the early implementations of the language that has stuck around through later versions.

If the underlying architecture is to blame, we may never see the OIP completely done away with, unless they do a major rewrite of CF, so the IBO may be the only lasting solution to the problem.


Alan Livie
I don't really care. With an IBO I have a unit-testable bit of logic I never had before with cfquery output= etc

I also have a clean separation of View and Model so I'm happy.

I began OO with Brians CFC Genearator and although it has been a great help it has also caused OO truble in the sense that I still thought of OO as starting at the db level.

Once you distance yourself from the Service -> DAO / Gaeway view and concentrate on what an object should DO and how it communicates with other objects you start 'getting' OO .. I'm a novice but enjoying the ride!


Brian Rinaldi
As I've said many times, the generator isn't intended to teach anyone OO. Nonetheless, it can help get grunt work out of the way on the projects where you inherit a db (which in my experience is most).


Sam Mawby
There are different types of design pattern and certainly some relate directly to overcoming an issue associated with a language (or type of). One of the reasons for J2EE specific patterns.

There is a very good argument for people to provide tried and tested solutions to common Coldfusion problems. The fact that Peter discusses the idea of an IBO is good, although people need to realise when a pattern is appropriate and when it is not. People shouldn't for example start to think that a Coldfusion recordset is a bad data type to use. Sometimes it works perfectly.

I would also like to make one new point too. If there is something that Coldfusion really doesn't do well then find an alternative. Although the solution might involve a different way of approaching the problem in Coldfusion, it could just as easily be to use Java, .Net, the database server, or the server (windows or whatever).


Write your comment



(it will not be displayed)