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 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 10:37 PM
Very Simple Pusher And ColdFusion Powered Chat
hi id making plz easy ... 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 »
May 15, 2013 at 4:15 PM
What If All User Interface (UI) Data Came In Reports?
@Josh, Thanks! @Ben, I definitely recommend the David West book "Object Thinking" I've been quoting from. It goes deeply into the philosophy and history of OO programming. His breadth ... read »
May 15, 2013 at 11:36 AM
Ask Ben: Print Part Of A Web Page With jQuery
I found this helpfull when you need to keep (refresh) the original parent page after closing the iframe child print dialog (Hoping you're not using a form at this time so it won't submit again): On ... read »
May 14, 2013 at 7:13 PM
What If All User Interface (UI) Data Came In Reports?
@Jonah, If there's any books you'd recommend on the subject of domain modelling, I'd love to hear it. I just downloaded the free PDF of "Domain Driven Design Quickly". Figured I'd give it ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools