The amazing adventures of Doug Hughes

A disclaimer up front – I am not sure if this pattern is specific to ColdFusion, but I have never seen it in another object oriented language before.

A design pattern is a template solution for how to address a common issue in object oriented development. So here is a problem. In an ideal object oriented system, you are dealing with a server that never goes down and has unlimited memory. Therefore, when your application has five thousand user accounts, you just have five thousand little user business objects floating around in memory waiting to be used. In reality this is not really practical.

So here is the dilemma – you want to stay true to object oriented practices and benefit from the use of business objects, but trying to create a business object for every user record in the database just to display a list of users is not really practical. At the very least, the current request will be very slow and at worst, if it is a common request, you could bring the server down trying to do that kind of object initialization and garbage collection.

Some time back, I was introduced to the concept of an iterating business object (IBO) by Peter Bell. Simply put, the IBO is a business object with all of the desirable object oriented characteristics – getter and setter functions, data encapsulation, etc. However, instead of just containing the data for a single record, it can contain one or more records. Therefore, when you need to deal with a collection of user records, instead of creating a new business object for each user record, you can create one single user IBO instance and load all of the user records into the one object instance.

Internal to the business object, each record is now stored as a structure within an array. The business object maintains a pointer to the “current” record and has a variety of infrastructure functions to manage this array of structures. These functions include:

  • add() – this function adds a new record (array element) to the business object and updates the current record pointer to point to the new record, leaving it ready to be populated.
  • asQuery() – this function takes the internal array of structures and converts it to a ColdFusion query object which is returned. This is useful for serializing the result to JSON or for other display purposes.
  • asStruct() – this function returns the current record as a structure. While returning records as structures looses the benefits of the object oriented business object, it can still be useful on occasion.
  • currentRecord() – simply returns the current record number being pointed to by the record pointer.
  • get( propertyName ) – a generic getter style function which will retrieve the value associated with the specified property for the current record. By using onMissingMethod(), this function can easily respond to the traditional getPropertyName() function call as well.
  • loadQuery( queryObj ) – accepts a ColdFusion query object and loads it into the iterating business object. This is useful when using a DAO to quickly load multiple records into a business object at one time.
  • loadStruct( structObj ) – accepts a ColdFusion structure and loads it into the current record of the iterating business object. This is useful for loading data like form submissions into a business object in that you can pass the entire form scope into the function at one time.
  • next() – advances the internal record pointer to the next record. This function is very useful in looping through an iterating business object.
  • recordCount() – returns the total number of records in the iterating business object.
  • reset() – resets the current record pointer to point to the 0 record. This in combination with the next() function makes it very easy to loop through an iterating business object.
  • set( propertyName, propertyValue ) – a generic setter style function which will set the specified value for the specified property for the current record. Again, by using onMissingMethod(), this function can easily respond to the traditional setPropertyName( value ) function call as well.

In another post, I will show some examples of how we have been using this functionality in our latest project as well as how we have encapsulated this functionality into a base object that all of our business objects extend, making it very simple to add new business objects to the system.

If you would like to learn more about object oriented development, and more specifically object oriented development with Model Glue, we have training opportunities that are coming up next month with early registration ending Wednesday. In addition, feel free to contact us to see how we can help with your next project.

Comments on: "IBO: A ColdFusion Design Pattern" (35)

  1. Steve 'Cutter' Blades said:

    Nice. Where do I download it to look over the code and try it out?

    Like

  2. This sounds similar to the ADO recordset concept.

    Like

  3. @Jeff, Nice posting – thanks!

    @Cutter, there is an ibo.riaforge.org which has some sample code. You might also want to search for ibo on my blog.

    @Eric, ADO recordset (as far as I know) is more like a ColdFusion query object, designed to provide access to data from a db query. The ibo is more like a combination business object and iterator, so if you had a user ibo you might have a custom getAge() method that’d calculate and return the users age based on a date of birth that was stored in the db.

    Like

  4. As I have gotten a bit into OOP, the IBO has been of interest to me. I have talked to Peter about it, but one thing has always confused me – if you have an “object” that has an aggregated object (ex. Employee has a Department object), how do you handle the:

    .get( “Department” )

    Do you have to turn around an hit the database for each call for that property for each record in the IBO? Or is it cached somehow in the IBO itself?

    Like

  5. Jeff Chastain said:

    @Ben, I have not seen a posting on this before, so maybe that will be next in line.

    For us, when we have related objects, we have used a ‘lazy-load’ style set of code for returning the object just as you would with any other business object. Say for example you have your Employee. A property of the Employee is probably a Department_Id (at least in the database). So, when I ‘get’ my Employee IBO instance, there will be a custom getter function on it for ‘getDepartment()’. There won’t actually be a Department instance created yet as that could lead to disastrous chaining effects. Then, when the Employee.getDepartment() function is called, it utilizes the internally stored department_id value to retrieve the Department instance (via service/DAO objects) and return it. Once the Department object has been instantiated the first time, it can be cached within the Employee object although you run into issues with it possibly becoming stale and out of date.

    Hopefully this is clearer than it sounds and I will add this to my to-do to put together some actual code.

    Like

  6. @Ben, I use a generic getAssociated() method. So, if a ProductCategory has-many Products, my display code would be something like:

    ProductList = Category.getAssociated(“Products”)

    #Category.get(“TItle”)#

    cfloop condition=”#ProductList.next()#”
    #ProductList.get(“Title”)#
    #ProductList.get(“Price”)#
    /cfloop

    getAssociated() calls the appropriate associated service class, so in this case it calls ProductService.getAssociated() that returns another IBO with a collection of products.

    Make any sense?!

    Like

  7. My concern is with a list like this:

    #objIBO.GetName()# – #objIBO.GetDepartment().GetName()#

    Imagine for a second that we have a custom tag that allows us to easily loop over IBOs. Now, we are looping over a list of employees and for each employee, we want to output the employee name and their department (not an uncommon list I would think).

    With lazy loading, this would force us to make N+1 calls to the database for that list (1 for the record set plus N for each department).

    Now, if this were a standard query, obviously, we would just join the department to the employee and output it simply – one query, one loop – piece of cake. Is there a simple way to mimic this functionality without additional calls to the DB?

    I am not trying to argue against the IBO pattern – I think it is very cool. This one point has always just confused me and I didn’t know if there was a clever and clean way to solve it.

    Like

  8. Jeff Chastain said:

    @Peter, I like how you have made the related object getter generic like that. You could still use the onMissingMethod function to make getDepartments() work the same as getName() works.

    @Ben, that is where the ‘caching’ comes in with our current approach. The first time you call getDepartment(), the getter function will check to see if the Department instance is already loaded and if not, use the department_id along with a service/dao to retrieve it. Then, the second time it is called, it can just pull the cached instance out and return it, bypassing the extra call to the database. Or, even simpler would be to have an intermediate variable in your code like this …

    #Employee.getName()# – #Department.getName()#

    As with everything, there are always multiple ways to skin the cat.

    Like

  9. @Ben, The solution I use for that is to allow dot notation to ask for properties of associated has-one objects.

    When I load a list of employees, I can ask for a property name list such as FirstName,LastName,Title,Department.Name and it’ll auto generate a single query with a left outer join to the department table so a single query will return all of the fields that I want and I don’t have to write SQL.

    Like

  10. @Jeff, Agreed re: oMM(). Caching approach you use also makes sense. As you said – multiple ways to fleece the feline ๐Ÿ™‚

    Like

  11. @Jeff,

    I am not sure that caching would make sense here – I am not calling the same department twice – I am getting the name of the department for each Employee (each one might be in its own department). Or am I missing something?

    @Peter,

    That’s a really interesting approach. To get around the need to require a different IBO for every different use case, I assume then that your IBO has some sort of “core” column list – the base employee data – and then can be expanded to use dot notation for number of different query structures.

    For example, one query might have an employee listed with their department while another might have each employee listed next to the emergency contact /relationship (ie. Amy, Wife, 123-555-1434).

    For one IBO, getting Department.Name would work, but for the latter, it would throw an error or something?

    Like

  12. @Ben, Caching does make sense as you’re not only having one user request so the first page would indeed have a n+1 query problem, but future requests would pull from the cache making it much faster.

    Re: the relationships, it’s a little more complex than that. I basically have metadata for each business object. One of the elements of that describes any of the has-one and has-many object relationships and my little data mapper uses that metadata to handle valid dot notation properties and to join the appropriate tables. I actually have an article in te next FAQU on how this works which gives a simplified idea of what I’m doing.

    Like

  13. @Peter,

    I look forward to the FAQu article ๐Ÿ™‚ I don’t quite understand the meta data for the BO concept – which are you creating first – the query object or the IBO? I assume the query since the IBO has the method:

    loadQuery( queryObj )

    Are you saying that you use the meta data to build the actual SQL query string?

    You don’t have to explain – just put it in the FAQu ๐Ÿ™‚

    Like

  14. @Ben, yeah, the metadata is used to build up the SQL query – it also handles table aliases, column aliases, default object filters (e.g. an Employee is a record in the User table where Employee = 1) and so on.

    My DAO gets with a Datamapper.cfc that generates the SQL, the DAO then returns a recordset which the service class (which called the DAO) encapsulates within an ibo.

    Like

  15. IBO is pretty ColdFusion specific. It’s only needed because CF performs so poorly at object instantiation. Any real OO language doesn’t have this problem, so it’s not a big deal to inflate recordsets into arrays of objects. Which is why you have things like Hibernate, SQLAlchemy, Rails, etc, all of which are devoid of IBO-like constructs.

    In other words, IBO is a “my platform [CF] sucks, let’s try and fix it with application code pattern”, not a “design pattern”.

    Like

  16. @Barney,

    I am not sure if you want to think about it that way. Yes, these are done because arrays of objects is slow in CF; however, you could also look at it as an optimization that leverages the ColdFusion query object. By using an underlying query object, it gives us the ability to optimize our SQL statements and only pull back the values that we need. So, imagine we have a a contact that has 20 properties, but for a list, we only need ID and name, our underlying query can be optimized to only pull back the needed data while still providing some of the OOP goodness.

    So, on one hand, its a workaround for instantiation issues… and on the other hand, it’s a leveraging of the efficiency that is the ColdFusion query object.

    Like

  17. @Ben,

    I’ll buy part of that argument if you have an incredibly wide object and/or your DB server is on a very slow network. But if you’ve only got, say, 50 non-LOB fields in your table, who cares? I rarely show more than 25 or so records per page, but say you show a list of 100 users. With 50 varchar(255) fields in your table, that’s still only a MB of data. And I think that’s an exceptionally inefficient (and unlikely) case.

    That being said, it’s still not an argument for IBO. Spring (the Java one) provides the concept of mappers. You write a SQL query and then apply a mapper to it, which turns each row into an object. That’s exactly the use case you’re discussing, but in a language with acceptable object creation performance (Java, in this case), you still create an object per row. A basic mapper might look like this (psuedocode that will hopefully not get drastically reformatted):

    class myMapper {

    Object map(RowSet rs) {
    User u = new User();
    u.id = rs.getString(“id”);
    u.name = rs.getString(“name”);
    return u
    }

    }

    The Spring machinery calls this method once per row, advancing the internal pointer of the rowset between each invocation. It assembles the results into a java.util.List, and returns that to the application.

    So while your argument is valid for not using an Entity-level persistence framework (Hibernate, etc.) in every case, it’s not an argument for IBO excepting as a workaroud for CF’s object instantiation issues.

    Like

  18. @Barney,

    The idea of a mapper is interesting. I acutally created a IBO one time (very simple one) that contained an actual instance of the target business object. Every time you moved to a new row, it would reset the business object and then populate it with the current row’s data.

    Again, a workaround, but I think this is in the same spirit of the mapper.

    … but you are right, these are really all workarounds, not necessarily arguments FOR.

    Like

  19. @Ben,

    It’s not in the spirit of a mapper at all. With IBO, you can’t maintain a reference to any of the objects, because there is only one object that changes state. With a mapper (or entity persistence), each object is totally distinct from all others. One use case would be maintaining a reference to the previous row as you loop for one-back comparisons (think computing intervals between log entries or something).

    IBO is totally orthagonal to the whole concept of OO programming. It’s 100% kludge. CF can’t support that style of programming, so why try to force it and absorb all these random downsides? It’s not as if looping over a recordset is undesirable.

    Like

  20. Paul Marcotte said:

    Jeff,

    There are a couple of related projects on RIAFroge very similar to IBO. I wrote them early last year, because I had spoken to Peter Bell on many occasions and though his implementation was an interesting solution to slow CFC creation times. My first crack at this was a composite Iterator.

    http://iterator.riaforge.org/

    There’s a lot of overhead using a composite Iterator, so I wrote an inheritance version called Recordset.

    http://recordset.riaforge.org/

    Peter Bell subsequently release the IBO which at the time that I wrote Iterator and Recordset was part of his in-house framework.

    Like

  21. @Barney,

    > IBO is a “my platform [CF] sucks, let’s try and fix it with application code pattern”, not a “design pattern”.

    Now now. Arguably ANY design pattern that needs to be explicitly implemented in a language as opposed to being implicit is a “my language X sucks, let’s fix it with application code pattern” – that’s pretty much what design patterns are. There was a meme going round a while back about “design patterns == language flaws” (I believe it was argued that was why the Java community has so much talk about patterns ๐Ÿ™‚ ).

    Like

  22. @Barney,

    > IBO is totally orthagonal to the whole concept of OO programming.

    Nope

    > It’s 100% kludge.

    Yep ๐Ÿ™‚

    > It’s not as if looping over a recordset is undesirable.

    Really?! So, I have a Product object with a calculated DiscountedPrice based on rich application logic that couldn’t easily be contained in a SQL SP. It also has a bunch of other calculated properties. I need to display products in about twelve different template files. What would you do? Loop over the recordset to create the calculated columns? Replicate your calculation logic in twelve templates? Add some random headless functions to displayProductDiscountedPrice(BasePrice, CoreDiscount, ProductBand)? I’ve tried all three and while the first is the least bad, it becomes an unmaintainable procedural mess as the number of calculated properties per business object (and their dependencies – need to calculate producttotal before discountedtotal, etc) grows.

    One of the core tenets of OO is putting data and associated methods together and that is exactly what an IBO does. Your User IBO has your user methods, your product IBO has your product methods and so on. The only difference is that there is a bit of violation of separation of concerns as each business object is both an object and an iterator. I agree that’s a kludge, but it allows for more maintainable and performant code that the alternatives I’ve seen in the CF world.

    I do agree that if object instantiation wasn’t so costly it would be unnecessary, but I think it facilitates a more OO approach (to solve the specific problem of the maintainability of business logic in custom getters and setters for business object) than would otherwise be possible in CF.

    Like

  23. @Peter,

    There’s a difference between a language not supporting feature X and a language supporting feature X in such a way that it needs to be avoided and synthesized with application code.

    CF does provide object instantiation. It sucks. IBO is about synthesizing that built-in functionality to avoid the costs of using the built-in mechanism.

    Design patterns build atop programming concepts in general, providing a higher-level way of thinking about classes of problems. Yes, certain design patterns are provided for explicitly in certain languages and not others. It makes a compelling case for those richer languages.

    Consider also IBO versus an object pool. Both are attempting to solve the same problem: avoid object instantiation at runtime. However, they’re very different, because the object pool is transparent. The application code still deals strictly with standard objects that are all distinct, have their own lifecycles, etc. There’s no way to tell the pool exists.

    Like

  24. @Barney, I guess this is my day for disagreeing with you – still gonna let me play with your CF Groovy?!

    > I’ll buy part of that argument if you have an incredibly wide object and/or your DB server is on a very slow network. But if you’ve only got, say, 50 non-LOB fields in your table, who cares?

    Here’s a common use case for me. A Page object has a HTML ntext field for static page content edited using a WYSIWYG, an Article has a similar field for a similar reason. So do press releases, newsletters, newsletter articles, product detail descriptions and the like. Try listing 50 product or pages on an admin page and loading up all of the indeterminantly large ntext fields and it’s not a great solution. That said, lazy loading of properties would be another way of solving that problem.

    Like

  25. @Barney,

    OK, I agree that a bad implementation of a feature in a language isn’t a good thing. A also agree an object pool preserves a nicer separation of concerns. That said, a design pattern is “a proven solution to a recurring problem”. I’d suggest that an IBO fits that criteria.

    Like

  26. @Peter

    Regarding your NTEXT columns and lazy loading, that’s exactly what you’d get with Hibernate, for example. And not via manual configuration, by default. You have to explicitly tell it you want LOB columns eagerly loaded. So not an issue with entity persistence. I don’t know if Transfer and such do this or not, or if they only operate at the entity level. And in any case, the mapper solution that I outlined is a better fit, in my opinion.

    For calculated fields, I don’t have a CFML solution that doesn’t require instantiation overhead. It’s the price you pay if you want OO. Or you could use Groovy. ๐Ÿ˜‰ Build your entities in Groovy, and if you don’t want to persist with Hibernate, it’d be trivial to do mapping a la Spring into the objects.

    Thinking a bit more about this, the concept of a helper really doesn’t bother me that much. It’s the “business object” nature that gets applied. Why not have a UserHelper CFC that has a bunch of methods that will only work inside a query loop. Here’s an example:

    select id, utcOffset as value
    from dim_timezones

    #h.getId()#
    #h.getOffset()#
    #h.getRelativeOffset()#

    And then the helper:

    Not really terribly different than IBO in concept: looping over a query, using a single shared object for data access. You get a place to house your computed fields, you avoid object instantiation, you maintain use of normal looping constructs, you can narrow your query as you deep appropriate (avoiding extra fields), etc. Are there benefits of IBO that I’m missing? It seems to cover the bases and avoid the problems at the same time. An no, I’ve never used it in practice; built it out in the process of writing this comment.

    Like

  27. @Peter

    >OK, I agree that a bad implementation of a feature in a language isn’t a good
    > thing. A also agree an object pool preserves a nicer separation of concerns.
    > That said, a design pattern is “a proven solution to a recurring problem”. I’d
    > suggest that an IBO fits that criteria.

    I agree it does fit that criteria, but I think a design pattern is something that is wider reaching than a single implementation of a single language. If you crank the settings on Railo, I think you’d be hard pressed to find IBO relevant there, so it’s reach is not even CFML apps. It’s CFML apps on ColdFusion. Would some way of coding applications to work around a Sun JVM issue (that JRockit or whatever didn’t share) be a design pattern?

    The semantics are fairly irrelevant, though. It’s clearly a widely used way of solving the problem with list views in CFC-based CMFL apps, no question there. And if it gets the job done, it’s useful.

    Like

  28. @Barney,

    Nice to know re: LOBs and hibernate – not had a chance to play with it on a real project.

    As for why you wouldn’t just use Groovy for your model, well I think we’re going to see a lot more of that if the cost of object instantiation in ColdFusion doesn’t alter by an order of magnitude. It works for me and it’s on my list of technologies to play with (despite some rather sniffy comments I’ve heard about the original compiler – a friend who teaches computing in the UK commented that if his students had submitted the original Groovy parser as part of an assignment he’d have failed them!).

    Re: the alternate approach, it is another approach. Personally I find the IBO preferable as I like to treat it as if I have a real business object which just happens to have an iterator built in. I have methods for getting associated objects so for a given category you can Category.getAssociated(“Products”) (or Category.getAssociatedProducts(), you can put your validation logic in, I can inject dependencies using LightWire (such as a Validation helper and the appropriate service classes/DAOs for handling persistence concerns), it is pretty easy to initialize and mock out dependencies for testing – basically it’s the closest I can get to OO in CF and I find it works quite nicely for my use cases. It isn’t exactly the same as having objects, but it’s close enough that I find it much easier to write in an OO style and it’d also be pretty manageable to refactor to an array of objects with an iterator if we got the improvements in CF object instantiation performance I’d like to see.

    Like

  29. This entire article and conversation are very interesting. I have been wrestling with these exact issues latley– trying to reconcile the OO design patterns I find in Java with what I am used to seeing in ColdFusion.

    I feel as though I should be dealing with collections of objects, but no one else is doing it, and worse, it’s impossible to pass an object to the client for Ajax related stuff. ColdFusion cfgrid will only bind to a result set– not an array of objects. So I feel funny creating all these objects on the server just so I can turn them back into a structure or result set to hand them to the browser.

    Like

  30. Robert Gatti said:

    Wow! Interesting read guys, many good points.

    Personally, I’ve never used an IBO but have used the concept of a formatting function inside the service object containing my business logic. One place I have been thinking about using an IBO for is displaying tabular data. That way the common pagination sorting and filtering logic that seems to be duplicated could be packaged up.

    For me, computed columns of any kind (even data formatting) are a great cause to use views in a database. I actually try to abstract all my tables into individual views for flexibility and create detailed views joining related/highly queried tables together. That way if I ever need to modify the logic all the db calls in my dao’s don’t change what their pulling from. Also, I can then just use plain old query objects to display data.

    One thing I do tend to watch when splitting logic up into more objects is db performance. Sometimes I’ve seen more hits to the database which can really slow down a site. It’s not that an extra 2 queries would kill a site but if a request pulls say 2K of db data and the site gets normally 2 requests per second that’s 245M of pull a minute and an extra 240 db hits. Then what happens when it’s high traffic like 5 or 10 requests per second, just saying it adds up.

    Like

  31. Josh Nathanson said:

    We can debate forever about whether the IBO is a design pattern or a hack, but all I know it that it’s allowed me to move forward with using OOP in ColdFusion. Without it I’d be dead in the water, having run up against the Object Instantiation Penalty. With it, I homebrewed my own ORM and now I’m RADding all over the place. Thanks Peter for your brilliant insight.

    @Ben:
    “Do you have to turn around an hit the database for each call for that property for each record in the IBO? Or is it cached somehow in the IBO itself?”

    I use dependency injection for this. In my ORM baseClass I have an inject method. When I get the Employee IBO I might do this:

    The details of how that works are buried in my baseClass, but ultimately you can do this:
    #employee.get(“department”).get(“departmentname”)#
    …and it behaves as expected.

    The nature of the employee’s dependencies are configured in the employee pseudo-constructor, and then handled by the inject method of the baseClass.

    Like

  32. tony petruzzi said:

    @Josh

    would you consider releasing your orm onto riaforge?

    Like

  33. Josh Nathanson said:

    @Tony – I do have plans to release my ORM (tentatively called CFHelium) in the near future. I want to have plenty of documentation of the API available before I do so.

    Like

  34. @Josh – Yeah like we don’t already have enough ORMs! We need some help on Reactor, which suffers greatly from the problem the IBO intends to solve .. maybe you could contribute to that project?

    Like

  35. Marcuski said:

    http://concealer.mybrute.com
    Check out this cool mini fighting game

    Like

Comments are closed.

Tag Cloud

%d bloggers like this: