By Peter Bell

Snippets: Creating and Loading a Base Business Object

I have looked at the code to create an iterating business object, as well as the code to display it.

This post looks at how to create and load such an object. Basically you just use a createobject() and then the loadQuery() method of the object, parameterized with a recordset returned from a DAO (my DAO's handle bulk operations as well as single records).

As an example, here is a very naive getbyUniqueAttribute() method from a base service object that allows you to create, load and return a bean using any unique attribute and a comma delimited list of one or more values. Please note that this is not a "safe" function, so it is a private method and just allows more specific methods such as getbyID() (another base method) or getbySKU() (a product specific method) or getbyEmail() (a user specific method) . . .

At the moment I have my bean creation within the method. Obviously I'll refactor that either to a service specific bean factory that will inherit from a base bean factory. I haven't decided whether the factory needs to be a different bean (which would make sense from a "do one thing and do it well" perspective) or just a different method within the service object (which seems pragmatic for now as it only has a single method) so I'll just leave it where it is for now and see where the code smells take me over time.

Please also note the "inappropriate" use of application scope. In my use case, I know application scope is going to be there, I know I'll always use the "ComponentRoot" property and I don't need to reuse my components in distinct applications - I use a software product line approach. So I'm happy to "break the rules" until I see a problem within my use case and then I'll refactor as required.

A general comment that this brings up is that these are not samples of "great code", but working examples of some interesting patterns that seem to be doing well in applications I'm building, but which are definitely a work in progress. If you want to see good code, check out the "real" frameworks available out there!!!

Other comments: Variable.ObjectName is set by the child class, so you would call ProductService.get() and the variables.ObjectName would be "Product". Please also note the use of an "any" returntype. This just allows this base method to return any kind of object (product, user, article, etc.). I've got a feeling I should replace this with something else that generically describes an object in CF, but it hasn't been a pain point, so I haven't bothered to Google it yet.

Oh, and before anyone mentions it, yes I have my DAO in REQUEST SCOPE!!! Am I crazy? Well, probably. But in my own defense, I was debugging, in a hurry, wanted everything in request scope (so changes would show up without having to call an appreset variable or something similar) and I chose a unique name of Request.Object["objectname"] so I can refactor to ColdSpring using a simple "find" and adding in a few cfarguments when I get a couple of hours to load up and implement the framework. I said this was a work in progress!!!

<cffunction name="getbyUniqueAttribute" returntype="any" access="private" output="false" hint="I return a single loaded iterating business object with data for each of the attribute values provided in the attribute value list - in the order of the values in the list.">
   <cfargument name="Attribute" type="string" required="yes" hint="I am the required name of the unique attribute that the Attribute Value List are associated to. E.g. ID, Email or SKU.">
   <cfargument name="AttributeValueList" type="string" required="yes" hint="I am the required list of 1 or more values for the objects to return. E.g. 2,6,1 or test@test.com,bill@company.com">
   <cfscript>
      var Local = StructNew();
      // Create a business object
      Local.Object = CreateObject("component","#APPLICATION.ComponentRoot#.com.custom.model.#variables.objectname#.#variables.objectname#Object").Init();
      // Get a query from the DAO with the data
      Local.Recordset = Request.Object[variables.ObjectName & "DAO"].getbyUniqueAttribute(Attribute,arguments.AttributeValueList);
      // Load the query into the object
      Local.Object.loadQuery(Local.Recordset);
   </cfscript>
   <cfreturn Local.Object>
</cffunction>

Comments
BlogCFC was created by Raymond Camden. This blog is running version 5.005.