Exercise List: Integrating The Domain Model Into The ColdFusion Code

Posted November 13, 2007 at 8:35 AM by Ben Nadel

Tags: ColdFusion, Exercise List

Click here to view the current Online Demo

Click here to view / download the current Code Base

Now that I have created my domain model, it's time to take these ColdFusion objects and start integrating them into my procedural code. As a first integration step on my journey into learning object oriented programming in ColdFusion, I am basically taking my domain objects and replacing them into the code were the equivalent queries used to be. The translation, for the most part was pretty easy; there were some functions that I needed to add to the domain models as I went and there was some tweaking, of course, in other areas, but for the most part, it was a fairly basic code replacement.

To start off, I updated my Application.cfc's initialization (OnApplicationStart()) event method to create and cache an instance of the ServiceFactory.cfc. Since the ServiceFactory.cfc creates and stores all of the service objects in the application, this will easily allow me to ensure that only singletons of my service objects exist. This is not a mission critical concept, as there is no data held within the service objects that necessitates being a singleton, but on the other side of that coin, as they have no instance data, there is no need to ever create more than one copy of each of them. Once the ServiceFactory.cfc was instantiated and stored, it would be referred to globally via APPLICATION.ServiceFactory.

Once the Service Factory was in place, I could then continue to replace all of my queries and update / insert logic with object creation and Service object usage. As I was doing this, I came to realize that all of my Services had a flaw (potentially) in their Read() method. The Read() method took a record ID and then populated a domain object instance. The Read() method gathered the record data by turning around and calling its own Search() method and passing in the ID that was passed to it. The problem was that the Search() methods were doing conditional searches based on the ID that was passed in; meaning, it only included the ID into the search logic IF the ID was non-zero. Part of my search logic is that I would never have to search for a zero ID because it wouldn't make any sense based on the database structure and its one-based auto-incrementing values. So, what was happening was that when I called Read( ID = 0 ), I was getting instance data based on the first record in the database since the Search() method was ignoring the zero-ID and was returning all records in the given table.

To solve this problem, I added some logic to my Read() methods that checks the passed-in ID; if the ID is zero, I simply return the results of a GetNewInstance() call; if the ID is non-zero, I proceed with the regular Read() method. This doesn't sit too well with me. I feel like I am doing something wrong. However, I suppose that using the Search() method from within the Read() method is also a bit of a short-cut. Had I been using my own query call in the Read() method, this additional logic would not have been required. So, I guess, the Read() logic is just a bit of a tradeoff for the ability to leverage the Search() functionality.

Other than the minor tweaks, the substitution process was pretty straightforward. Some of the code became much shorter. I mean, you simply can't beat something like this for brevity when compared to full-on query:

  • <cfset REQUEST.Exercise = APPLICATION.ServiceFactory.GetService(
  • "ExerciseService"
  • ).Read(
  • REQUEST.Attributes.id
  • )
  • />

It looks better all on one line, but I am breaking it up here so you don't have to scroll. This is much shorter than the equivalent query, but at the same time, it's a really long single statement. I found that a lot of my statements became very long and a bit unwieldy. Take a look at this snippet of code where I am populating my JointAspect.cfc ColdFusion component:

  • <!---
  • Get the joint actions for this joint. This will be a
  • list of three IDs for Action, Plane, and Symmetry.
  •  
  • NOTE: We know that these will all be numeric based on
  • our RegularExpression CFParam.
  • --->
  • <cfset REQUEST.JointAction = REQUEST.Attributes[ "joint_action_#REQUEST.JointID#" ] />
  •  
  • <!--- Set the properties for the various aspects. --->
  • <cfset REQUEST.JointAspect.SetJoint( APPLICATION.ServiceFactory.GetService( "JointService" ).Read( REQUEST.JointID ) ) />
  •  
  • <cfset REQUEST.JointAspect.SetJointAction( APPLICATION.ServiceFactory.GetService( "JointActionService" ).Read( ListGetAt( REQUEST.JointAction, 1 ) ) ) />
  •  
  • <cfset REQUEST.JointAspect.SetMovementPlane( APPLICATION.ServiceFactory.GetService( "MovementPlaneService" ).Read( ListGetAt( REQUEST.JointAction, 2 ) ) ) />
  •  
  • <cfset REQUEST.JointAspect.SetMovementSymmetry( APPLICATION.ServiceFactory.GetService( "MovementSymmetryService" ).Read( ListGetAt( REQUEST.JointAction, 3 ) ) ) />

Pretty freakin' wordy! I could alleviate a bit of this by creating short-hand references to the Service Objects rather than constantly going back to the Service Factory and its GetService() method, but this would only have condensed it a bit. In general, I found that many of my lines of code, while less in number, were much greater in length.

Also, little conveniences were taken away. For instance I used to be able to just call ValueList() on the joint_id column of my join query, but now that that query has been replaced with an array of JointAspect.cfc object instances, I have to iterate over the array to build up the ID list. I guess, there's just a bunch of little tradeoffs to dealing with object oriented programming that balance out a lot of the great benefits that it provides.

Overall though, it was a smooth process. The next step is to figure out what to do with data validation. All of the data validation is currently living in the controller / view code; this needs to somehow be encapsulated so that we can use the same logic in multiple places without having to duplicate our efforts... but that is another post altogether.



Reader Comments

Nov 13, 2007 at 10:08 AM // reply »
45 Comments

Are you using CFCExplorer for the Kinky File Explorer?

DB


Nov 13, 2007 at 1:58 PM // reply »
11,238 Comments

@David,

No, just an AJAX call and PRE tag to display the content. I hope to put in some color coding at some point. Just been short on time.


Feb 26, 2009 at 11:22 PM // reply »
26 Comments

Thanks for putting this stuff out there for the public to go through. It's handy to see someone else's thought processes when trying to learn.

I did some quick searches here but didn't see it. Maybe I missed but if not I think it would be good for some folks if you touched on why you were using the request scope instead of variables or something else similar. Grax!


Mar 2, 2009 at 7:25 PM // reply »
11,238 Comments

@Allen,

No problem. I am still learning all of this OOP stuff, so this is just my experimentation.


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 20, 2013 at 11:45 AM
Using jQuery's Animate() Step Callback Function To Create Custom Animations
This is really useful. I found out that you don't actually have to use a dummy css property (surprisingly). To animate a property in a linear-gradient for instance I did this this.css('someLinearGra ... read »
May 20, 2013 at 10:51 AM
Using A Dynamic Column Name With ValueList() In ColdFusion
@Josh, Oh snap! You're totally right! I'm not sure I've ever tried that. I did know that you can call a number of other array-methods on ColdFusion query columns: http://www.bennadel.com/blog/167 ... read »
May 20, 2013 at 10:45 AM
Using A Dynamic Column Name With ValueList() In ColdFusion
@Ben - I believe you can achieve the same functionality with ColdFusion's built in ArrayToList() function. ArrayToList( users[ "id" ] ); ... read »
May 20, 2013 at 10:21 AM
My Experience With AngularJS - The Super-heroic JavaScript MVW Framework
Is there any error logging and handling framework in angularjs, if not then in what way I can do this. ... read »
May 19, 2013 at 2:31 PM
My Experience With AngularJS - The Super-heroic JavaScript MVW Framework
It's funny really just how well that image describes the way I would imagine most people that go with angular for some project is. I have had a similar roller-coaster ride with it as well, but not qu ... read »
May 17, 2013 at 7:42 PM
HashKeyCopier - An AngularJS Utility Class For Merging Cached And Live Data
Ben - thanks so much for posting these Angular articles and findings, they've been a huge help towards learning one of the more 'complex' JavaScript frameworks out there (IMO). I have been using Angu ... read »
May 16, 2013 at 5:01 PM
UPDATE: Parsing CSV Data Files In ColdFusion With csvToArray()
Your code was the closest thing I've found to obtaining some direction for converting ISO fields to values that CF can translate properly. Thank you for posting! ... read »
May 15, 2013 at 6:07 PM
Making SOAP Web Service Requests With ColdFusion And CFHTTP
Ben, you once again saved my bacon at work. Thank you, thank you, thank you! ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools