Visit the ColdFusionProNews Directory
Beginners
Installation, Coding Techniques, Data Structures...
CF Powered Sites
Stores, Directories, Universities...
Developers
Developers, Designers, Experts...
E-commerce
Shoes, Food, Music...
Education
Books, Online Resource, Languages...
Expert
LiveChat , CFX XMLParser , User Defined Function Library...
Hosting
Dedicated Servers, Virtual Server, Multi-user...
Intermediate
AutoResize , DataSource Encryption, Guestbook...

Submit your site for FREE

Implementing Railo Effectively As A Developer


By: Raymond Camden

About a week or so ago I attended a presentation on object factories by Rob Gonda.

Object factories were something I had heard about and read about, but didn't quite get. The presentation really helped a lot, and I thought I'd share my thoughts on how I understand this concept, and then quickly show a practical example of how I applied this to the new beta of Canvas.

First lets talk a bit about how a person typically creates a set of components for use within an application. Most folks will (hopefully) create these components in the Application scope so they only have to create it on time. So let's start with a simple onApplicationStart method:

<cffunction name="onApplicationStart" returnType="boolean" output="false">
<cfset application.ship = createObject("component", "cfcs.ship").init("dsn", "arrayofshipclasses")>
<cfset application.soldier = createObject("component","cfcs.soldier").init("dsn", "arrayofjobs")>
<cfreturn true>
</cffunction>


This application uses 2 CFCs (Ship and Soldier). Each CFC has 2 arguments necessary to initialize them. So far so good. If either of the CFCs change then it isn't a big deal.

Where things get complex is when you begin to add a few more CFCs to the mix:

<cffunction name="onApplicationStart" returnType="boolean" output="false">
<cfset application.ship = createObject("component", "cfcs.ship").init("dsn", "arrayofshipclasses")>
<cfset application.soldier = createObject("component","cfcs.soldier").init("dsn", "arrayofjobs")>
<cfset application.planet = createObject("component", "cfcs.planet").init("dsn","arrayofplanettypes","maxforgame")>
<cfset application.player = createObject("component", "cfcs.planet").init("dsn","arrayofplayertypes","maxforgame")>
<cfset application.ruleset = createObject("component", "cfcs.ruleset").init("dsn")>
<cfreturn true>
</cffunction>


So that isn't terribly bad. It's a bit messy, but ok. But let me throw a monkey wrench into the process. What if....

* Ship.cfc needs it's own planet, solder, and ruleset cfc?

* Solder.cfc needs a copy of ruleset

* Planet.cfc needs a copy of soldier, ruleset

* Player.cfc needs a copy of ship,solder,planet, and ruleset.

Um, so I can handle that. Each of the CFCs above, in their init methods, will simply have their own creatObjects. While I used to have 5 CFCs cached I now have 15. Well, RAM is cheap so I'm not too worried, and it's not like the CFCs take up a lot of RAM anyway. But what is more troublesome is the thought of change. If the required attributes for ruleset change, now I have to update multiple CFCs as well as Application.cfc. And guess what happens if I forget?

So the first thing a factory can help me out with is simply handling creating objects for me. Let's build a super simple factory. Consider the code below:

<cfcomponent output="false">

<cffunction name="getComponent" returnType="any" output="false">
  <cfargument name="name" type="string" required="true">

  <cfswitch expression="name">

   <cfcase value="ship">
    <cfreturn createObject("component", "cfcs.ship").init("dsn", "arrayofshipclasses")>
   </cfcase>

   <cfcase value="soldier">
    <cfreturn createObject("component","cfcs.soldier").init("dsn", "arrayofjobs")>
   </cfcase>

   <cfcase value="planet">
    <cfreturn createObject("component", "cfcs.planet").init("dsn","arrayofplanettypes","maxforgame")>
   </cfcase>

   <cfcase value="player">
    <cfreturn createObject("component", "cfcs.planet").init("dsn","arrayofplayertypes","maxforgame")>
   </cfcase>

   <cfcase value="ruleset">
    <cfreturn createObject("component", "cfcs.ruleset").init("dsn")>
   </cfcase>

   <cfdefaultcase>
    <cfthrow message="#arguments.name# is not a recognized component.">
   </cfdefaultcase>

  </cfswitch>

</cffunction>

</cfcomponent>


All I've done is created a function that - based on a name passed in, will return an instance of the component. Where things really get nice then is back in the Application.cfc file. Look at the change:

<cffunction name="onApplicationStart" returnType="boolean" output="false">
<cfset application.factory = createOject("component", "cfcs.factory")>
<cfset application.ship = application.factory.getComponent("ship")>
<cfset application.soldier = application.factory.getComponent("soldier")>
<cfset application.planet = application.factory.getComponent("planet")>
<cfset application.player = application.factory.getComponent("player")>
<cfset application.ruleset = application.factory.getComponent("ruleset")>
<cfreturn true>
</cffunction>


Wow - a lot simpler, right? And if a component's needs change - I can edit the factory and not change anything else in Application.cfc.

What this doesn't yet fix are two issues: How do my CFCs, which each needs instances of each other, get their instances? Sure they can also use application.factory, but that breaks encapsulation. Secondly - my factory makes a new instance of a CFC for every request. Is there anyway to make that nicer?

To be continued...

Comments

Tag: ,

Add to Del.icio.us | Digg | Reddit | Furl

About The Author

Raymond Camden, ray@camdenfamily.com
http://ray.camdenfamily.com

Raymond Camden is Vice President of Technology for roundpeg, Inc. A long time ColdFusion user, Raymond has worked on numerous ColdFusion books and is the creator of many of the most popular ColdFusion community web sites. He is an Adobe Community Expert, user group manager, and the proud father of three little bundles of joy.