Categories
Contact Doug!
Learn About Doug!
View Doug Boude's online resume
updated 11/18/2009

View Doug Boude's profile on LinkedIn
Link to me!

Follow Doug Boude on Twitter
Follow me!

Be Doug's friend on Facebook
Befriend me!
(I promise not to follow you home)
OO Lexicon
Chat with Doug!
Recent Entries
You may also be interested in...
Web Hosting

<< May, 2013 >>
SMTWTFS
1234
567891011
12131415161718
19202122232425
262728293031
Search Blog

Recent Comments
Re: Disappearing IE Popup Window During Save/Open Dialog (by LZ at 4/20 7:58 AM)
Re: Create Dynamic WHERE Clauses in PHP (by pooja at 3/20 7:29 AM)
Re: Just What IS a 'Service Layer', Anyway? (by EugenK at 3/07 7:56 PM)
Re: Using Google as your CF Mail Server (by 5starwebteam.com at 2/25 1:27 AM)
Re: Why Provide for Service layer objects in CFWheels? (by Steven Benjamin at 1/25 11:43 AM)
Re: What is an 'Advanced' Coldfusion Developer? (by ColdFusion Developer at 12/24 5:14 AM)
Re: Equivalent of SQL "TOP X" in Oracle (by Ashenafi Desalegn at 12/06 5:29 AM)
Re: PHP Export to Excel Snippet (by serene at 12/05 1:44 AM)
Re: Just What Is 'Application Logic', Anyway? (by Arif at 11/13 8:06 AM)
Re: Hosts File Changes Not Acknowledged on Vista 64 (by Aaron at 10/22 2:31 PM)
Re: PHP Export to Excel Snippet (by Jafar Shah at 10/10 4:28 AM)
Re: Viewing Option Text (in IE7) that's Wider than the Select List (by Chenelle S at 10/04 12:53 PM)
Re: PHP Export to Excel Snippet (by Kilo at 9/26 5:20 PM)
Re: Porting Coldfusion Code to Mura (by tariq at 9/03 9:51 AM)
Re: Just What IS a 'Service Layer', Anyway? (by James at 8/27 4:06 PM)
Re: Calculating Business Hours (by helen at 8/14 2:54 AM)
Re: What IS 'Business Logic', Anyway? (by dougboude at 8/06 11:30 AM)
Re: What IS 'Business Logic', Anyway? (by Adrianne at 8/06 10:29 AM)
Re: Family Law: The Weapon of Choice for Woman Scorned (by dougboude at 8/04 4:39 PM)
Re: Family Law: The Weapon of Choice for Woman Scorned (by Lola LB at 8/04 7:43 AM)
Archives
Photo Albums
Funnies (5)
Family (3)
RSS

Powered by
BlogCFM v1.11

18 April 2012
Providing for Service Layer Objects in CFWheels: Hello Wirebox!
Post 3 of 3

This is the third and final post in a series on making the case for service layer objects (in CFWheels or any framework for that matter!), and two means of implementing them. The second post demonstrated one approach to manually implementing SLOs. This post will demonstrate my MUCH preferred approach: utilizing Ortus Solutions' Wirebox DI/IOC framework.

DI/IOC REVIEW

By way of quick review, the purpose of a Dependency Injection/Inversion Of Control framework is to give the developer ONE PLACE in his app where he can manage the objects that are players within his or her app. For instance, you may have a dataImport object which itself, internally, must be able to communicate with the persistence layer (session, typically), create and manipulate users via a CFWheels User model object, and perhaps access some global utilities via a Utilities object. The manual approach requires you to create and pass in these objects at the time you create your dataImport object. Using Wirebox, you simply ask for the dataImport object, and because you have already pre-defined what it's requirements are, Wirebox worries about building it for you. The advantage? When the app's architecture evolves, and/or object interfaces change, the developer can make those changes in a single spot: the wirebox configuration cfc.

Assuming that at this point you understand why DI/IOC is important, and assuming that you understand the common need to utilize objects in your CFWheels controllers that are NOT directly associated with a database table, allow me to dive in to how I added SLO functionality to CFWheels using Wirebox and the Wirebox Plugin.

Steps I took/Modifications I Made

1. Created a Services folder off the root;
2. Dropped the Wirebox framework off the root;
3. Dropped the Wirebox Plugin zip file into my Plugins directory;
4. Modified the config/wirebox_config cfc so that it knew how my service layer objects should be prepared

That's it! Let's peek at these items in more detail. Well, at least, the ones that aren't already self-explanatory. Oh, I guess that would only be the last step!

In step 4, I needed to tell Wirebox about my service layer objects, the values they require when being created, and the relationships between them. Wirebox provides two basic ways to do this: By annotating your CFCs using the Wirebox Domain Specific Language, or using dependency method chaining. Let me show you a quick example of doing the same thing using each approach.

Let's say you have an object that you want to be given your app's datasource name when it is created. You would manually pass in this value in the object's init method via an argument, so let's go that route. Using Wirebox annotation, you would do this:

 

<cffunction name="init">
 <cfargument name="dsn" type="string" required="true" inject="wheels:setting:datasourcename" />
 <cfset setDSN(arguments.dsn) />
 ....

 
Of note there is the "inject" attribute; Wirebox inspects your CFC before instantiating it and knows that when it does, it should retrieve and pass in the wheels datasourcename during init.

 

Here is what it looks like, in your wirebox_config CFC, using the dependency method chain:

 

<cfset mapPath("services.dataImport").initArg(name="dsn",dsl="wheels:setting:datasourcename");

 

Personally, I prefer (and recommend) the latter method. It keeps your CFCs "normal" (no custom attributes), and the dependency method chain is much easier to read and interpret, all in one line.

Once you have completed step 4, you can write controller methods such as this:

 

<cffunction name="importUsers">
  <!--- perform the data import routine for incoming data... --->
  <cfset result = service("importService").importData(params.dataIn) />
 
  <cfset flashInsert(msg=result) />
  <cfset redirectTo(action="index") />
 </cffunction>

 
Notice the "service()" method; this is what you will use when you want to retrieve a SLO as opposed to a Wheels Model object.

 


DEPENDENCY METHOD CHAIN DETAILS

What good would it be to be able to use SLOs in CFWheels, but those SLOs not be able to use Wheels Model objects internally?? Not much at all. Using the Wirebox plugin, you have the option of enabling your SLOs to have access to Wheels Models. Let's examine a fairly complex Dependency Method Chain definition for the importData SLO.

  

//define our import service layer object
   mapPath("services.importService")
    .asSingleton()
    .initArg(
     name="dsn",
     ref="dsn")
    .initArg(
     name="messageprefix",
     dsl="wheels:setting:messageprefix"
    )
    .property(name="sessionService",ref="sessionStorage")
    .mixins(wheelsORM);//give this object the ability to access Wheels models

 

The first method, 'mapPath', tells wirebox to create an object called 'importService', the CFC for which is found in the services folder.

Next we chain on 'asSingleton()' so that Wirebox knows there should only ever exist one instance of this object.

'initArg' we saw already; we are telling Wirebox that this CFC's init method requires an argument named "dsn", and we want to pass the value contained in the reference ('ref') named "dsn". More on this in a moment.

A second initArg method is chained onto that. Can you imagine what the CFC's init arguments look like? I bet you can. For this initArg(), Wirebox is being told to utilize the Wheels-specific Domain Specific Language (part of this plugin) to retrieve the setting for "messageprefix" (probably being set in config/settings.cfm) and pass that in.

'property()' is telling Wirebox that we want to inject into the object's variables scope, after it has been initialized, a variable named sessionService that is an instance of the sessionStorage object. Again, more on the 'ref' key in a moment.

Lastly, we are telling Wirebox via the 'mixins()' method that we wish for this object to have the ability to call Wheels' 'model()' method internally.Okay, the 'ref'. Also in our configuration cfc we created a value named "dsn" that we can then REFerence in other object definitions. It looks like this:

 

map("dsn").toDSL("wheels:setting:datasourcename");

 

By doing that, any other object that needs the datasourcename value passed in, we can simply say ref="dsn". Same with the sessionStorage service. Elsewhere in our configuration cfc we defined it as

 

map("sessionStorage").to("services.persistenceCFC").asSingleton();

 

If we want to inject that object, now we only need refer to it by 'ref'.

Hopefully that quick overview, and the link to the working data import sample app that uses Wirebox will get you started. The plugin has not yet been approved for inclusion on the CFWheels site, but if you want to play with it now there's a link to it as well. The plugin and the app both contain a READMEDUDE.txt file that you should check out before you do anything else.

Thanks for tuning in!

--------------------------------------

Video demo on youtube

Thorough Wirebox Documentation

Sample App Zip File (be sure to read the READMEDUDE.txt in the zip; you'll have to create one table and edit the datasource setting to get the app to work for you)

Wirebox Plugin (again, be sure to visit it's READMEDUDE.txt)

Posted by dougboude at 11:50 AM | PRINT THIS POST! | Link | 6 comments



13 April 2012
Providing For Service Layer Objects in CFWheels
Post 2 of 3

In my previous post in this series, I made the case for why I believe that service layer objects are a common need in an application's architecture. I also pointed out the fact that CFWheels does not provide for such animals within its framework, and that I had overcome this obstacle using two different approaches. What follows are the details of my first approach and a simple yet complete working sample app for your dissection pleasure.

MANUALLY IMPLEMENTING SERVICE LAYER OBJECTS IN CFWHEELS

So, what we need to be able to do, ideally, is have and use CFCs in our controllers that are NOT directly associated with a database table. The CFWheels approach requires all models to extend the Model CFC. If we omit that extension, and then attempt to retrieve our service layer object using the "model()" method call, we receive an error. If we DO extend the Model CFC on a service layer object and attempt to retrieve it using the "model()" method call, we receive an error. What to do, what to do!

In a nutshell, we have to instantiate and retrieve our service layer objects ourselves. This could simply be done using a line in a controller that performs a "createObject" call, and that would give us our object. Ah, but one of the key elements that a CFWheels developer needs is still missing, because although I can indeed create an instance of a service layer object this way, my service layer object will be completely ignorant of the CFWheels environment. It won't be able to do one of the things it needs to, and that is to ITSELF utilize the CFWheels "model()" and "get()" calls! The remedy for this turned out to be simple, but took a LOT of digging to discover: include the appropriate files from the CFWheels framework in my service layer objects.

Personally, I opted not to show a demo of implementing SLOs (I'm gonna use this acronym from here out) the way described above, because it just wasn't beautiful nor did it provide for an easy way of re-use in multitple controllers. What I decided I wanted, then, was a method all my own that I could use within controllers in order to retrieve my SLOs. Since I retrieve models using 'model("somemodel")', I thought it appropriate to retrieve my SLOs using 'service("mySLO")'. Additionally, I didn't want my SLOs living in the same folder as my models, so I create a folder just for them called "services". This folder contains a core SLO base object, exactly the same way that the "models" folder contains a core Model object. All of my SLOs extend this core component, and thusly inherit the required CFWheels functionality they need to do their jobs.

Steps I took/Modifications I Made

1. Created a "services" folder off the root;
2. Created a core "Service.cfc" that all SLOs must extend;
3. Modified my core "Controller.cfc to include two new methods;

That's it! Let's peek at these items in more detail.

In step 2, it was convenient (and followed the same approach as the rest of CFWheels) to create a core component to be extended. The entire contents of this component is as follows:

<!---
 This CFC provides access to the wheels core functions needed by our service layer objects.
--->
<cfcomponent output="false">
 <cfinclude template="../wheels/global/functions.cfm">
</cfcomponent>

In step 3, I added two methods to my core Controller.cfc. One of these methods, you may have supposed, is called "service". The other provides a single place where the developer can declare and create all of their SLOs at once. That method is called "initServices", and it looks like this:

<cffunction name="initServices" returntype="void" hint="I initialize the services objects for this app">
 <!--- create readable alias keys that the dev will use to get these objects --->
 <cfset application.$_ServiceObjects = {
  importService = createObject("services.importUsers").init(
     dsn = get("DataSourceName")
     ),
  sessionStorage = createObject("component","services.wormhole").init()
 } />
</cffunction>

The "service" method looks like this:

<cffunction name="service" returntype="any" hint="I am the method used to access any service layer object from within any controller">
 <cfargument name="service" type="string" required="true" />
 
 <cfset var retval = "" />
 
 <cfif structkeyExists(application.$_ServiceObjects,arguments.service)>
  <cfset retval = application.$_ServiceObjects[arguments.service] />
 </cfif>
 
 <cfreturn retval />
</cffunction>

One more tiny little thing, within the Controller.cfc's Init method, I added a call to InitServices to kick it off:

<cfset initServices() />

 

 

 

 

That is IT. In this example, what I am able to do now that I could NOT do before in a CFWheels controller (without bloating my controller, anyway) is this:

<cffunction name="importUsers">
 <cfset var objImporter = service("importService") />
 <cfset result = objImporter.importData(params.dataIn) />
 <cfset flashInsert(msg=result) />
 <cfset redirectTo(action="index") />
</cffunction>

THAT, my friends, is how thin a controller method SHOULD be, WHENEVER possible!

Okay, I won't blab on about this approach. I think it's slick, it's fairly easy to maintain, and I think once you take the time to poke through and run the sample user data importer app linked in this post, that you'll agree that you really have been missing Service Layer Objects too, you just didn't call it by that name.

Doug out  :0)

Next up in the series: Implementing Service Layer Objects in CFWheels using the awesome DI framework WIREBOX and the plugin I wrote for it! :)

--------------------------------
Sample App Zip File (be sure to read the READMEDUDE.txt in the zip; you'll have to create one table and edit the datasource setting to get the app to work for you.)

Posted by dougboude at 7:39 PM | PRINT THIS POST! | Link | 4 comments
12 April 2012
Why Provide for Service layer objects in CFWheels?
Post 1 of 3

It's been probably 3 months since I started using the CFWheels framework, and I have nothing but praise for it. It's a compact conventions-based framework patterned after Ruby on Rails that, once you have a grasp of the relatively simple yet complete (mostly) API, makes putting an app together a pleasure. Having come to CFWheels from other frameworks that I've been using for a few years now (Model Glue and Coldbox primarily), I was a bit taken aback when I discovered that not only was there no provision made in CFWheels for utilizing service layer objects, but every other CFWheels developer I communicated with about the apparent lack gave me the virtual two dollar look and wondered why on earth I would ever need a service layer object in my application! Apparently, or so it seems to me thus far, I am the ONLY CFWheels developer on the planet who ever saw a service layer object as a necessity! Now, I don't believe that is true (how could it be?), but since I've encountered no others, I felt the need to do a short series of blog posts covering my view of service layer objects, why they're potentially necessary in ANY app (including a CFWheels app!), and two ways in which I overcame CFWheels' ostrecization of service layer objects.

This post will cover my personal philosophy on service layer objects and use cases for them. I'll cover the remaining information in subsequent posts.

note: my personal belief on the necessity of service layer object only holds water IF a person, like me, holds religiously to the philosophy that controllers as a rule should remain as thin and code-free as possible, and that as much business logic as possible belongs in the app's model, not in its controllers. Additionally, that the controller's job is to act as liason between the view and the model, nothing more.

SO, what is a service layer object? I evolved my personal definition of this creature literally years ago, and in all my subsequent experience with OOP, that definition has not changed one iota. A service layer object is an object which utilizes one or more child or even sibling objects in order to encapsulate and perform some genre of work for your applicaton. My favorite analogy is that of a man in an easy chair with three remotes on the tv table beside him. His wife (the application) commands him to "start the movie" (calls his "startMovie()" method). The man (the service layer object, "objHusband") picks up the TV remote (objTV) and turns it on (objTV.powerOn()), changes the input source (objTV.changeInputSource(3)), then adjusts the volume (objTV.adjustVolume(15)). He then takes the DVD remote (objDVD) and powers it on (objDVD.powerOn()), and starts the movie (objDVD.Play()). This husband provided his wife with a single API method ("startMovie()"), while he himself (objHusband) internally manipulated at least two other autonomous class instances (objTV and objDVD) in order to accomplish that piece of work. THAT is the beauty, purpose, and reason for, service layer objects. Without the husband, the application/wife would have had to talk to two other objects and manipulate them herself...heaven forbid! And, if at any point in time the objTV had been replaced and the buttons weren't the same, the wife wouldn't be able to start her own movie at all! But with the Husband service layer, she doesn't ever need to care about how to work the TV remote...that's the service layer's job, and that is where any and all code related to TV manipulation live and would be modified if the need arose. It's beautiful, isn't it? And if the solution is beautiful, it is right.

Now, where in the real world of apps does this same situation occur? In my world, and I KNOW it must be so in your world too, it occurs ALL THE TIME! As an example, allow me to share the skinny on an app I wrote a while back. This app is a tool that allows multiple users belonging to multiple different client subscriber companies to upload their spreadsheet full of insurance claims into a third party system. This third party system has a rather painful upload lifecycle that requires that each claim be in the form of an XML file that conforms to their DTD. Each xml file/claim is then FTP'd to a test server where, after some unknown time period, their cron job comes along and parses it to test for errors. The cron job leaves behind a text file named the same as the xml file indicating if it passed its test, and if not, what errors were encountered. My app has to poll for these test results, grab them, parse them, and return meaningful information to the user. If the xml file passes, it is then allowed to be FTP'd to the third party's production server where the same process takes place again. That's it in a nutshell. Ugly, eh? But even with such a complicated, ugly process to have to deal with, it can be managed well code-wise if we carefully group like functionality together and encapsulate it in a logical way. Working through the process/code needs to accomodate the process described, you would (as did I) come up with an architecture that is composed of several very purposeful, focused CFCs, and a few higher level CFCs that incorporated and manipulated these more specific CFCs (this is called "aggregation"; my service layer component "aggregates" my single-focus CFCs). My own solution resulted in the following CFCs, all of which reside within my app's "model" folder:

  • user - represents a system user
  • keychain - represents a user's system roles and permissions
  • POIUtility - a utility (modificaton of Ben Nadel's POI Utility) for parsing and manipulating Excel files
  • profile - simple object for retrieving client data profiles
  • spreadsheet - retrieves client spreadsheet definitions and mappings between spreadsheet columns and XML nodes
  • token - utility cfc to translate placeholder tokens into appropriate values
  • fileModel - utility to manage the upload, retrieval, parsing, and db logging related to files sent to the 3rd party system
  • wormhole - persistence layer object used to allow other objects to communicate with the persistence layer (session, etc.)
  • XMLService - service layer object that uses token and profile (and other settings) to translate incoming claim records into proper XML files for upload.
  • spreadsheetService - service layer object that utilizes POIUtility, spreadsheet, and XMLService to do its work (look! A service that relies on another service!)

 

 

 

I won't delve into any more detail than this, but suffice it to say that, there is a LOT Of work that is going on that does NOT relate directly to ANY DATABASE TABLE! Now, if a CFWheels developer (any of the ones I have communicated with) were to write this same app using that framework, there's only a few probable things that could occur: They would end up with controllers that are bloated beyond belief, possibly trying to call one another for different functionality, OR they would have created a whole slough of UDFs somewhere and had to include them in their controllers, OR they would have had to write CFWheels plugins to handle the meatier parts of the work. Any of those three approaches, to me, are either: wrong, ugly, far more work than should be necessary, or any combination thereof. CFWheels, like any other app, SHOULD provide for easily implementing service layer objects, not force developers to work around this fact! I should be able, within my controller OR from within my service layer object, be able to call "<cfset objSpreadsheetService = model("spreadsheetService"), and NOT get an error telling me there's no corresponding table! That's my belief, anyway.

So, based on my personal OOP beliefs, and using this real world example as my use case (though I have several others as well), I conclude that there exists a definitive need for CFWheels to accommodate service layer objects and to expand its definition of what an app's model truly is, as encompassing not only the CFCs representing discrete database tables, but also any and all other business logic that is unique to the application's identity.

 All that said, I do realize that CFWheels is patterend after ROR, and typically when I ask questions like this, the first response is to ask "how does RoR handle that"? I don't know the answer to that, and perhaps because this IS a RoR-patterned framework I shouldn't even WANT it to accommodate service layers as I know them to be. In any event though, I DID convince CFWheels to allow me to code the way I want to. Coming up next, the second post in this series covering the first approach I used to get CFWheels to respect my need for service layer objects.

Next: Providing for Service Layer Objects in CFWheels

Posted by dougboude at 10:48 AM | PRINT THIS POST! | Link | 5 comments
19 April 2011
Picking Up Where Interfaces Fail
Interface.CFC

What Is An Interface?

Interfaces in ColdFusion are something that makes most of us turn our heads sideways and give the two dollar look. Any of us who didn't come from other languages before ColdFusion probably hadn't heard of them, and since they were introduced into CF, the majority of us haven't taken the time to even understand their purpose, let alone actually use them for anything. Myself, I did take the time to know what they were for (in a ColdFusion context anyway), but even so had never found a single solitary use case for them...until recently.

For the record and to give the rest of this post context, let me share my understanding of what interfaces do for us in ColdFusion. In a nutshell, they act as validators for our CFCs. That is, by "implementing" an interface within a component (<cfcomponent implements="myInterface"....>), we are forced to adhere to rules we laid down beforehand for the functions we will write in the future, and we'll be stopped dead in our tracks if we violate any of those rules. Rules such as  what arguments a function must minimally have, what the returntype of a function should be, and other criteria that interfaces allow us to specify.

My Use Case

I have recently written a small library called JBase that is a virtual relational database. Two pieces of functionality that JBase sports, which I factored out into their own components, are data formatting and validation. Now, knowing full well that I haven't anticipated every possible formatting or validation need, I created those components in such a way that they can be easily customized by the developer, AS LONG AS CERTAIN RULES ARE FOLLOWED when writing the custom functions.

I documented what those rules are very thoroughly, as well as placing them into the CFC itself as comments. But, I really wanted to be able to make CERTAIN that all customized functions followed my rules. Now this, you might be saying to yourself, is a perfect use of ColdFusion interfaces! And you would be so very right if it weren't for a couple of teeny weeny challenges, challenges that caused ColdFusion interfaces to utterly fail in this scenario.

1) CF Interfaces (as it is in all languages to the best of my knowledge) require that you EXPLICITLY indicate the name of the function you want to police - but I have no idea what my developers will name their custom functions! As long as they follow a naming convention of "format[whatever]" or "validate[whatever]", the function has a valid name according to my rules.

2) ColdFusion interfaces do not allow me to police functions that are designated as private. Why, I'm not sure, but since one of my rules is that custom functions MUST be private, this was also a fail. What to do, what to do?

Write my own interface component.

What I needed was something I could transparently apply to a component or chain of components (if one extended the other to infinity) that would inspect all of the methods and ensure those whose names matched a pre-defined pattern also adhered to other applicable rules. I called it, strangely enough, "Interface.cfc". Interface.cfc leverages a "rules" configuration array that it uses to analyze the methods, public AND private, within a component or component chain that can be n levels deep. It allows me to provide a regular expression describing function names, and when it encounters a function whose name matches the regex, it then analyzes the function based on the rules associated with that regex. Here's an example rules config array:

<cfscript>
  stRules = [
  {
   name = "^format(?!Value).+?",
   args = {
    targetValue = {
     type = "string",
     required = "true"
    }
   },
   access = "private",
   returntype = "string"
  },
  {
   name = "^validate(?!Value).+?",
   args = {
    targetValue = {
     type = "string",
     required = "true"
    }
   },
   access = "private",
   returntype = "boolean"
  }
 ];
 return stRules;
</cfscript>

 

Allow me to share a short list of Interface.cfc's highlights:

  1. Very non-intrusive. Simply extend Interface.cfc within a component or within the most base component of any heredity chain;
  2. Rather than die on the first error encountered, Interface.cfc will analyze the entire function collection at once and throw a comprehensive error detailing EVERYTHING it found in violation of the rules;
  3. The rules is an easy to read array that is self-explanatory and highly expandable.
  4. Rules are triggered when a function name matches a regular expression in the "name" key for a given rule set.

 

 

 

That's it! Let me show you how to use it and then what the results look like.

Picture If You Will...

Here is a rough diagram of the components that comprise the JBase relational database library. I've circled the customizable components in red:

Here is the same diagram showing interface.cfc implemented to ensure that all of the rules I lovingly outlined in the documentation are actually adhered to :) :

In this diagram, the components circled in red are those who will be validated by Interface.cfc. If we had three or four or n components in the inheritance chain, ALL of them would be subject to Interface.CFC's scrutiny. (note: the level at which Interface.CFC's functionality is triggered does allow one to control "how high" up the chain validation will crawl. The level at which "validateInterface()" is executed is where validation begins to cascade downward. Typically, you will execute validateInterface() at the topmost level component in the chain.)

To use Interface.CFC, follow these simple steps:

1. Create the rules array within the getRules method of Interface.CFC;
2. Make the most base component in the chain (or the component being validated, if there's only one) extend Interface.CFC (<component extends="Interface"....>")
3. Execute the "validateInterface()" method in the pseudo-constructor area of the topmost component that is to be validated
liks so:

<cfcomponent extends="myBaseComponent">
 <cfset validateInterface() />
 
 <cffunction name="init" ....</cffunction>
 ....
</cfcomponent>

 

 

For demonstration purposes, I have chained together (via the "extends" attribute) three components with the most base of them extending Interface.CFC. My rules are defined as in the rules example above. I purposefully coded in several errors. When I attempt to instantiate the topmost component, here is a screenshot of the results:

That's it! I'm extremely pleased with the results.

You can grab Interface.cfc here. Get Interface.cfc from Github at: git://github.com/dougboude/interface.git  View the awesome API documentation here.

And Boyan Kostadinov (@boyank), my .NET evangelist buddy, time to eat a little crow pie my friend. I don't UNDERSTAND interfaces??? Wrong, my man. Dead wrong. Contrary to the beliefs that keep some programmers of other languages thinking highly of themselves, this stuff just ain't all that challenging to comprehend once you weed through all the highfalutin lingo, acronyms, jargon, and fluff. Literally, I can teach this stuff to my 4 year old (and have!). ;) Love you buddy.

Posted by dougboude at 12:18 PM | PRINT THIS POST! | Link | 4 comments
20 January 2011
Use Case for Circular Dependency
Project: JBase

Circular dependency is a concept that's been around a long, long time and most people who do OOP style programming are aware of it. But in my own personal experience, there are very few real instances where a use case exists for implementing it. I am currently working on a project, though, where circular dependency is exactly what the doctor ordered, so I thought I'd share the use case for the next time someone teaching OO concepts needs a real life example.

JBase is a class that is used within a project to act as a relational database (it’s a singleton that persists its data in json files written to disk). It has one other class which it aggregates, called JTable. JBase behaves as a database, while the n number of aggregated Jtable instances behave as individual tables within that database.

JTable is a “smart” table…performs its own saves, finds, deletes, etc. One of the other functions that JTable has is the ability to join itself to other JTable instances to which it is related. But, those other instances exist within the parent JBase instance, so JTable must reference it’s parent JBase instance in order to interact with the related JTable instances.  Feel me dawg?

On a side note, I do plan on sharing JBase as soon as I am finished with it. I don't know if it's actually overly useful to anyone, but hey, you never know. :)

Doug out.

Posted by dougboude at 10:38 AM | PRINT THIS POST! | Link | 4 comments
23 February 2010
Real World Benefits of Encapsulation
I, as most if not all of you do, realize that to do any new development and NOT encapsulate my code would border on absurdity and I would be painting myself into a very narrow corner with regard to maintenance and future project expansion. This post, however, is focused on those projects where you are thrown headlong into an existing codebase that is not based, even loosely, on any kind of object oriented principles, has little to no rhyme nor reason to its architecture, and yet you are tasked with making functional modifications to it without breaking it. A little like playing "pick up sticks", right? Good luck with that! But, by leveraging encapsulation, I was able to accomplish just such a task with relative ease.

For those who may not know, encapsulation is a term that means exactly what it says: containment and separation. Remember those plastic easter eggs that you put things inside as a kid? Whatever you put in there, be it a toy, candy, grasshopper, or whatever, immediately became encapsulated, separated from and unaffected by anything outside of itself (barring direct sunlight, but we'll assume your code will never be subjected to that).

It isn't difficult to port such a definition over to the programmer's world, as we soon learn that by encapsulating specific types of functionality, we can re-use and even share code, thus preventing us from having to waste time re-creating work. In the real world, however, as is often the case, theory doesn't always mesh well with reality. Due to time constraints, lack of experience, laziness, or the inability or lack of authority to modify certain aspects of existing codebases, we very often do not implement encapsulation as we could and should. In a recent project of mine involving an older codebase, the absolute benefits of encapsulation became more than apparent, so I thought I would share the experience.


The task was to modify the import process in the administrative area of a large, "pre-Object Oriented" CMS (which was now living on a ColdFusion 7, "Obect Oriented-friendly" server). In order to minimize the invasiveness of the surgery I was about to perform, I wrote a CFC/class to handle all of the major work, the plan being to isolate the individual switch statement in the thousand line template responsible for the old import process and inject my modifications there and there only. The import process was no simple task, either, and it took a LOT of trial and error to get my code solidified to account for all possible anomolies. But, by encapsulating all of the new functionality in a CFC, I was able to write a quick and dirty test template that utilized my CFC to perform the test imports in isolation from the rest of this app, thus ensuring that all of my code mods, hacks, dumps, and random outputs had NO impact whatsoever on the live app. Once I had my test imports running successfully, complete with statistics being compiled and code written to properly output those stats, all I had to do was drop the relevant portions of my test template into the live app, make sure I had a fast and bullet proof rollback strategy in case something went awry (ALWAYS have a rollback strategy...never trust your own code), and run one final test with my CFC implanted in the live app. Yes, the app I had to modify had no test or qa server; I had to operate directly on the live patient, with no anesthetic.

So, even though you may be often called upon to perform mods to existing, older codebases, if the app lives in an environment conducive to Object Oriented approaches (or even if it doesn't! Don't forget about the ability to encapsulate via Includes if you must!), your path of least potential fallout, self-documentation, and future modifications made easy, is to heavily leverage encapsulation.
Posted by dougboude at 11:46 AM | PRINT THIS POST! | Link | 1 comment
17 December 2009
Using a CFC as a Configuration File
Leveraging The Decorator Pattern
SO, you too find yourself needing to write something that could really benefit from having its settings contained in some external resource. Let's see, what are the choices...we could possibly store our settings in the database and retrieve them at application initialization, if our architecture permits that; we could create an xml file that contains our settings in a nice, nested, readable manner; we could (as one person I mentioned this to suggested) put our settings into an INI file (ya think this person does a little too much .NET? :) ); or we COULD, as I have recently become enlightened to, put our settings into a CFC. Since I am especially partial to the idea of being able to have the choice of hard coding my settings and/or leveraging Coldfusion's dynamic personality to populate them, I went the way of using a CFC.

Allow me to preface the remainder of this post by saying thank you to those out there who have already traveled this road and have made their work open source. By dissecting several different code samples and doing a lot of experimentation, I have been able to enlighten myself as to the mechanics and theory behind it.

SCENARIO
For the sake of illustration, let's say I'm writing a plugin that will be used to provide shopping cart functionality to whatever app is implementing it. Of course, every app's needs, environment, and settings are different, so our plugin needs to be configurable. My goal then is to create a CFC that will contain a nested structure/array of settings that my shopping cart plugin CFC can utilize to control how it is implemented. Sounds simple, right? Or is it... :)

For those who want to skip right to the heart of the matter, you may do so now. For those who, like me, enjoy the layered learning process and the excitement of examining the pieces before putting the puzzle together, let's take a quick look at essential the concepts that allow using a CFC as a configuration file to work.

THE ESSENTIAL CONCEPTS

SCOPE
You already know about scopes in CF and are well versed in how and when to use them, I'm sure. You know, for instance, that if you create a variable within a template and ommit the scope, it is automatically put into the variables scope. You should also be aware, however, that any functions you create within your template also occupy a place within the variables scope. Take this template, for instance, and the accompanying dump:
<cfset thisvar = "Hello" />

<cffunction name="returnIt" access="private" returntype="any">
    <cfargument name="incoming" type="any" />
    <cfreturn arguments.incoming />
</cffunction>

<cfdump var="#variables#" label="MyTemplatesVariables" />


dump of variables scope in a coldfusion template

Interesting, eh? Keep this in mind.

Now, you may also already be aware of the fact that within an instantiated CFC you have scopes as well. I won't spend any time elaborating on those scopes or the differences between them (did that in another post a while back). But I WILL hit you with a short CFC and a dump of its own internal variables scope. Based on our little experiment above with our template, look at the CFC internals and formulate an idea of what you would expect to see. You may see something surprising in this one.

Component A.cfc
<cfcomponent output="false">
    <cffunction name="Foo" access="public" output="false" returntype="any">
        <cfargument name="nuttin" type="string" />
        <cfreturn arguments.nuttin />
    </cffunction>
   
    <cffunction name="Man" access="private" output="false" returntype="any">
        <cfargument name="nuttin" type="string" />
        <cfreturn arguments.nuttin />
    </cffunction>
   
    <cffunction name="Chu" access="remote" output="false" returntype="any">
        <cfargument name="nuttin" type="string" />
        <cfreturn arguments.nuttin />
    </cffunction>
   
    <cffunction name="getMyVariablesScope" access="public" returntype="any">
        <cfset var theseVars = "" />
        <cfsavecontent variable="theseVars">
            <cfdump var="#variables#" label="ComponentAVariables" />
        </cfsavecontent>
        <cfreturn theseVars />
    </cffunction>
</cfcomponent>


Code to instantiate A and retrieve and output its variables scope:
<cfset objA = createobject("component","A") />
<cfoutput>#objA.getMyVariablesScope()#</cfoutput>


dump of variables scope from within a coldfusion cfc

As you probably expected, there in the variables scope are all the functions of the CFC (regardless of what access type we gave them). Additionally, we have the often shunned THIS scope...and looky what THIS is harboring. That's right boys and girls, a reference to (not copy of) the CFC instance. THIS, as you may or may not know, IS accessible from outside the CFC instance. So if we modify slightly the code we used above to instantiate the object, and add a line to give our object another attribute, a subsequent call to getMyVariableScope will reflect the results.

Code to instantiate A and retrieve and output its variables scope:
<cfset objA = createobject("component","A") />
<cfset objA.someFunkyParam = "Doug Boude Rocks" />
<cfoutput>#objA.getMyVariablesScope()#</cfoutput>


dump of variables scope from with a coldfusion cfc

This is perfect behavior for what we're wanting to do! Oh...what is it we are wanting to do? Let's get to the next and last essential concept and see!

THE DECORATOR PATTERN
Here's a term I'm sure most of you have heard of. If you haven't heard specifically of this pattern, I'm sure you've at least heard of design patterns in general. Well, you can and should think of this one exactly as its name sounds. Let's say you figure out that the fastest way to meet chicks is to buy a dog (since you can't afford to buy a baby), so you grab a "mildly malformed" West Highland White terrier from the "we finance anyone" pet store down the street. You invest a few more bucks and take little Timmay to the groomer. When you pick him up later, he is now sporting a lovely red tartan neckerchief and smells of Eau de Tim McGraw. Timmay has been decorated! He's still a midly malformed Westie, only NOW he ALSO has been given the ability to attract hot chicks, AFTER he was born. I know, it was an elaborate analogy, but this is how I entertain myself. So then...since in our mind's eye we want our Config.CFC to be beautifully simple for the end user to populate and we don't want them to have to ignore (and try not to touch) lots of other support methods or worry about inheritance dependencies, what we ideally need to be able to do is provide them a clean, simple CFC that contains only a configure method. When they populate it (or code it to grab its values from elsewhere), we'll take it and then DECORATE it with a method that will allow us to retrieve that same configuration info! Okay, enough of concepts and ideas. On to the solution.

THE SOLUTION
The key players in this scene are:
"ShoppingCart.cfc", a plugin designed to provide shopping cart functionality to any application;
"Config.cfc", a cfc whose sole purpose in life is to provide the developer with a single place in which to maintain relevant ShoppingCart settings;
"configTest.cfm", a cheesy template who just kinda glues this stuff together for us.

First, configTest.cfm.
<cfset objShoppingCart = createObject("component","ShoppingCart").load("Config") />
<cfdump var="#objShoppingCart.getSettings()#">


Straightforward. We're creating our shoppingcart cfc, calling the load method and passing in the class path to our configuration cfc. Then, calling shopping cart's getSettings method just to prove to ourselves that it worked.

Config.cfc.
<cfcomponent output="false">
    <cffunction name="configure" access="public">
        <cfscript>
            settings = {
                environment = {
                    DSN = "dbserver",
                    EmailServer="mail.onelove.com"
                },
                cartSettings = {
                    maxCartItems = "15",
                    salesTax = "true",
                    cartHeading = "One Love to Rule Them All",
                    cancelMessage = "Aw baby, why you leavin?",
                    thankyouMessage = "Stay Cool",
                    daysLeftTillXmas = ceiling(datediff("h",now(),createdate(2009,12,25))/24)
                }
            };
        </cfscript>
    </cffunction>
</cfcomponent>


This is a "hard coded" version, where all the settings are just there. You'll notice at least one of them taking advantage of a PRIME reason to do configuration this way: dynamic values!

ShoppingCart.cfc (scaled down to ONLY the relevant methods needed to illustrate the point of this blog post).
<cfcomponent output="false">
    <cfset variables._settings = "" />
   
    <cffunction name="load" access="public" returntype="any" hint="I load settings from an external CFC">
        <cfargument name="configpath" type="string" required="true" />
        <cfscript>
            var objConfig = createobject("component",arguments.configpath);
            //need to run objConfig's configure() method in order to actually create the
            //configuration settings structure
            objConfig.configure();
           
            //decorate objConfig with our local _getConfig  method :)
            objConfig.getConfig = variables._getConfig;
           
            //execute the method we just added to objConfig to retrieve objConfig's 'settings' struct
            variables._settings = objConfig.getConfig();
           
            return this;
        </cfscript>
    </cffunction>
   
    <cffunction name="getSettings"
        access="public"
        returntype="any"
        hint="I am the method used to get our local configuration values.">
           
        <cfreturn variables._settings />
    </cffunction>
   
    <cffunction name="_getConfig"
        access="private"
        returntype="any"
        hint="I am the private method that will decorate our configuration object!">
       
        <!--- we're counting on our configuration object to have a variable called 'settings'... --->   
        <cfreturn variables.settings />
    </cffunction>
   
</cfcomponent>


You'll want to study this one a bit, and let me point out a few things.

The last method, "_getConfig", serves no other purpose than to decorate our configuration object. Now, you may be thinking, "but I could just put that method inside my configuration object and tell my users to just ignore it!". Yeah, you could; but that's cheesy. So, to avoid smelling of aged Camembert, we hide this method here and add it to our configuration object within the "load" method.

Here's the results of calling configTest.cfm:
dump of coldfusion structure

SUMMARY
In a nutshell, because an object always sports a THIS scope, AND because local functions always exist in the VARIABLES scope, it is a simple matter to attach a new method to an object. If the method you are attaching is written correctly, it can access the methods and values within the object that all of the native methods can. By leveraging this very cool relationship, you can move configuration settings to a CFC.


POST SUMMARY
You may also be thinking, "Dude, I or someone else I don't trust could wreak so much havoc in my code by decorating objects with well-written methods!". And dude, I do believe you're probably correct. I haven't researched much into the security ramifications, or how many ways one might find to defile the sacraments of "clean OO"; but, I know that with CF comes great power, and with great...oh, you know. We've chosen the more lenient world of CF, so it's up to us to respect those freedoms and work with them accordingly. If you don't feel good about that, well, there's always the more communistic "typed" languages, with their greater complexities and unbending rules. :) Hey, some people prefer domination ;) To each his own.
Posted by dougboude at 12:41 PM | PRINT THIS POST! | Link | 0 comments
07 November 2008
SQL Forward Engineering with Visio 2003 Professional
made a little simpler

Finding the shortest route from diagram to tangible product can be tricky depending on the tool you use to create your Entity Relationship (database) diagrams. I'm using Visio 2003 Professional for mine, and so I went on the hunt for a way to transform diagrams into SQL 2005 Scripts (Visio Professional doesn't include any export features for ER diagrams). The final solution isn't the absolutely most elegant, but I'd call it live-able at least. The basic steps are:


1. Export your diagram to XML;
2. Apply an XSL stylesheet to the XML that generates SQL 2005-compatible scripts.

Exporting XML from VISIO 2003 Pro

Visio Professional doesn't include the luxury of exporting to XML, so I discovered a very sweet third party tool aptly called "Toolbox" made by a generous company named Orthogonal (the tool is free!). Installing Toolbox creates a floating toolbar in Visio that allows you to export the currently open ER diagram. To install simply download the Orthogonal "Toolbox" product, run the setup, restart Visio (if it was open during install), and open an ER diagram. The toolbox should be floating there in your window. If you don't see it, you can go to View,Toolbars and make sure it is checked as being visible.

Creating the SQL Scripts

In my scenario I opted to just go the route of using Internet Explorer to view the finished XML code since it will automatically apply any referenced stylesheets. Because Toolbox let us choose a stylesheet to apply at the time of export, a reference was added to the XML file so when we view it in IE we see a nicely formed SQL 2005 script to create our tables and their relationships. Here's a snapshot of the Toolbox dialog box:

The finished product:

xml created by appling xslt to Toolbox XML file

On the subject of the XSLT...Orthagonal provides an XSLT file that creats the script, but without any linebreaks or anything to make it readable. I found a modification to this XSLT on this guy's site , and I modified it a little further in order to account for autoincrementing identity fields, table names that might also be reserved words (who ever does that?), and default values for bit type fields. My version is at the end of this post.

Final Notes
The XML exported by Toolbox doesn't seem to capture anything you put into the "default value" for entity columns. Because of this, I hard-code a rule into my XSLT that says if the field type is bit and NULL is NOT allowed, make the default value true. Also, although Visio does allow you to say that an column is an identity column, it does NOT give you a way to specify that it should autoincrement. I added one more rule to my XSLT that says if the column is INT and is IDENTITY, script out the autoincrement functionality as well.

The XSLT file has some HTML embedded in it in order to allow for an eye appealing output when viewed in IE. If you are going to be applying the stylesheet via another mechanism, you'll probably want to go through the XSLT and strip out the generated HTML first.

TIP: If you weren't aware of it, you can have multiple pages within one Visio ERD document (as in the screenshot at the beginning of this post). The Toolbox export will export one xml file for every diagram on every tab, so if you want to get things done in one shot just consolidate your Visio documents into one!

That should be it. Here are the relevant links for you to get started creating SQL 2005 scripts from your Visio 2003 ER diagrams:
my version of the XSLT file

link to get Toolbox
sample of the XML produced by Toolbox (without xslt applied)

sample of the XML produced by Toolbox (WITH xslt applied!)

Posted by dougboude at 6:04 PM | PRINT THIS POST! | Link | 24 comments
22 August 2008
Just What Is 'Application Logic', Anyway?
as opposed to 'Business Logic'

In a previous post I did on "what is Business Logic", I used the analogy of the application's controller making a request for information from the model, and how the process that the model executes in order to produce the requested information IS the business logic itself. Since I had taken the time to expound on the term "Business Logic", a reader asked me if I would expound on what, in contrast, exactly Application Logic is, so what follows is an analogy of the term as I understand it....

Let's start a company, shall we? Sapient Grey will be primarily a think tank, but with an in-house development group with the capabilities to make the visions of the core committee a reality. Our corporate motto, "Sapient Grey is People..." will be burnished in giant brazen letters alongside a customized version of Rodin's famous sculpture "The Thinker", all of which will adorn the east-facing side of our brand new ten story red granite office building.... Oh, wait. We don't have an office building yet. Okay then, so we'll hire an architect to design our office building, being sure to include a private elevator and an elaborate zen-style atrium or courtyard in the center. In the meantime, while the building is being designed and constructed, you and I and our other elite colleagues will fly ourselves to Tahiti to brainstorm Sapient Grey's visions, goals, agenda, and lay out a detailed business plan.

Our architect is creating detailed blueprints for the office building, figuring out how the plumbing will need to be laid out, how the electrical systems will be segregated and tied together, how the interoffice communication system will be organized, and how we will implement security at all levels. The systems and designs that our building architect is handling is a precise analogy to what "Application Logic" is within a web application. How security is implemented, how we will manage and access state and persistence, how we will handle storage and retrieval of data....this is application logic. Like our office building, which when complete could house and accommodate anything from an elite night club to an investment firm, the application logic is independent of the actual business logic that executes within it.

Back in Tahiti, we and our elite colleagues have nailed down our mission, vision, and corporate culture statements, and have managed (despite the infinite flow of top shelf pina coladas) to draft a three hundred page document which architects Sapient Grey's primary divisions, corporate policies, managerial policies, communication policies, and human resources policies. We know, generally at this point, what our company will be doing and all the internal workings that will allow it to function efficiently. In our analogy with a web based application, we have just architected our application's Business Logic.

So, although at first glance the terms Application Logic and Business Logic can seem to be very ambiguous and even overlapping (they were for me, anyway), in reality they are not. Using the analogy of Sapient Grey and its office building, it is a rather simplistic exercise to properly categorize any aspect of a web based application's logic as one or the other. Just ask yourself, "is it part of the building our company resides in, or is it part of our company and would go with us DESPITE the building we happen to office in?"

Just my take on things. Input and/or clarification soliticted from any other enlightened beings.

Doug out.

Posted by dougboude at 7:56 PM | PRINT THIS POST! | Link | 5 comments
29 July 2008
How to Think about Controller objects and Model objects
with Coldspring in the mix!

Even though MVC has been "all the rage" now for a good long time and several frameworks have been lovingly and painstakingly developed and shared by the CF community to help facilitate the migration to a more standardized OO approach to development, I do believe that there will always be a need to regularly return to the foundational principles of our craft. For some, an affirmation or further perfecting of their core thought processes; for others, the first exposure to a new way of thinking about and viewing the tools they wield as a problem solver and programmer. After having immersed oneself so deeply in MVC and OO for a substantial length of time and embracing those concepts so completely, these foundational principles can become so much a part of us that we hardly even recognize them as such, and tend rather to simply see them as a part of who we are and how we think. Sometimes, though, the privileged occasion arises when we get to once again see them as the wondrous, shiny ideas that they are, when a person who has had the tenaciousness and fortitude to embark upon that OO journey asks us to share our own insight in order to facilitate the evolution of their own assimilation of these concepts.

Alright, perhaps a bit too poetic a prelude, but I was recently asked to share my own understanding of the relationship between controller objects and model objects and the mechanics there. I couldn't help but get a little excited as I took the time to examine my own understanding of the subject and attempt to relate it to this person and realized just how much a part of my thinking it has become. Of course, it goes without saying that I know for a fact I still have a lot of room for growth in this area, but I do feel at least a sense of satisfaction that the couple of years I've invested so far in this has grown me more technically than I believe I had in the five years prior doing procedural coding.

 Okay, enough with the nostalgia already! Here's the question I was asked:

[10:09 PM]  hey Doug-
[10:10 PM]  thanks so much for all the tutorials and learning materials, can't thank you enough
[10:11 PM]  i've got a basic model glue site up and running with one exception, total MVC with not much in the model, totally bloated controllers. Still trying to get my head around calling and using the code from my model via the controller, any blog entries or anecodotal stories to suggest that would guide me?

My Response:

Hey, you're welcome for the tutorials and such. I definitely don't do it for the fame, but rather because I KNOW how painful it can be to traverse a new learning curve, espcially when it comes to frameworks, OO, and the like. If I can spare someone even ten minutes of hair pulling then I've accomplished what I set out to do! :)
 
Using your model code in your controllers (which is exactly what a person should be doing :) )...this is nothing more or less than giving your controller cfc an instance of your model cfc so it can manipulate it, call its methods, etc. For instance, imagine for a moment that we are attempting to log a person in to our app (framework doesn't matter, all we know is it's one that supports MVC). The user has just filled in their username and password and clicked the submit button, and those two pieces of info are now handed off to our controller via whatever mechanism the framework we're using has provided us. We have created for ourselves a Security.cfc that has a method called "Login".

 
<cfcomponent displayname="Security">
   <cffunction name="login">
       <cfargument name="username" />
       <cfargument name="password" />
    ...
   </cffunction>
</cfcomponent>


 
Now, Security is our controller, so by virtue of that fact the general rule of thumb is that the controller's job is to be nothing more than a liaison between the View (our forms and results page) and our model (where the real work gets done!), our controller cfc should have very little code in it and in fact should be using our model object to get the real work done. In order for it to do that, it needs an instance of it's Model security counterpart. In our scenario, we have a CFC living in the Model directory also called Security which performs the actual act of attempting authentication. Here's what our Model/Security.cfc might look like:
 

<cfcomponent displayname="Security">
   <cffunction name="login">
       <cfargument name="username" />
       <cfargument name="password" />
       <cfset var results = false /><!--- set the value of our return variable. by default we're going to return a result of false, meaning the authentication failed --->
       <cfquery name="qryLogin">
          select username from user_table where username = <cfqueryparam value="#arguments.username#" cfsqltype="cf_sql_varchar" /> and password = <cfqueryparam value="#arguments.password#" cfsqltype="cf_sql_varchar" />
       </cfquery>
       <cfif qryLogin.recordcount eq 1><!--- we authenticated! --->
            <cfset results = true />
       </cfif>
       <cfreturn results />
   </cffunction>
</cfcomponent>

 
Makes sense to you, I'm sure...same kind of code we've been using for decades to authenticate a person, right? Okay, so now we need for our controller to actually make the login call. Let's give our Security controller access to this functionality. Here's our controller Security CFC again...
 

<cfcomponent displayname="Security">
   <cffunction name="login">
       <cfargument name="username" />
       <cfargument name="password" />
       <cfset var objSecurity = createobject("component","Model.Security") />
       <cfset var results = false />
       <cfset results = objSecurity.login(username=arguments.username,password=arguments.password) />
       <cfreturn results />
   </cffunction>
</cfcomponent>

 
So, within our controller, we have created an instance of our Model security CFC and called its login method. I know this is a very simplified example, but it is precisely the way to think about the relationship between your model and your controller objects! We can get a little fancier if we like and put our object into the variables scope within our CFC so that we only create one instance of it and then let every method in the controller access it as needed, like this:
 

<cfcomponent displayname="Security">
 <cffunction name="init">
  <cfset variables._objSecurity = createobject("component","Model.security") />
 </cffunction>
 <cffunction name="getSecurity">
  <cfreturn variables._objSecurity />
 </cffunction>
 <cffunction name="login">
    <cfargument name="username" />
    <cfargument name="password" />
    <cfset var results = false />
    <cfset results = getSecurity().login(username=arguments.username,password=arguments.password) />
    <cfreturn results />
 </cffunction>
</cfcomponent>


 
Now any method in my controller that needs to use the model security object need only do a "getSecurity()" call! This is assuming that your Init method is getting called when your controller is instantiated by your framework; it would need to in order for the security object to be present and available.
 
Now, for many reasons, it is not the best idea to be hard coding object instantiation into your controllers. I mean, what if you did that and then somewhere down the road you had to make a change to your Model/security.cfc that now required the init method to be called upon instantiation? You would have to hunt down every place in your app where the security object was being instantiated and change the createobject line to include the init method call. In this scenario probably not a huge deal to do so; but potentially this could create a LOT of extra maintenance. This specific thing is why I have come to love Coldspring so much. It allows me to "inject" an instance of my model/security.cfc into my controller/security.cfc in one handy place so that I need never (probably) touch my controller when a change is made to my model as I described. Here is my controller when I inject the model/security object using Coldspring:
 

<cfcomponent displayname="Security">
 <!--- Coldspring Autowire methods --->
 <cffunction name="setSecurity" access="public" returntype="void" output="false">
  <cfargument name="Security" required="true" type="any" />
  <cfset variables._Security = arguments.Security />
 </cffunction>
 <cffunction name="getSecurity" access="private" returntype="any" output="false">
  <cfreturn variables._Security />
 </cffunction>
 
 <cffunction name="login">
    <cfargument name="username" />
    <cfargument name="password" />
    <cfset var results = false />
    <cfset results = getSecurity().login(username=arguments.username,password=arguments.password) />
    <cfreturn results />
 </cffunction>
</cfcomponent>

 
By adding Coldspring to the mix, when it instantiates your controllers and finds corresponding SET and GET methods like that, it will look to see if it has a definition for the object the set and get references (in this case, the set and get are for 'Security'...getSECURITY, setSECURITY...so it will be looking for a bean definition named SECURITY). If it does, it will go ahead and create that object and inject it into the controller for you so that it is "present and accounted for" from that moment on. So, I could theoretically define a whole bunch of different objects (aka 'beans') for Coldspring, and then when I need one of those objects in my controller, all i gotta do is create a SET and GET method that matches the object name. Let's say our Security controller ALSO needs to be able to send emails, and our app has an Emailservice CFC in the model. Well heck, let's just inject that bad boy and use it! :
 

<cfcomponent displayname="Security">
 <!--- Coldspring Autowire methods --->
 <cffunction name="setSecurity" access="public" returntype="void" output="false">
  <cfargument name="Security" required="true" type="any" />
  <cfset variables._Security = arguments.Security />
 </cffunction>
 <cffunction name="getSecurity" access="private" returntype="any" output="false">
  <cfreturn variables._Security />
 </cffunction>
 
 <cffunction name="setEmailService" access="public" returntype="void" output="false">
  <cfargument name="EmailService" required="true" type="any" />
  <cfset variables._EmailService = arguments.EmailService />
 </cffunction>
 <cffunction name="getEmailService" access="private" returntype="any" output="false">
  <cfreturn variables._EmailService />
 </cffunction>
 
 <cffunction name="login">
    <cfargument name="username" />
    <cfargument name="password" />
    <cfset var results = false />
    <cfset results = getSecurity().login(username=arguments.username,password=arguments.password) />
    <cfif not results>
      <cfset getEmailService().sendAdminEmail(subject="failed login") />
    </cfif>
    <cfreturn results />
 </cffunction>
</cfcomponent>

 
Coldspring just makes object injection SO simple, don't you think? Setters and getters are one way of injecting objects using Coldspring; it also can do it another way, which I won't get into right now (no need to muddy the waters at this juncture). Now, you should also know that there are times when individual Model objects ALSO need to use instances of other model objects (you may have encountered this already at some point). For instance, the example of an Emailservice object...by virtue of the very defnition of a service object (which I do have a blog post about), it is likely manipulating the methods of two or more OTHER objects. Just like our controller, for our model object to use another object, it has to have an instance injected into it somehow. Either we created that instance manually using a Createobject statement, OR we leveraged Coldspring to auto-inject those instances for us. The manner in which it is done is exactly the same as it is for controllers, no significant differences at all.
 
Okay, I know I've kinda gone on and on about this, but (if you can't tell) I do tend to have a passion for Coldspring and the beauty it brings to an OO application! But you know, even if you opt not to leverage Coldspring to perform the object injection and choose rather to do it manually (which I, for one, would not frown upon you for doing :) ), the concept is exactly the same: If one object needs to manipulate another object,  you must create an instance of the needed object(s) within the controlling object, whether that happens to live in the model or controller. Having said that, there are a few hard and fast rules of thumb when writing these apps that I always follow and which you may want to consider for yourself.
 
1. A controller's job is to be liaison between view and model, only. Keep controller methods as light as possible, doing as little work as possible.
2. A controller should NEVER talk to the database
3. A controller is the ONLY one who has the privilege of talking to Session or Application scopes (unless you have yourself a session facade object, which I personally have never seen the need for. If you DO have a session facade object, then IT is the only object in the app who has the privilege of talking to session. in that case, the session facade will have a corresponding controller and model object).
4. Model objects should be doing as much of the app's work as possible. In a nutshell, build your model objects as if tomorrow you would be told that you had to change frameworks and your model was the only thing you could take with you.
5. NEVER even consider injecting a controller object into a model object. BLAH! YUK! PTOOEY! In fact, never allow yourself the sacrelige of injecting one CONTROLLER into another. If you're seeing the possibility of a need to do that, then probably you need to refactor some logic and move some code around.
 
That's about it. Have I helped fill in any gaps? Have I opened any more? Did I address what it is you were needing? Let me know, I don't mind taking the time to share (and learn)!
 
Doug  :0)

 

 

 

Posted by dougboude at 9:31 AM | PRINT THIS POST! | Link | 2 comments
01 May 2008
Why I Hate ORMs (a solicited rant)
A necessary disclaimer...
Everything in the following post that appears to be an opinion most likely is and should be taken as such. My personal view on a topic does not (necessarily) invalidate any other opposing view. Readers should ascribe whatever value they so choose to the information that follows and either adopt it or reject it at their own discretion.

In the comment thread to a post I did on custom validation in Model Glue, I shared the fact that ORMs aren't my friends. In so doing, it prompted another commenter to ask me to share more details about my decision to be anti-ORM, as they too are weighing out the pros and cons of incorporating it:

"  Doug,
Can you elaborate on why you've abandoned ORM? I browsed thru your blog but didn't see any references to this decision. I'm wrestling with its costs vs benefits as well and would be interested in hearing from someone further down that path.

Thanks,
Dave  "


What follows are those details.

Why I am Anti-ORM


The Beginning

Just over a year ago, my team and I embarked on a journey to learn the ways of the object oriented programmer. We evaluated some of the popular Coldfusion MVC frameworks and decided to go with Model Glue. At the time, the trend was also to utilize other frameworks alongside Model Glue, so we too jumped on the bandwagon, reasoning that if we were going to adopt the tried and true standards of the OO world, we were going to embrace it completely. So, we architected our first MVC application, opting to utilize MG as our MVC framework, Coldspring as our IOC framework, and [brand X] as our ORM. For those of you who may not know what each of these frameworks are for, ModelGlue is the framework that separates, organizes, and "glues" together your views, your CFCs, and the controller CFCs that act as liaison between the other two. Coldspring is the IOC (Inversion of Control) framework whose job it is to manage the relationships between your CFCs. For instance, you might have a User.cfc that needs to perform a function located within another CFC such as Security.cfc. Using Coldspring, you can define that relationship ahead of time and, rather than hard coding the instantiation of your Security.cfc within your User.cfc, Coldspring will do that for you automatically whenever your app asks for the User.cfc. Ah, and now for [brand X]. {brand X] is an ORM framework whose job it is (and here's where my opinion and personal understanding heavily apply) to add a layer between your app and your database. The reason for this, you might ask? The reasons that my team and I saw for doing so were:

1) To allow us to easily change backend database platforms later down the road, should the need occur (not likely, right?)

2) To allow us to take advantage of some of the nifty "helper" features, such as auto-validation and scaffolding (automatically building Create, Update, View, and Delete forms for a given table)

3) To allow us to pre-define relationships between data so that we could "drill down" into child data by calling auto-generated methods, without having to query for it

4) Because using [brand X] was what every CFer "in the know" was doing, so it must be the right thing to do!

Sound like decent reasons, right?

I'll summarize, from my experience, the reasons that ORMs gave me to despise them. I'll try my best not to rant (actually I already did a lot of that in this other post).


The Reasons

The first reason my ORM gave me to hate it was that it forced me to have to synchronize case between field names and elements within different XML files. Coldfusion has LONG been a case-insensitive language for the most part, but suddenly now, as I am embarking on a journey through the foreignness of ORMs, I have to ALSO be mindful that everytime I type in a field name, I had just BETTER make sure I type it exactly the same way every time! Of course, I learned about this the hard way, through many hours of troubleshooting, following nearly useless error messages, and piecing together scraps and tidbits from here and there on the net building myself a "Franken-Solution".

Second reason: the Coldfusion ORM frameworks are a work in progress, and thus subject to undiscovered anomolies coded into their core. While my team and I were burning the midnight oil trying to learn and use our ORM, it kept changing on us. We'd update and replace core files only to find that some behaviors had suddenly changed. The one thing that DIDN'T change were the nearly useless error messages, though...that kept it "interesting" for us.

Hey, this ever happen to you? You're building an application and suddenly realize you need another field in a certain table, so you...go ahead and add it? Sheesh, it happens ten times a day sometimes! A very common occurrence, a very expected occurrence, right? Which leads me to the third reason my ORM gave me to hate it: our ORM didn't take kindly to change. It took us FAR too long to try and figure out how to cause it to see and propagate database changes throughout the app without spilling its groceries into a useless error message. The final solution, that took us weeks of evolving to: nuke it. Just delete the whole cotton-picking cache of files that our ORM had automagically generated for us and FORCE it to recreate them all. This approach defies common sense, and thus it was the end of our evolution and not the beginning. Why's an ORM gotta defy common sense?

The fourth reason: gluttony. As mentioned in the list of reasons why we chose to use an ORM, we wanted to leverage the beauty of pre-defining data relationships and be able to drill down into child data with ease. In theory, this is a beautiful thing. In practice, it's a disgusting hag. The bloated, inefficient objects within objects within objects that get created in this process can cause an app to literally CRAWL. What would take less than a second to perform the traditional way can take many hundreds of times that amount of time when using these auto-generated object nests. When you do take the time to define all of these relationships as they truly are (and good luck getting that right the first five tries), the resulting objects are ginormous and slow as molasses on a cold January morning. Painfully slow. Not acceptable, ORM. Not acceptable.

And ah, the grandest reason of them all that I pretty much despise ORMs: losing my beloved sql. Now, I wouldn't have a problem with losing sql as long as my ORM provides me with a suitable substitute. But it does not. The task of translating a simple sql statement into "ORM-speak" is far, far from simple, my friend. I and others I know have quite literally spent an entire DAY trying to figure out how to write the code, leveraging our ORM, to execute a simple join. Don't get me wrong, it IS do-able. But from the perspective of someone who knows how to query a database, doing the same thing using only ORM objects is convoluted, WAY over-complicated, gluttonous from an efficiency point of view, time consuming, and in the end....what the heck good is it anyway? What did I just do to help myself by spending an entire DAY figuring out how to define object relationships in a way that my ORM likes, defining events that have every parameter present and properly cased, making sure that the database changes I make along the way are actually recognized by my ORM and my application has been properly reinitialized, and then synchronizing the whole thing and crossing my fingers that it'll actually work and not throw me back some useless error? Writing and executing what was and is simple SQL is ridiculously convoluted by an ORM, eats up a huge amount of precious development hours in figuring out how to do it, and gives me only negative return on that investment by creating code that increases my bottom line in IO and makes it so that only another person who has drunk the ORM kool-aid can possibly ever understand. Oh yeah, and when you DO finally figure out how to write a simple join, you then realize that there are actually probably four or five different ways you could have done it using the ORM objects; which one is most efficient? who the heck knows, and you'll only know if you invest the hours to write it with each approach and time it yourself. And even your ORM's BEST and most efficient approach will STILL NOT beat the time you would get by executing straight SQL...there's no way.


Conclusion

What this and any decision comes down to is really just a list of reasons TO do something versus reasons NOT to do it. In this case, based on what I consider to be thorough personal experience combined with that of my peers, adopting an ORM has an extremely sparse list of "Pros" which in no way even come CLOSE to outweighing the list of Cons that come with it.

I realize I didn't do very well at filtering out my ranting. I also realize that, if you happen to be a person who has already gone to ORM prison and now you're used to the lifestyle of having it dwell within your apps, you're going to have a totally different take on it. But I'd be willing to bet money that even you die-hard ORMians felt the same way I do at one point in your J-Curve, only instead of ceasing to knock your head against the wall, you banged a little longer and finally broke through it. Now it's second nature to you to  know where NOT to step in order to avoid the landmines, so you can play soccer freely in the minefield having only lost a few virtual limbs in the process.  HOWEVER, if you are the person who has yet to step into that tempting and beckoning ORM minefield, if you're still on this side of the kool-aid, you should know that forcing yourself to use and learn an ORM is a bit like forcing yourself to learn to smoke. Yeah, given enough choking, hacking, and puffing, you CAN eventually learn to love the feeling of hot, acrid, killer gases in your lungs; but is the miniscule physical pleasure and social "coolness" worth the initial pain, suffering, and certain long term problems that go with it? I say no way, and after having hacked and puffed on my chosen ORM for a solid six months, I say no way to that as well.

I am of course committing a social faux pas by pre-judging all ORMs based on my experience with one, much the same way as it is commonly said that you can't judge all women by the way one woman treated you. But you know what? Even the slickest ORM is STILL only going to provide me with 2 or 3 pros, tops, and will STILL of necessity be adding overhead to my application's efficiency and learning curve to my timeline. From that perspective then, yes, I AM pre judging and have every intention of remaining "ORM Celibate" from here on out. I've worked on several applications since the one I mentioned earlier, all completely without an ORM involved, and have been utterly delighted with their performance. Good riddance, ORMs, I'm not missing you at all and will probably never recommend you.

Doug out.
Posted by dougboude at 11:54 AM | PRINT THIS POST! | Link | 21 comments
07 March 2008
What IS a Function, Anyway?
Function.
The word has given not just new coders wrinkled brows and vacant stares, but also most everyone who encounters the term initially. Though we programmers might tend to think  "function" only applies to us, in reality it crosses every boundary and therefore I believe that NOBODY should live one moment longer without being armed with a precise understanding of it. Here's what got me thinking about it...

Today as we were driving my step daughter home from school, I asked her what she was doing in math these days and she told me they were working with functions. It immediately brought to mind my first foray into Calculus taught by Mr. Musgrave, when "Eff of X" was a phrase I heard constantly yet was NEVER given the understanding of. Every single day I struggled to wrap my mind around what a function really was, what "Eff of X" was really saying, and never managed to until just a few years ago (hence I hobbled by with a mere C in that class). Now that I'm older and wiser, the term is no longer foreign to me and in fact is second nature, as I finally connected the dots between Calculus functions, Javascript functions, Coldfusion functions, and even the functions that occur in nature. What follows is my personal definition of what a function is, accompanied (as usual) by a colorful and simplistic analogy to help illustrate.

The Definition: A function receives something into itself, performs some kind of work on whatever the input was, and spits the results of that work back out. Period.

It can be a math function that accepts a value 'x', plugs it into some equation, and then returns the mathematical result; it can be a programmatic function that receives something into it...be it a numeric value, a string of text, an object, etc....and returns the results of the code it was told to execute. Ah, and here's the clincher, the missing link that will help ANYBODY, I mean even your TODDLER, to completely understand what a FUNCTION is:

Even your own BODY is a function! You give it some kind of input...let's say, a peanut butter sandwich. Your body performs some kind of WORK on that input (in our case, digestion), and VOILA! You get some output. In this case, a turd.

There is absolutely NO difference whatsoever between a calculus function, a programmatic function, the Human function, or even the myriad of individual functions that work in harmony within our own ecosystem. A function receives something in, performs some work on it, and gives something back.

Pass this tidbit on to everyone you know, even and especially your kids, so that perhaps when they too first encounter Mr. Musgrave's endless repitition of "Eff of X, boys and girls, EFF OF X!", they can avoid the mental anguish of trying to grasp something so simple and common sense, yet perpetuated (for some odd reason) as being so deep and abstract.

And now, if you choose to accept, your Assignment:
Find the nearest individual who you think would be least likely to understand what a function is (young or old), take two minutes to teach them the concept using their own body, their Play Doh Fuzzy Pumper Number 9, the oven, or anything else you can think of that they can relate to, and see if their retention of the definition isn't 100% every time you ask them thereafter.

Doug out  :0)
Posted by dougboude at 1:27 AM | PRINT THIS POST! | Link | 1 comment
06 March 2008
What IS 'Business Logic', Anyway?
So I'm having a discussion with my friend Jim the other day about an article he was writing and I give him a suggestion regarding one of his sentences on the subject of encapsulation. He had stated that encapsulation is about hiding data, while I appended the fact that it also hides business logic. This prompted an immediate discussion on the term 'business logic', and what exactly it was and was not. So, I thought it good to share my own personal definition of the phrase in order to solicit the input of others to see if the way I think of it differs significantly from the connotation it holds for the community at large. I'm also adding this to my Personal OO Lexicon for posterity's sake.

Business Logic

So this Controller is sitting at the bar babying a Belvedere Gimlet when he gets a call from his Framework asking him to please provide the value for the current user's next inspection date. A bit perturbed but never one to tarry when the Framework makes a request, he immediately dials his peep, Joe Object, down in the Model district and asks for user 1287's next inspection date. Joe Object quickly does his thing and gives Controller the value he requested, who in turn hands it off to his Framework.

The process that Joe Object went through in order to calculate the user's next inspection date is an example of what is referred to as "Business Logic". It's the process, formula, algorithm, decision tree, methodology, query, magic 8 ball, or any other means used to perform a piece of work that is specific to this application.  'Business Logic' is the answer to the question "How did you get that value?".  Consider this dialogue: "Hey, Joe Object, how exactly did you come up with that inspection date?" asks Controller.  "Since my job is to encapsulate the processes I use, I can't tell you," Joe Object says. "All I CAN say is that I executed the business logic for that particular request and gave the result to you."


As an aside, anything that you the developer would classify as Business Logic (as defined above), is the PERFECT candidate for inclusion in the CFCs that compose your application's MODEL; in fact, I would go so far as to say that it is mandatory that such code reside within your model. The rule I use (which I gleaned from perusing blogs and mailing lists) when deciding if code is business logic or not is this: "If I had to change frameworks tomorrow and the ONLY thing I can take with me is my Model, is this a piece of functionality I would consider to be uniquely associated with this app?"
Posted by dougboude at 8:32 PM | PRINT THIS POST! | Link | 9 comments
08 October 2007
Appropriate Usage of the "THIS" Scope
For the past several days, my good friend Jim and I have been having a series of discussions regarding the use of the 'THIS' scope within CFCs; specifically, CFCs that are to be used in an OO fashion. He's part of a small team that has just begun their OO journey and are embarking on a project where they hope to grow and refine their understanding in this arena. Jim being the stickler for correctness that he is, he often bounces approaches and ideas off of me to see what my take is, as well as compare the code he produces to that of his fellow teammates. Here is where a certain rift has manifested itself among them, as his fellow coders are producing CFCs that make heavy use of the 'THIS' scope and little to no use of 'Variables' and 'Var', while Jim is not using 'THIS' at all and is rather declaring his variables as public within the 'Variables' scope or private using 'Var'.

My personal take on the use of 'THIS' within a CFC (and what I firmly expressed to Jim) is that it would be a rare circumstance when I would see 'THIS' as the appropriate scope, since putting variables into 'THIS' exposes them to actions performed outside of the CFC. Just visualizing a CFC with all it's internal variables in the 'THIS' scope immediately causes me to think, "You've just reduced your object down to a very primitive state...a Transfer Object. Why don't you just rather create a structure to hold those values since you're ACCESSING them as if your object WERE a structure." Basically, I've been telling Jim that using 'THIS', except in very specific circumstances, is a bad thing to do.

His own intuition and experience up to this point tells him the same thing, since his comprehension of 'Variables' and 'Var' is quite clear. He has as of yet, however, been unable to convince his peers of this, and has even been admonished to STOP using 'Variables' and 'Var' and start putting his CFC variables in 'THIS'.

Because Jim is a stickler for learning to do things the "right" way, he set out on a Google journey to find documented proof that what he and I believe regarding 'THIS' is absolutely correct. His search has left him empty-handed, though, and so he and I turn to you, our fellow developers, for input on this topic.

The question then: What are your basic rules of thumb regarding the use of 'THIS' when writing a CFC to be used in an OO application (even a loosely structured one)?

Thanks in advance for sharing your opinion!

Doug  :0)
Posted by dougboude at 11:45 AM | PRINT THIS POST! | Link | 6 comments
02 October 2007
Dumping An Object is Like Taking an X-Ray
an OOP noobie analogy
Lately I've had the privilege of helping a good friend of mine climb "Mt. OOP", and in the process have been able to refine a lot of my own knowledge. I've also discovered that I sometimes make too many assumptions when imparting understandings, and this short post is in regards to one of those items: Dumping Objects.

One thing I always urge my fellow developers to do is to form a solid expectation of what the results will be when the code they're writing is executed.  Well, what I found out is that my friend (and the rest of his team who are just getting their feet wet using objects) were certain that dumping an object should allow them to see EVERYTHING inside of it. Consider the following CFC:

<CFCOMPONENT DISPLAYNAME="FleshAndBones">
    <CFFUNCTION NAME="init" ACCESS="public" RETURNTYPE="any" hint="I return the body with a single organ">
        <CFARGUMENT NAME="initialOrgan" TYPE="string" REQUIRED="yes" hint="I am the first organ to be added to the body">
        <CFSET variables.stBody = structNew() />
        <cfset variables.stBody.organ1 = arguments.initialOrgan />
        <CFRETURN THIS />
    </CFFUNCTION>

    <CFFUNCTION ACCESS="public" NAME="addOrgan" OUTPUT="false" RETURNTYPE="void" hint="I add a new organ to the body!">
        <CFARGUMENT NAME="thisOrgan" TYPE="string" REQUIRED="yes" hint="I am the organ being added">
        <cfset var newKey = "organ" & structcount(variables.stBody) + 1 />
        <cfset variables.stBody[newKey] = arguments.thisOrgan />
    </CFFUNCTION>
</CFCOMPONENT>


Now, consider the following code which creates, initializes, populates, and dumps the "FleshAndBones" object:

<cfset objBod = createobject("component","FleshAndBones").init(initialOrgan="Heart") />
<cfset objBod.addOrgan("Lungs") />
<cfset objBod.addOrgan("Pancreas") />

<cfdump var="#objBod#" />

The expectation was that when dumping an instance of the objBod object, "variables.stBody" should be visible somewhere in the dump. When it wasn't, red flags were raised and a revisiting of the CFC occurred until, by golly, the developer FORCED that variable to show up in the dump! How?  By experimenting with scopes until he found one that allowed it to be visible: the THIS scope. Bad form, Jack. Putting variables into the THIS scope without a VERY good reason is tantamount to circumventing the very purpose of using an object, in my opinion. If you're going to do that you may as well just create a structure and manipulate that since the object will pretty much be behaving the same way. Enough on that, though.

Here is what the dump DOES contain:



To help explain what SHOULD be expected in the dump of an object, I gave my friend an analogy that helped him so much that he said I should definitely share it on my blog, so here it is:

CFDUMPing an object is exactly like taking an X-Ray of the object: You should expect ONLY to see the bones, not the soft innards. The bones of an object are its methods and metadata such as the method hints, return types, incoming arguments, etc. The soft innards are all of the variables, both private and public, that have been declared. It could also be any queries that have been executed, structures that were created, or anything else for that matter. Nothing besides the bones will ever be visible on an X-Ray, so not seeing those other internal items in the content of the dump is perfectly normal and is what SHOULD be expected.

Now, very often you WILL want to see what some of those soft innards of your object are looking like at various times. The answer to that is simply to make sure you have a method present whose job it is to return that particular soft innard, such as the following:

<CFFUNCTION ACCESS="public" NAME="getBody" OUTPUT="false" RETURNTYPE="struct" hint="I return the body!">
    <cfreturn variables.stBody />
</CFFUNCTION>


You can then dump that soft innard like so:

<cfdump var="#objBod.getBody()#" />




So in summary... CFDUMP (and the "getMetaData" function) give you X-Rays of an object. If you want to see the squishy parts, create a method that returns them!

Doug out.
Posted by dougboude at 3:03 PM | PRINT THIS POST! | Link | 0 comments
17 September 2007
Just what IS an Object, Anyway?
Making a distinction between the definition of an Object versus a Class is probably not a vital factor in one's OOP abilities. I believe, however, that if we're going to have and use terms, we should do so accurately in order to effectively communicate. I absolutely hate it when people misuse words in ignorance, such as when someone refers to a Cicada as a Locust (a locust is a grasshopper! a Cicada is a Cicada!), or a bat as a rodent (they're both mammals, but that's as close as it gets). For clarification's sake, then, following is what I have discovered to be the definition of an Object in a Coldfusion context.

When asked the question "what IS an object?", I nearly always respond with a description that includes the phrase "living and breathing". Here's why:

According to science, the basic checklist to use when determining if something is alive or not is:

  • Can it Reproduce?
  • Can it Obtain and use energy?
  • Can it Grow, develop, and die?
  • Can it Respond to the environment?

Once you issue the command

<CFSET objFrankenObject = CreateObject("component","model.Frankenstein") />

Coldfusion takes what is a lifeless blueprint (the Frankenstein.cfc file) and breathes life into it, creating something that meets every one of these criteria!
  • Can this Creation reproduce? It certainly does have the potential, depending on how it was designed.
  • Can it grow, develop, and die? Abso-frickin-lutely! It occupies a certain amount of ram, and I guarantee you that as soon as I call one of its setters and stuff a large structure into it that it will grow and then occupy MORE ram! If I <CFSET objFrankenObject = "", it'll be dead and gone.
  • Can it respond to its environment? Of course; that is what it was created to do in the first place.
  • Finally, can it use and obtain energy? Without spending too much effort in attempting to stretch the analogy into that realm...let's just say 'yes' since our server is plugged into an active outlet.
By all accounts, this Object is a living, breathing, programmatical entity. This way of thinking about objects in contrast to the flat, lifeless CFC/Class (that so often is referred to as an object, erroneously in my opinion) makes the distinction between them crystal clear.

In a nutshell then:

Object = living breathing instance of a CFC (Class)


Again, thinking of objects in this way may not make one a better or worse OO programmer, but it definitely doesn't hurt to have a finer understanding of what the terms truly represent, right?


If you missed the post "Just What IS a Class", it's the complement of this one and might make good prerequisite reading since it defines what an object IS NOT.

(this definition along with all the others I've collected over the past year can be found in my personal OO Lexicon)
Posted by dougboude at 12:34 PM | PRINT THIS POST! | Link | 0 comments
14 September 2007
Just What IS a CLASS Anyway?
OO Terms in a Coldfusion Context
Which phrasing is correct:

1."Hey boss, take a look at this object I just wrote!"
2."Hey boss, take a look at this class I just wrote!"

The answer is number 2. After reading the following definition, hopefully the phrasing in choice 1 will sound strange to you.


The term "CLASS" tends to be misused, or even UNDERused in OO conversations with regard to Coldfusion, and is very often omitted in favor of the term Object. There is, however, an important distinction between the two. Let's illustrate this by asking a simple question that I KNOW you know the answer to.

Can you open a CFC in notepad?

The answer is "Heck yeah!" Why is this true? Because in reality, a CFC is JUST A TEXT FILE with a '.cfc' extension. It's the content, however, of this text file that makes it special, because what it contains are the blueprints that Coldfusion uses to create living breathing objects. So, when you tell Coldfusion something like


<cfset objUser = createobject("component","model.user")>


 you're actually saying "CF, go find the user.cfc file, open it up, read the contents, and give me back a living breathing OBJECT that is built according to the blueprints."

In a very small nutshell then,

A Class is the definition used to create an object.

The class tells Coldfusion what methods to create, what variables are available, what items are returned...gosh, it tells CF every little detail about how the finished product (object) should behave and respond!

Class = CFC = Blueprint
 
For contextual illustration, a Java ".class" file is also just a text file containing the blueprints that Java needs in order to construct a Java object. A CFC is a Coldfusion class containing the blueprints CF needs in order to construct a Coldfusion object.


 The plan...the blueprint...the CFC... it's what the rest of the OO world refers to as a CLASS, and so should you!

(this definition along with all the others I've collected over the past year can be found in my personal OO Lexicon)
Posted by dougboude at 6:12 PM | PRINT THIS POST! | Link | 1 comment
12 September 2007
Reactor: A LOT Like a Wendys Drive Through
Okay, I've been up since 3 A.M (went to bed waaay too early last night) working on a Modelglue project, and now I'm feeling the need to rant a little bit. Not complain, per se, because I truly do appreciate the blood, sweat, and tears that must have gone into creating the frameworks that comprise Unity; But out of the 4 hours I "worked", a full third of it was spent on issues related to trying to get my app to "see" certain kinds of changes, even WITH my cheat sheet (which itself was born out of a lot of time spent pulling my hair and bumping around in the dark). That's just a wee bit much for something that's supposed to help me spend my time more efficiently, wouldn't you agree? In particular, this morning my beef is with Reactor.

Reactor has a Development mode and a Production mode. In theory, I should put this baby in Dev gear and just leave it there until I'm ready for production. But, Dev mode is just plain slow as molasses in January, so I opt rather to work with Reactor in production mode until and unless I make a change directly related to the database. This morning happened to be one where I had added some fields to a table. So I make my table changes, change Reactor to Development mode, and reinit the app. I then walk through my app as a user would to the point where I KNOW this particular table's record object is needed. It HAS to do be done this way, you know. If I didn't, Reactor would not have re-created my object for me, DESPITE the fact that I re-init'd the app, because it is a WHOLE lot like a Wendy's drive-through: neither one creates it until you actually order it. Okay, so now I am able to successfully edit and insert records containing values for these new fields, so I must have ordered my burger right (pun intended). As usual, I now switch back to production mode for efficiency's sake. More testing, and I realize that something's amiss with one of my fields...I'm getting a sql error when trying to do an update after having edited a value. BUT HEY NOW! WAIT JUST A MINUTE! HOW can I be getting a SQL error when I'm using Reactor validation to check values before attempting to insert them? This cannot be! And yet, it is. After fiddle farting around with double checking syntax, making sure quotes were correct, field names and form field names correlated...it finally occurred to me to open up the Reactor validator object for this table, JUST TO MAKE SURE it looked right. Surely it would be right. After all, I KNOW I did what Reactor required of me to regenerate that table's objects. Sure enough, though, no validators existed for the new fields. DANG IT! Apparenly Reactor only regenerated the SPECIFIC Reactor objects I needed for the functions I performed before switching back to production mode. Back to development mode, re initialize the app, walk through as a user to the point where I INVOKED VALIDATION, then all was well.

When I finally DID get everything working well and regenerated in my local environment, I then committed my changes via SVN to the repository and ran the update for our testing environment. We aren't including Reactor's base project CFCs in our repository, so now it was time to switch to dev mode in Test and regenerate. Ay, here I go again, having to login in as a user and physically "touch" the app in a lot of places to force Wendy...er, Reactor, to make my burger. You can imagine how much time it can potentially take when you have to go into the app and USE it in order to make changes happen on the backend like that. And what if you don't know the app from the front end? What if you're job only entails backend work? Then you're either forced to learn the app, or wait for your testers to go in and tell you if it worked or not. Either way, it's not efficient use of time.

My rant is just this: why's it gotta be so painful to use Reactor? Why do I NEED an initialization cheat sheet when developing with it? If I've jumped through the fiery hoop to get Reactor to regenerate my table's record object, why can't it just regenerate ALL of the objects for that particular table in one fell swoop??? WHY am I FORCED to know the app from the FRONTend in order to manifest a change on the BACKend (Reactor's whole, "I won't make it for ya till you order it!" philosophy)? What if all I was hired to do was back end coding and don't know the app well enough from the user's perspective to properly navigate my way through to where my code change lives?

Perhaps I'm just using this awesome tool the wrong way; I don't think so, though.  I've worked with several other people together on MG projects, I've read just about everything out there that has to do with MG:Unity, I've got a LOT of hours logged getting my hands dirty with this framework, and I haven't seen anybody else do it any different than I. If I had a magic wand, I would wave it and miraculously "init=true" really WOULD reinitialize my app completely!  As it stands now though, it's kind of a pain.

Okay, I'm done venting. Thanks for listening. ModelGlue:Unity, I still love you.

Doug out.
Posted by dougboude at 12:29 PM | PRINT THIS POST! | Link | 4 comments
29 August 2007
"My Boss Wants To Know Why We Should Create Objects"
A good friend of mine IM'd me this morning, hot in the middle of a sales pitch to his boss as to why it was a good idea to get away from the Spaghetti paradigm and move towards some semblance of OO methodologies. Our conversation was short and sweet, but I thought I'd toss it out here in case anybody else has anything to add (or correct), for the benefit of any other developer who finds themselves in a similar "sales" position.

The Conversation

MyBuddyJack: My boss wants to know, why do we have to create instances of objects and go that route? Why can't we just use cfinvoke to get the data we need and just code everything an object needs right in the same cfc.
MyBuddyJack: I think he is wanting to code things procedurally, but with cfcs...that's the feeling I get. But what is the advantage to coding it more OO by creating instances etc.?
MyBuddyJack: I just told him it is easier to maintain and change down the road.
Doug Boude: persistence
MyBuddyJack: I couldn't really sell it like I wanted.
Doug Boude: for example, i have a user object. If I instantiate it, then I can keep it alive and interact with it, changing things about it here and there and maintaining those changes throughout the life of the object
Doug Boude: if I just use invoke, I'm treating it as nothing more than a dumb collection of functions
MyBuddyJack: he wants to put everything into the session scope
MyBuddyJack: so everything is always available anywhere
Doug Boude: and what would BE in session? Oodles of variables sitting there beside one another, all in the same bucket, differentiated only by some naming convention, if that?
Doug Boude: using a CFC as an object, you collect related things together, so you always know where to go for a specific thing
Doug Boude: if you didn't use a User object, I'm POSITIVE he'd probably create a User structure that lived in session to hold all of the user's info
Doug Boude: but, the methods he needed to act upon and with that user info would all be living here and there and everywhere...little semblance to anything truly organized and encapsulated.
Doug Boude: to move that user functionality, then, at some later date would be a nightmare because SOME Of the user stuff would live in application.cfm, some of it would live in some UDFs, some would live here, some would live there...no encapsulation
Doug Boude: it would be what we have always been used to: spaghetti
MyBuddyJack: Yeah that's a good point. I told him that if he has an instance of a User Object, then when he wants to output stuff he just calls the object, whereas otherwise he'd have to invoke everytime to get the data he wanted.
Doug Boude: but stuff it all into a user CFC, and voila! it's always packaged up, ready to drop into anything
Doug Boude: invoke is expensive...it instantiates the object first, then calls the method, then destroys the object again
Doug Boude: extra overhead
Doug Boude: why not just breathe life into it ONE time initially and have it waiting to be called upon instead?
Doug Boude: i could only see using cfinvoke under two circumstances
Doug Boude: one, when my CFC is truly just a collection of random methods that I will need on occasion only
Doug Boude: or two, when I need to call dynamically named methods, which isn't possible on an already instantiated object
MyBuddyJack: I think I understand encapsulating everything as a benefit. But is that it? What other beneifts are there to instantiating objects OR why is that better than procedural?
Doug Boude: you can instantiate objects and still code procedurally
Doug Boude: it's really two different things
Doug Boude: using CreateObject does not an OO application make
Doug Boude: like i said, there's the savings of overhead; there's the logical arrangement and grouping of both functions, business logic, and data
Doug Boude: there's the re-usability factor, should that ever be a desire
Doug Boude: if you use objects as the main basis for your app, then one day when the light DOES go off for them and they see the beauty in MVC, moving to a new framework won't be nearly as large a pain
Doug Boude: it's MUCH easier to make modifications to an app when you have things arranged in objects, and without having that old common spaghetti coder's fear, "What else is going to break if i change this?"
Doug Boude: but putting things into CFCs and then using CFINVOKE to interact with them is like starting your car long enough to get you to the first stop sign, then turning it off again. then starting it up again when you're ready to proceed, then turning it off again at the next red light. etc.
Doug Boude: in that analogy, it almost looks...ridiculous to do it that way
Doug Boude: and, it's easy to see the extra overhead involved with that analogy...extra wear and tear on your starter, extra time needed to actually respond to the light turning green, etc. Same thing in an app
Posted by dougboude at 10:58 AM | PRINT THIS POST! | Link | 3 comments
The Model-Glue Event Lifecycle in Layman's Terms
Okay, actually there's no way to COMPLETELY distill this topic down to the point where you don't have to have a decent understanding of web development to grasp it. BUT, I do believe that I've been able to demystify the subject sufficient to allow even the beginner OOP/Model-Glue developer to "get it", which is what I wish I would have had a year ago when I left the comforts of procedural and embarked on my OO journey. That being said, this post is not one of the shorter ones I've done; necessarily so, as there's a lot of ground that I felt couldn't afford to be skimmed over. By taking the time to read through it, however, I do believe that a LOT of the "gray areas" that we OO newbies face, architecturally speaking, will be cleared up enough to at least give us a clue which direction to go. That being said, what follows is my PERSONAL understanding (which has worked well for me) of the Model-Glue Event Lifecycle. Enjoy.

UNDERSTANDING THE MODEL-GLUE EVENT LIFECYCLE

The Model-Glue framework can present an intimidating learning curve when coming directly out of the procedural world to that of Object Oriented Programming. One of the things that will help the Model-Glue student immensely is to have a solid understanding of how the Model-Glue event lifecycle works: being able to visualize the invisible. With this knowledge in pocket, many of the architectural questions that will inevitably arise will be more easily addressed. So, let’s explore what we mean by the term ‘lifecycle’, what the definition of ‘event’ is in a Model-Glue context, and what Event’s role is in a Model-Glue application!


 A Lifecycle You Already Understand

 Let’s look at a lifecycle you’re already familiar with: http request. Pictures are worth a thousand words, so allow me to illustrate this:


Looks familiar, doesn’t it? The request begins life when the client initiates it with an http call to our web server for a specific template. The server receives the request, grabs the template requested, and hands it over to the Coldfusion server for processing. The Coldfusion server renders the CFM template into pure HTML (since that’s all a browser understands), hands the HTML back to the web server, and the web server returns the HTML to the client. End of the request’s lifecycle!

 
When a client makes a request of a Model-Glue application, a similar process takes place. The focus of this post will begin (and end) at the point where index.cfm is requested and passed a parameter called “event” (eg; http://www.myMGapp.com/index.cfm?event=home). The receipt of this parameter is the first breath our Model-Glue application draws, and begins the internal process which we will now follow through to its conclusion.

 

What Exactly IS A Model-Glue Event?

‘Event’ is two distinct things:

  • ‘Event’ is a simple value: a name, such as ‘home’, or ‘do.login’ (yes, compound event names are acceptable and even advantageous for organization’s sake!);
  • ‘Event’ is a bucket.

 
 “A bucket?”, you may be asking yourself. Yes, a bucket! Buckets carry things around, and at a certain point in our event lifecycle study we will see how the event changes from being simply a name to an actual value-carrying OBJECT that gets passed around within the application! It’s a beautiful metamorphosis, as you will see.

 The Event Lifecycle in a Nutshell

 

Let’s begin with an overview of what takes place in the lifecycle of a Model-Glue event (We’ll be exploring each step in detail later):

  1. A request is made, notifying model-glue to execute a specific event (eg; http://www.myMGapp.com/index.cfm?event=do.login). At this point, Model-Glue generates an empty Event Object (aka: bucket).
  2. Model-Glue looks in its modelglue.xml file to find out what messages to broadcast to listening controllers ( <broadcast><message name="login" /></broadcast> ) for the 'do.login' event.
  3. Controllers listening for the "login" message execute their corresponding functions ( <controller name="AuthenticationController" type="controller.AuthenticationController"><message-listener message="login" function="AuthenticateUser" /></controller> ).
  4. Model-Glue executes any relevant result actions (behaves as an 'if' statement), if present.
  5. Model-Glue renders any views that are defined for this event. HTML is delivered and the event lifecycle is over.

 
Event Lifecycle, Step One: Create the Event Object (aka: bucket)

 
The whole event lifecycle depends upon values being passed around within the application, so the first thing Model-Glue does after being notified which event to execute is to create an Event Object. Just visualize it as a bucket at this point.

 After the Event object is created, any incoming form fields and URL parameters are immediately stuffed into it for safekeeping.

 
Event Lifecycle, Step Two: Reading the Event Definition

 Now that Model-Glue has the Event Object all populated with incoming values, it’s time to discover exactly what should be done with them for the event name that was called. The instructions, or event definitions, that Model-Glue refers to when an event name is received all live in an XML document called “Modelglue.xml”. Here is what an event definition looks like:
 

<event-handler name="do.login">

            <broadcasts>

                        <message name="login" />

            </broadcasts>

            <results>

                        <result name="success" do="home" redirect="true" />

                        <result name="failure" do="login" redirect="false" />

            </results>

            <views />

</event-handler>


Summary of steps 1 and 2

The <event-handler> tag has three children: <broadcasts>, <views>, and <results>, and they are evaluated in that order. Let’s look at each one more closely, following our Event Object through the process.

 

Event Lifecycle, Step Three: Giving Shout-Outs (aka: making broadcasts)

 The first thing Model-Glue does for a given event is to make any defined broadcast. A broadcast is simply a shout out that triggers certain CFCs to execute specific methods. In our example, the broadcast “login” is made. Model-Glue looks in another section of its Modelglue.XML file to find out what CFCs are “listening” for that particular message, then executes the relevant method. In this scenario, this is what Model-Glue found in it’s XML file:

 <controller name="AuthenticationController" type="controller.AuthenticationController">

            <message-listener message="Login" function="Login" />

            <message-listener message="Logout" function="Logout" />

</controller>

 
Ah, so Model-Glue is going to invoke the “Login” method of the AuthenticationController.cfc (which lives in the “controller” directory). Here is an important thing to know at this point: for every method that Model-Glue calls, the Event Object that was initially created and populated will be passed in as an argument, like so:

 <cffunction name="Login" access="public" returnType="void" output="false">

            <cfargument name="event" type="ModelGlue.Core.Event" required="true">

            ….

</cffunction>

 
Why? So that our methods can read values out of it (such as the username and password that were passed in via our login form) AND so our methods can put values INTO the bucket as well! In our example, the Login method is going to attempt to authenticate a user. If it succeeds, it’s going to add a ‘Success’ result to the Event bucket; if authentication fails, it’s going to add a ‘Failure’ result.


Summary of Step 3

Okay, the “Login” method finished, Model-Glue has the Event Object in hand, and there are no more broadcasts defined for this event, so let’s go on to the next step in the Lifecycle.

 

Event Lifecycle, Step Four: Decide What Results to Execute

 Take a look at the <results> section of the event definition. We see two named results defined (so called because each of them has been given a specific name): success and failure. Recall how our Login method added one of two possible results to the event bucket, either “Success” or “Failure”. At this point, Model-Glue looks for any results in the Event bucket and executes whichever one is appropriate. Executing a result really just means “hey Model-Glue, you found a result named “Success”, eh? Then I want you to jump to the defined event named “home” and execute that now.” If a result named “Failure” had been found, then the “login” event would have been called, presenting the user with the login form again. When Model-Glue executes a named result and jumps to another event, the programmer has two choices at this juncture. To start the new event fresh with an empty Event object, or to carry the existing, populated Object over to the next event. This is controlled with the <result> attribute “redirect”. If set to ‘True’, a new, empty Event object is created; if set to “False’, the original Event Object is passed along.

Summary of Step 4

At this point, all of our messages have been broadcast and relevant methods executed; if we needed to redirect to another event, that was also already accomplished. We’ve now arrived at the final step in the event lifecycle: Render our HTML and send it back!

 

Event Lifecycle, Step Five: Render The Views!

(aka: create the HTML that will be passed back)

 Since our “do.login” event was all about actions and not views, let’s look at the “home” event that a successful login attempt redirects us to:

 <event-handler name="home">

            <broadcasts />

            <results />

            <views>

                        <include name="body" template="dspMainContent.cfm" />

                        <include name="final" template="dspLayout.cfm" />

            </views>

</event-handler>

 This particular event doesn’t ask Model-Glue to make any broadcasts nor does it ask Model-Glue to look for and process any results. What it DOES do, however, is ask Model-Glue to render two different CFM templates, dspMainContent.cfm and dspLayout.cfm. There are several important things to note here.

 First, that we can tell Model-Glue to render any number of individual CFM templates. Second, notice how each template is given a “name” attribute…the rendered HTML will later be referred to by this name. Third, the order we list them in is irrelevant with one WHOPPING exception: the last template rendered is the ONLY one that Model-Glue will return to the browser. So what happens to the other Views that were rendered and placed onto the Viewstack (notice how I just increased your Model-Glue vocabulary ;) )? All other rendered templates are “included” in the final template, in nearly EXACTLY the same manner as using a CFINCLUDE, only slightly different. See a previous post I did on Views called “Model-Glue Views Demystified” for more detailed information on this topic. Now, let’s find out where our Event Object/Bucket is relative to the views that are being rendered, shall we?

 Model-Glue makes the contents of the Event Object available to your CFM view templates in an object referred to as “ViewState”. It, too, is an object, very similar to the Event Object, and it contains all the values that your template could possibly need. You may be asking yourself, “why do we need the ViewState Object if we already have a perfectly good Event Object?”. Valid question, and the answer lies within the philosophy of object oriented programming and the two cardinal virtues that a framework like Model-Glue seeks to uphold: Encapsulation and Autonomy. Suffice it to say that in order not to violate basic MVC principles, copying the contents of the Event Object into the ViewState Object was the better thing to do. Okay, take a look at the following two lines of code taken from within a view template:

 <CFSET firstname = ViewState.getValue("firstname") />

 <CFOUTPUT>Welcome, #firstname#!</CFOUTPUT>

 Any CFM template created for use within a Model-Glue application can absolutely count on the presence of “ViewState”. The value “firstname” that we’re retrieving from ViewState is a value that was placed in the Event Bucket at some point previously in the event lifecycle, likely by one of our broadcasts. Are you seeing the beauty of the Event Object yet? From the beginning of our event call, that bucket was passed around here and there, values being put into it, redirections being made as needed, until finally we arrive at our views where all of the previously saved values are made available for use within your templates. Strings, Arrays, Structures, Queries, and even other Objects can be stuffed into the Event Bucket and made available via ViewState. No limitations in that arena!

Slightly off topic from this article, let’s quench some curiosity and sneak a quick peek at how the final view being rendered includes content previously rendered in the viewstack, in this case, how “body” is output within “final”. Take a gander at the following few lines of code:

 <cfset body = ViewCollection.getView("body") />

 <div class="contentbody">

<cfoutput>#body#</cfoutput>

</div>

Yes, it’s really that simple. All rendered views are placed onto the viewstack, referenced by the name we gave them in the event definition, and are available within our template by accessing the “ViewCollection”.  Again, for more detail on Model-Glue views, see the “Model-Glue Views Demystified” post.

Views all rendered and the final HTML complete, Model-Glue returns it to the web server, which in turn returns it to the browser that requested this particular event in the first place.


Summary of Step 5, and the end of our Event Lifecycle

This is the end of our Event’s life; it is disposed of properly. RIP.

 
One Final Bit of Trivia

If you’re curious about what the Event Object really looks like, here’s a CFDUMP showing it and its methods:


CFDUMP of the Event Object

Conclusion

 As its name implies, Model-Glue is a framework that allows a developer to create code that is truly self-contained and reusable by acting as the glue that binds all the pieces together. It accomplishes this by managing the one common denominator that the Model, View, and Controller all have in common: The Event Object. From the client’s initial call to the final delivery of the requested HTML to the browser, it is the Event Object that the developer must understand and interact with in order to create a working application. Only a mid-level understanding of the event lifecycle is required to meet the majority of architectural needs. How to incorporate security, how to ensure the display of appropriate navigation, how to easily add in new functionality: these are all common challenges that understanding the Model-Glue event lifecycle will enable any developer to overcome.

Posted by dougboude at 1:04 AM | PRINT THIS POST! | Link | 4 comments
13 August 2007
OO Lexicon Available as Webservice
Some time back someone asked me if I would consider exposing my personal OO lexicon as a webservice. My answer was yes. However, I didn't get around to doing it until just today. I've decided to secure it, so if you're interested in consuming it, just email me (email address buried in my funky "Yahoo Personals" style resume) and I'll likely give you access to it. Okay, here are the particulars:

webservice address: http://www.dougboude.com/webservices/DBLEXICON.cfc?wsdl

Return type: either XML or native CF Query, that's up to the consumer

Sample call and processing for XML return:
<cfset ws = createobject("webservice","http://www.dougboude.com/webservices/DBLEXICON.cfc?wsdl") />
<cfset lex = ws.getLexicon(username=[your username],password=[your password],toXML = 1) />
<cfset xPath = "//ITEM">
<cfif isxml(lex)>
    <cfset terms = xmlSearch(lex,xpath)>
    <cfoutput>ITEM COUNT: #arraylen(terms)#</cfoutput>
    <br>
    <cfloop from="1" to="#arraylen(terms)#" index="i">
            <CFOUTPUT>#terms[i].Category.xmlText# <STRONG>#terms[i].term.xmlText#</STRONG> - #terms[i].definition.xmlText#</CFOUTPUT><br />
    </cfloop>
</cfif>

Sample call and processing for CF Query return:
<cfset ws = createobject("webservice","http://www.dougboude.com/webservices/DBLEXICON.cfc?wsdl") />
<cfset lex = ws.getLexicon(username=[your username],password=[your password],toXML = 0) />
<cfoutput query="lex" group="category">
        <h2>#lex.Category#</h2>
        <cfoutput>
            <STRONG>#lex.term#</STRONG><br />#lex.definition#<br />
        </cfoutput>
        <hr />
</cfoutput>

Since I'm requiring authentication upon invocation, and since the contents of the lexicon aren't changing all that often, I recommend that you just cache the results after the first call and refresh once a day or so.

Oh, one last thing while we're on the subject...

I know that my lexicon is much less than fully comprehensive, so if anybody has any suggested terms to add and a starter definition to go along with it, I'd be glad to consider them for addition.

Doug out.
Posted by dougboude at 5:56 PM | PRINT THIS POST! | Link | 4 comments
02 July 2007
Basic Event Security in Model-Glue Applications
To anyone who has not yet breached the subject of model-glue event security, it can potentially be confusing at first, so I thought I'd share my approach to it in case it helps save someone a little time.

Understanding and being able to visualize the life-cycle of a Model-Glue event is a prerequisite to really grasping event security, so let me share my take on what a brief overview of that life-cycle is.

  1. A request is made, notifying model-glue to execute a specific event (eg; http://www.somesite.com/?event=fireinthehole )
  2. MG looks in its modelglue.xml file to find out what messages to broadcast to listening controllers ( <broadcast><message name="blowitup" /></broadcast> ) for the 'fireinthehole' event
  3. controllers listening for the "blowitup" message execute their corresponding functions ( <controller name="bombController" type="controller.eodGuy"><message-listener message="blowitup" function="BlowInPlace" /></controller> )
  4. MG executes any relevant result actions (acts as an 'if' statement almost) if they exist
  5. MG renders any views that are defined for this event
  6. The event lifecycle is over.

So, now that we know the flow of a named event within Model-Glue, it's time to add in a security check to make sure the current user has permission to execute that event. In my scenarios typically I have private and public events (those that can be executed without being logged in (such as the 'login' event itself), and those that require previous authentication (such as 'manageAccount')) and events requiring a specific role (such as viewing billing reports).
What we will effectively do is slide in some functionality between the event request and the execution of the event itself by leveraging OnRequestStart. This functionality will either allow the named event to pass on through OR redirect the user to the event we want them to arrive at. For instance, if they attempt to access an event that requires login and we intercept that event, we'll redirect them to the login page.

Here's the process for putting the named event check functionality in place:

1.Create a function that checks the current event name against a given list of event names;
2.Register that function to be called at 'onRequestStart';
3.In the Modelglue.xml file, create an event called "modelglue.OnRequestStart";
4.Within the modelglue.OnRequestStart event, register named results and provide appropriate redirection values;

What's going to happen then during the event life-cycle is that, before the actual named event executes, any controllers listening for the 'onRequestStart' message will execute their functions. One of those functions will have the sole job of verifying that the event being requested is allowed to be called in the current session state (logged in, not logged in, is an admin, etc.) If the event is good to go, the function is finished. If the event should NOT be allowed to execute, the function will set a model-glue named result. Next, since we defined an event called modelglue.OnRequestStart, that event is evaluated before any named events. The only thing we have defined for it to do is to look for specific named results and if one of them is found, perform the appropriate redirection. If none of the results being watched for are present, the named event executes normally.

I know at this point there must be a lot of questions on how to actually implement what I've been describing at a high level, so here are the same steps with snippets you can use:

1.Create a function that checks the current event name against a given list of event names;
In our scenario, let's assume two things: that we have events we want to require security, and events that we want to require that the person logged in also be an administrator.
<CFFUNCTION name="checkEvent" access="public" returntype="void" output="false">
    <CFARGUMENT name="event" type="any">
    <CFSET var eventname = arguments.event.getValue(arguments.event.getValue("eventValue")) />
    <CFSET var user = arguments.event.getValue("currentUserObject") />
    <CFIF not user.getUserID() and not listFindNoCase("login,signup,forgotpassword,sendpassword", eventname)>
        <!--- if we aren't logged in AND the event we're calling is NOT a public event... --->
        <CFSET arguments.event.addResult("LoginNeeded") />
    <cfelse><!--- we are logged in. If this event is in our list of events requiring admin login, check to see our user is an admin. if not, redirect them to home. --->
        <cfif listFindNoCase("admin.home,admin.billing,admin.creditAccount", eventname)
                and not user.getRole("Admin")>
                <CFSET arguments.event.addResult("AdminNeeded") />
        </cfif>
    </CFIF>
</CFFUNCTION>


2.Register that function to be called at 'onRequestStart';
<controller name="MyController" type="controller.Controller">
    <message-listener message="OnRequestStart" function="checkEvent" />
</controller>

3.In the Modelglue.xml file, create an event called "modelglue.OnRequestStart";
and
4.Within the modelglue.OnRequestStart event, register named results and provide appropriate redirection values;
<event-handler name="modelglue.OnRequestStart">
    <results>
        <result name="LoginNeeded" do="login" redirect="true" />
        <result name="AdminNeeded" do="home" redirect="true" />
    </results>
</event-handler>

As with anything Model-Glue or OO, there's always greater levels of detail to be expounded upon, but these snippets are more for illustrative purposes than actual 'out of the box' code, so I'm leaving a lot of the details to you. Such as where you should really store your lists of named events, or how your user object is always present, empty or populated, regardless of whether or not the user is authenticated, etc.

Anyway, hope this helps get somebody over the hump!
Posted by dougboude at 3:27 PM | PRINT THIS POST! | Link | 2 comments
20 June 2007
Circular Dependency Experiment
Circular Dependency is a phrase used to describe two objects who both use one another internally. That's simple enough. But...how the heck do those two OBJs get inside each other? And how do they behave once they're in there? These were some of the questions I needed answers to, and so I'd like to share with you my experiment and some of the things it taught me about circular object dependency.

I basically had the following questions I wanted to answer:

  1. How can I successfully get instantiated objects inside one another?
  2. Once instantiated, does object 2's manipulation of its internal copy of object 1 affect object 1's state, and vica versa?

Getting Objects Inside One Another
Okay, so how do we get an object inside another object? We inject it (embrace the phrase, you're gonna hear it a lot in the OO world!). With Coldfusion CFCs, this can be done one of two ways that I'm aware of: using "Setter Injection", or "Constructor Argument Injection". The Coldspring framework does that very thing for us when we leverage it in our apps, BUT I wanted to know what the raw, manual process of doing so looked like, so I created two sets of rudimentary CFCs, each of which has circular dependencies within them.

The first set (CFC1 and CFC2) have dependencies which utilize setter injection; The second set (CFCA and CFCB) use constructor arguments to get inside each other. CFC1 and CFC2 are identical, code-wise, as are CFCA and CFCB. Here is what they look like:
CFC1 and 2:
<cfcomponent displayname="CFC1 and CFC2">
    <cffunction name="init" access="public" returntype="any">
        <cfreturn this>
    </cffunction>
    <cffunction name="getMyName" access="public" returntype="string">
        <cfreturn variables._myname />
    </cffunction>
    <cffunction name="setMyName" access="public" returntype="void">
        <cfargument name="newname" type="string" required="true" />
        <cfset variables._myname = arguments.newname />
    </cffunction>   
    <cffunction name="getObj2" access="public" returntype="any">
        <cfreturn variables._obj2 />
    </cffunction>
    <cffunction name="setObj2" access="public" returntype="void">
        <cfargument name="obj2" type="any" required="true" />
        <cfset variables._obj2 = arguments.obj2 />
    </cffunction>
</cfcomponent>

(The Setter Injection method, as seen in CFC1, simply utilizes a "setObj2" method to set an internal variables-scoped variable to hold an instantiated copy of CFC2)


CFCA and B:
<cfcomponent displayname="CFCA and CFCB">
    <cffunction name="init" access="public" returntype="any">
        <cfargument name="obj2" type="any" required="true" />
        <cfargument name="myName" type="string" required="true" />
        <cfset variables._myName = arguments.myName />
        <cfset variables._obj2 = arguments.obj2 />
        <cfreturn this>
    </cffunction>
    <cffunction name="getMyName" access="public" returntype="string">
        <cfreturn variables._myname />
    </cffunction>
    <cffunction name="setMyName" access="public" returntype="void">
        <cfargument name="newname" type="string" required="true" />
        <cfset variables._myname = arguments.newname />
    </cffunction>   
    <cffunction name="getObj2" access="public" returntype="any">
        <cfreturn variables._obj2 />
    </cffunction>
    <cffunction name="setObj2" access="public" returntype="void">
        <cfargument name="obj2" type="any" required="true" />
        <cfset variables._obj2 = arguments.obj2 />
    </cffunction>
</cfcomponent>

(Notice that I still do have setters and getters for obj2; I didn't really have to have a setter, but the getter is needed so I can retrieve obj2 and call its methods)

Here is the code I used to instantiate CFC1 and CFC2 using the Setter Injection method:
<cfscript>
    //circular dependency using setter injection...
    obj1 = createobject("component","CFC1").init();
    obj2 = createobject("component","CFC2").init();
    obj1.setMyName(newname="Object 1");
    obj1.setObj2(obj2);
    obj2.setMyName(newname="Object 2");
    obj2.setObj2(obj1);
</cfscript>

Here is the code I used to instantiate CFCA and CFCB using the constructor argument method:
<cfscript>
    //circular dependency using constructor argument injection
    objA = createobject("component","CFCA");
    objB = createobject("component","CFCB");
    objA.init(obj2 = objB.init(obj2 = objA,myName="object B"),myName="object A");
</cfscript>

Okay, everything instantiated without any errors! Cool, and I have answered my first question. Now for question 2...

Object Behavior
How do these objects behave when set up in this fashion? To find out, I conducted interviews with each of the objects. Following are some exerpts and code snippets from those interviews (full interview can be seen here):

Interviewing obj1...

Q: What is your name?
A: My name is Object 1!
My name is #obj1.getMyName()#!
Q: What is your dependent object's name?
A: My dependent object's name is Object 2!
My dependent object's name is #obj1.getObj2().getMyName()#!

Interviewing obj2...

Q: What is your name?
A: My name is Object 2!
My name is #obj2.getMyName()#!

Q: What is your dependent object's name?
A: My dependent object's name is Object 1!
My dependent object's name is #obj2.getObj2().getMyName()#!

Q: Can you change your dependent object's name?
A: I don't know...let's give it a try, shall we?
(lots of grunting and straining sounds can be heard...)
<cfscript>
    obj2.getObj2().setMyName(newname="Eduardo");
</cfscript>

I think I did it! My dependent object's name is NOW Eduardo!
I think I did it! My dependent object's name is NOW #obj2.getObj2().getMyName()#!

Interviewing obj1 again...

Q: What is your name NOW, obj1?
A: My name is Eduardo!
My name is #obj1.getMyName()#!

Q: Why don't you go ahead and try to change YOUR dependent object's name...
A: Sure thing! My dependent object's new name is Florence. He he he he he.
<cfscript>
    obj1.getObj2().setMyName(newname="Florence");
</cfscript>
My dependent object's new name is #obj1.getObj2().getMyName()#. He he he he he.

Interviewing obj2 again...

Q: Obj2, is that really your new name?
A: Lemme check... Florence...yep!
Lemme check...#obj2.getMyName()#...yep!

I conducted the same interview with objA and objB, and the answers were identical.

My Conclusion
Circular dependencies, in my experiment, are nothing more than providing each object with a proper internal reference to the instance of the other object, in a reciprocal fashion. The fact that I could change the value of a variables-scoped variable in an injected instance of obj2, and that change be visible by obj2 itself from outside of obj1 proves that point unequivocably. Just for fun, I asked one final question of Obj1:

One Final Deep Question for obj1...

Q: Obj1, what is the name of your dependent object's dependent object's dependent object's dependent object?
A: It's name is Florence
It's name is #obj1.getObj2().getObj2().getObj2().getMyName()#


Cool stuff. Remember though, Coldspring is there for you to manage all of this so that you don't HAVE to do it manually. Coldspring can perform even deeper work, too, like injecting individual METHODS into objects on the fly! That's a little thing I like to call Aspect Oriented Programming, or AOP. You should take the time to investigate it.

Doug out.
Posted by dougboude at 2:26 PM | PRINT THIS POST! | Link | 3 comments
Just What IS Circular Dependency?
Circular dependency.

Initially, the phrase invokes visions of things that we naturally know to steer clear of, like infinite loops. If we've come to OO from a procedural world, we've probably been groomed to fear circular dependency in coding, reinforced by having encountered errors that demeaningly declared "Can't resolve circular dependencies, Idiot!". Circular dependency...it just sounds dangerous, doesn't it? Unstable, unpredictable, uncontrollable; without an end and without a beginning, as in the proverbial question of the chicken and the egg. In OO though, circular dependency needn't be a taboo phrase at all.

When you take a look at the natural world (of which Object Oriented methodologies are a rough emulation of), circular dependencies are common occurrences, and actually viewed as good things. I need my job and my job needs me. That's circular. I need my spousal unit and my spousal unit needs me. That's got a roundness to it, too (pun intended).  But, even deeper than the "we need each other" view, circular dependency implies that each of the two are within one another. Kinda like the ol' Frampton song, "I'm in you....you're in meEEeeeee....". A circular dependency in code is exactly the same thing: two objects who depend on one another for something and exist within each other. My user service needs my address service, and my address service needs my user service. We shouldn't be looking for ways to break these guys up! Rather, let us look at their relationship with admiration, because it is a perfectly natural one.

Now, some architects (we're ALL architects to some degree) might hold fast to a rule of "No Circular Dependencies", and rather than have two objects dependent upon one another directly, they'll create a third object to act as the broker between them. Instead of the two objects being injected into one another, those same two objects are instead injected into the third object, who orchestrates how they work together. I wouldn't say this is a bad thing, and in fact probably makes perfect sense to do so in many situations. Bottom line, though, is that we don't have to avoid circular dependency relationships when they do make sense.

All this talk about circular dependencies got me to wondering just how it all works under the covers. For instance, if I instantiate a CFC that needs another CFC internally, how can I do that without having first instantiating the OTHER CFC (who itself needs an instance of the first CFC I haven't instantiated yet!)? And if I DO manage to get instances injected into one another, will they be by ref or by val? In other words, will object 1 have a copy of object 2 inside of it, and my object 2 have a copy of object 1 inside of it? Or, will they both actually be seeing one another real time? Time for an experiment in object dependency! I'll share the results very soon.

Doug out.

P.S. Here is the link to my circular dependency experiment. (http://www.dougboude.com/blog/1/2007/06/Circular-Dependency-Experiment.cfm).  It REALLY helped clear some things up regarding how to "think about" this topic.
Posted by dougboude at 1:33 PM | PRINT THIS POST! | Link | 1 comment
10 June 2007
Global Configuration Settings in Model-Glue:Unity
Some Suggestions
When making the transition from procedural CF to OO, sometimes what was SO simple before can become a challenge (at least the first time). For instance, the way we used to pass around our app's DSN value was probably something along the lines of setting an application variable in our application.cfm or cfc, thus making it accessible throughout our app while consolidating the value to a single location for ease of change later. But now that we've decided to force ourselves to learn to do things in an OO fashion, where on earth is the "correct" place, or what is the "correct" way to perform this same action?

In our procedural apps, common sense told us to "find a place within the execution path that always gets called, no matter what, and check for and set your global value there...". Let's use that same line of thinking for our OO app, too, and find an appropriate spot in which to set our global variable.

Even in an OO approach, CF still respects application.cfc/cfm, so setting the value there could be an option. However, one of the chief tenets of OO is encapsulation, meaning that we try to make each aspect of the application as non-dependent as possible on the rest of the application. Setting our DSN in application.cfc/cfm then means that likely our urge would be to stuff it into the application scope:

<cfset application.dsn = "Horton" />

If I want to use that value within any of my model CFCs then, SOMEWHERE I'd have to write a line of code that talks to the application scope; not a best practice, and indeed immediately makes my CFC dependent on the existence of some value outside of itself. No bueno.

How 'bout instead we utilize a configuration bean...a tiny object whose sole purpose in life is to pack around global values I might need here and there, and to make itself available anywhere within my app? Now that makes my common sense tingle with delight. Utilizing Model-Glue:Unity, let me share a couple of ways I have done this very thing.

At this juncture, if you aren't familiar with the member of the Model-Glue: Unity trinity called Coldspring, it's time you two met. Coldspring is an expert bean handler, and is quite a versatile fellow when it comes to creating beans and making them available wherever you'll be needing them. Coldspring does all of what it does based on the content of its XML configuration file (Coldspring.XML), so it is within that file where we will 'instruct' it regarding our configuration values.

At this point you're probably thinking to yourself, "okay self, all I need to do then is create a CFC that handles configuration values for my app. I'll make a getter and setter method for my DSN, one for my images directory path, one for....". Hey, that is definitely a good way of thinking. HOWEVER, Coldspring has a surprise for you, O Best Beloved. Coldspring can automagically create that configuration bean for you, and all you gotta do is tell it what you want it to contain via the Coldspring.XML file! Allow me to
elucidate.

In order to auto-create one of these configuration beans, let's define it within Coldspring.XML, like so:
  <bean id="AppConfiguration" class="ModelGlue.Bean.CommonBeans.SimpleConfig">
    <property name="Config">
      <map>
    <!-- this is the DSN used throughout the app... -->
        <entry key="DSN"><value>Horton</value></entry>
    <!--  path the CSS directory -->
        <entry key="CSSPath"><value>/appCSS/</value></entry>
      </map>     
    </property>
  </bean>
(Note: Notice the class of our configuration bean...we're leveraging a built-in class of model-glue)

Now that we've defined it, from this moment onward we'll maintain our app settings RIGHT THERE. If the DSN changes, I'll change the value of the DSN entry key.

Making this configuration bean available throughout the app is a purposeful endeavor, meaning that you have to explicity tell Coldspring to make it available to a specific CFC. We do this by "injecting" it into other CFCs that we've told Coldspring about. Looky here:

  <bean id="EmailService" class="model.EmailService">
    <constructor-arg name="AppConfiguration">
      <ref bean="AppConfiguration" />
    </constructor-arg>
  </bean>

I've told Coldspring "I have an EmailService.CFC, and it is expecting an argument value named 'AppConfiguration', so when you instantiate EmailService for me, please go ahead and pass in an instance of my AppConfiguration bean as that value. Thanks man."

Okay, the only other thing you have to do in order for this to work smoothly is to ensure that the object you're wanting to inject the configuration bean into is prepared to receive it. With the approach we're taking, the proper way to do this is to make sure your CFC has an init method, and within that init method create a required argument named exactly the same as your constructor-arg name. Like so:

<cffunction name="init" returntype="EmailService" output="false" hint="Constructor">
    <cfargument name="AppConfiguration" required="true" />
    <cfset variables._config = arguments.AppConfiguration />
    <cfreturn this />
</cffunction>

Okay, so now we have our Coldspring simple config object injected. Pay attention, this is important: for every value we defined for this config object, you will access it via the following method: getConfigSetting([value name]). For instance, if within our EmailService object we have a method that needs the DSN value, we'll grab it with
<cfset myDSN = variables._config.getConfigSetting("DSN") />

Alternatively (and this is what I did), you can create a generic "GetConfigSetting" method within your recipient object, like so:

<cffunction name="GetConfigSetting" access="private" returntype="string" output="false">
    <cfargument name="name" required="true" type="string" />
    <cfreturn variables._config.getConfigSetting(arguments.name) />
</cffunction>

With that method present in your recipient object, you would access the DSN like this:

<cfset myDSN = GetConfigSetting("DSN") />


It's a little cleaner, I suppose.

Now, you could be thinking that since your config object contains values that may also be needed within a view, such as a CSS path, or an images directory path, that you'll need a way to make it available there, too. Let me toss out a suggestion based on the way I have done it.

Everytime a MG:U event is called, you can have listeners that execute beforehand based on the fact that they're listening for a call to "OnRequestStart", as in this snippet from my modelglue.XML file:


<controller name="MyController" type="controller.Controller">
   <message-listener message="OnRequestStart" function="loadConfiguration" />
</controller>

You can, within the method being referenced in onRequestStart, stuff the configuration bean into the event object, thus making it available to every other object referencing that event, INCLUDING your views! Let's look at the controller object mentioned in this example:

<cfcomponent displayname="Controller" extends="ModelGlue.unity.controller.Controller" output="false">
    <!--- Autowire / private getter --->
    <cffunction name="setAppConfiguration" access="public" returntype="void" output="false">
        <cfargument name="AppConfiguration" required="true" type="any" />
        <cfset variables._config = arguments.AppConfiguration />
    </cffunction>
    <cffunction name="getAppConfiguration" access="private" returntype="any" output="false">
        <cfreturn variables._config />
    </cffunction>


    <!--- Place the configuration bean into the viewstate --->
    <cffunction name="loadConfiguration" access="public" returnType="void" output="false">
      <cfargument name="event" type="any">
      <cfset arguments.event.setValue("appConfiguration", getAppConfiguration()) />
    </cffunction>
</cfcomponent>

A few things to point out here:
1. Because this object is a controller object, Coldspring gives us the privilege of autowiring in beans that it knows about by simply providing it with a "get" and "set" method named according to the bean we want to inject. In this instance, Coldspring already had created for us a bean called AppConfiguration, so by virtue of the fact that Coldspring saw our controller object had a method named "getAppConfiguration" and "setAppConfiguration", it assumed we wanted it to inject an instance of the AppConfiguration bean. Coool.
2. On request start, Model-Glue is calling our "loadConfiguration" method, which is taking the injected configuration bean and placing it into the Event bucket (some like to call it the event 'bus', but thinking of it as a bucket makes more sense to me). This automatically means that the configuration bean will be available in our viewstate as well, and from within any view can be referenced like


<cfset appConfig = viewstate.getValue("appConfiguration") />

<link rel="stylesheet" type="text/css" href="<cfoutput>#appConfig.getConfigSetting("CSSPath")#</cfoutput>styles.css" media="screen" />

Now, having shared all of that, I will tell you that if you're using Reactor within your app, you were already defining the DSN within the Coldspring Reactor Bean, and may not want to define the DSN twice, but rather would like to use Reactor's DSN value throughout your app. This can be done just as easily, only you'll be injecting not your appConfiguration bean into the CFCs that need the DSN value, but the "reactorConfiguration" bean instead (already exists within your Coldspring.xml file). Once injected, you'll get at your DSN value with a method called "getDSN()".

Here's something else to chew on that may be helpful to you (as it was for me): Besides just a global application config bean, you can also define configuration beans for different services that your app has. For instance, my app performs image manipulation, so within my Coldspring.xml file I defined a configuration bean called "ImageServiceConfig" that contains settings for thumbnail dimensions, large image dimensions, naming conventions, pathing information, etc., then I inject that bean into my ImageService.cfc. I do the same thing for my EmailService.cfc. This allows me to truly consolidate all of my application settings within my Coldspring.xml, simplifying maintenance in that regard.

That, Boys and Girls, is injection at its finest, and it allows me to maintain my app's global values in one place, just like I used to do with application.cfc/cfm.

Doug out.
Posted by dougboude at 9:58 AM | PRINT THIS POST! | Link | 8 comments
27 March 2007
Just What IS Abstraction, Anyway?
Consider scenario 1:

It's Saturday, and I have a list of chores to do.
  1.  Throw the laundry into the washer;
  2.  Do the dishes;
  3.  Scoop the cat poop out of the litter box;

So, I take the laundry out of the basket in my closet and put it into the washer. I dump in one cup of SudSoClean, set the temp to warm, set the load size to medium, and start the cycle.

Next, I move all the dishes out of the sink and onto the counter, wash out the sink, put the drain-stopper in, and fill it with hot soapy water. I put the silverware in first so it can soak the longest, then the plates, and lastly cups. As I wash a dish, I rinse it in the other side of the sink under warm water, then set it on the towel to drain while i finish washing the rest of the dishes.

Saving the worst for last, I get a plastic bag from the kitchen drawer and take it to the cat litter box. I get the plastic strainer scooper thingy out of its container, remove the lid to the litter box, and start scooping out little cat tootsie rolls and putting them into the bag. When I'm finished, I add some fresh cat litter, put the lid back on the litter box, and slide it back into place.

Whew! That was hard work, wasn't it boys and girls!

You know what. I think I'll abstract my chores by adding something between them and myself: my kids!

Consider scenario 2, with me doing my chores after having abstracted them:

I call out to objBrandon and ask him to do the laundry (<cfset laundrydone = objBrandon.doLaundry()>);

I call out to objLilly to do the dishes (<cfset dishesDone = objLilly.doDishes()>);

I call out to objSarah to scoop the kitty litter (<cfset noMoTootsies = objSarah.scoopLitter()>);

Hey! I'm done with my chores!

Abstraction: removing the actual work from myself and executing it by commanding someone else to do it.

It's easy to see why I'd want to abstract my chores. But in an application, WHY would I want to add yet another layer to what may already be somewhat complex?

Because...the way the actual work gets done just might change, and if I have the work abstracted out to individual objects, making those changes is all done in one place.

As an illustration, consider a change to the process for washing my dishes. Now, instead of doing them in the sink, I give in and allow the new process to be rinsing them and stacking them in the dishwasher. I re-write the routine for objLilly, but my call to her to doDishes(), and in fact, anybody else's call to her for the same does not change. Because we've abstracted that chore, the "business logic" associated with it is entirely encapsulated (contained) and found in one place.

In the context of an application, if we DID follow the advice of a peer and "create an abstraction layer for managing persistent variables (such as session variables)", then when the day came that we found a need to stop storing values in session and switch instead to client variables, we don't have to hunt and peck all over our code for every occurrence where a session var gets set; we need only go to our Persistence object and make the needed changes right there.

Abstraction - it's what's for dinner.

Abstraction - the other white meat.

Abstraction - not such a vague term after all, is it?
Posted by dougboude at 2:11 PM | PRINT THIS POST! | Link | 12 comments
22 March 2007
Just What IS the Factory Pattern, Anyway?
A Factory makes things, right? And that is precisely what is being referred to when someone talks about a Factory, or the Factory Pattern: an object or framework whose job it is to create other objects for you.
So, rather than create your own object yourself like so:

<cfset myObject = createobject("component",model.myObject)>

 
You would call upon your Factory object to make it for you, similar to the following:

<cfset myObject = myFactoryObject.MakeMeAnObject(obj = “model.myObject”,args = stArgs) >

 
If you opt to have an object create your other objects for you, thenYOU, O Best Beloved, are a user of the Factory Pattern, and may boast of it in public settings as the mood strikes you.

Here’s a question that’s BEGGING to be asked: WHY would anybody wanna add that level of complexity to their app???

I’ll have to respond to that question with another question: Has it crossed your mind that sometimes, perhaps, one object might need an instance of another object inside of itself in order to do some kind of work?

Whether it has or hasn’t crossed your mind, the fact is that many times this will be the case, especially when you’re writing your app around an MVC framework. Now, the traditional method of making one object available within another object would be to simply write a line of code within your CFC that instantiates the other object, such as in our example above. However, what if you are using this same CFC…we’ll say, a CFC that performs emailing duties, within many other objects? Then one day you make a change to the Email.sendMail() method that requires an additional parameter be passed in. You would have to go to every other CFC that instantiates the Email.CFC and modify that line of code to accommodate the new parameter. Could take a long time, you might miss one, etc. Using a Factory, however (such as the Coldspring framework, which I am totally in love with), you can make that change in one place and the Factory will ensure the change is cascaded appropriately.

So what would be a real world scenario where I would actually need one object inside of another? Hmmm…how about registering a new user for access to a site? The steps involved with registering a new user are:

  1. create the user record
  2. send the user an email.

In order to keep my functionality all segregated nice and neat so i can use it here and there, I have myself a User object that handles user records, and an Email object that performs emailing duties. Since my registration process means I need to be able to perform functionality from both the User object AND the email object, I create a third object called RegistrationService.CFC that will do nothing more than orchestrate, or coordinate, work that the User and Email objects know how to do. This scenario is just one of many compelling reasons to utilize a factory.

(FYI, that coordination of work is what makes RegistrationService a service layer object...not the fact that it has 'Service' in the name.)

One last thought...Factory Pattern…this is another one of those “patterns” that I do not consider to be a pattern of any sort. From my real world experience, an object can BE a Factory, or you could even create an entire application (or framework) whose job it is to BE a Factory…but a pattern of factories? Nah, doesn’t gel.

Doug out.

Posted by dougboude at 5:16 PM | PRINT THIS POST! | Link | 1 comment
Just What IS the Singleton Pattern, Anyway?

You, O Best Beloved, are a Singleton. There is nobody else like you in the whole wide world, nor has there ever been. You’re a singular occurrence, a unique random combination of genetics that exists only wherever you happen to be at a given moment. And if any of  your friends wants to interact with you, they know just where to find you. You can interact with lots of different people, but no matter how many friends you may have, every one of them is interacting with the exact same YOU. When your good friend Dave asks you to tell Theresa hello next time you see her, you store that information and next time you interact with Theresa, you pass along that exact message.

 
You getting the picture here? If you instantiate a CFC and put it in a place (Application scope, anyone?) where EVERY other part of your application is able to interact with THAT PARTICULAR instance of your CFC, then YOU, O Best Beloved, have created your object as a Singleton. Now, for whatever reason, people seem to be awfully fond of tossing around the buzz phrase “Singleton Pattern”…not sure why. It’s way simpler just to use the word as an adjective describing how you have instantiated your object, and it makes more sense, too.

 A few other thoughts on Singletons…
 

  • It’s vital to understand this term because it has a huge effect on how your app will work. Basically, if an object is created as a Singleton and you aren’t able to visualize what that means, you could have people seeing other people’s data. Not good.
  • That I’m aware of, there is no opposite of Singleton...an object either IS a Singleton, or it isn't.

 
POP QUIZ!

Which of the lines of code below is creating my object as a Singleton?

A) <cfset adminObject = createobject("component",model.admin) >

B) <cfset application.adminObject = createobject("component",model.admin) >

Posted by dougboude at 4:41 PM | PRINT THIS POST! | Link | 13 comments
28 February 2007
Lost my public speaking virginity!
Yesterday evening (Tuesday February 27th) I gave my first live presentation! The Kansas City Coldfusion User's group (www.kcdevcore.org) invited me to come and speak about Model-Glue since I've been using it on my day job for the past six months or so and have learned it and OO coming from a strictly procedural background. I wasn't nervous until Jim Pickering (the UG manager) and I drove up to the building where they meet. The nervousness finally subsided about five minutes after I got into the presentation and then I felt like it flowed pretty smoothly.

My approach to this presentation was a little different than what most probably expected. I opted NOT to do a demo app at all since there's already a plethora of sample apps and tutorials out there already that are really great. Instead, I decided to take the time to share all of the things needed in order to know how to "think about" OO and model-glue...all of the things that I spent the most time researching and trying to comprehend so that I COULD take advantage of Model-Glue's simplicity.

So, for what it's worth, here is a link to my first presentation!

https://admin.adobe.acrobat.com/_a200985228/p45002941/

Actual PPT and accompanying Word doc for my presentation (caution: the PPT is nearly 5mb, so only click it if you really want it): MMG.PPT   MGPreso.DOC

Disclaimer: Everything I shared in this presentation is as I understand it to be, and was not painstakingly researched to validate it's accuracy. Whether it's accurate or not, complete or not, the understandings I share in the presentation work for me in my real-world scenarios and should be considered as "this guy's view"  and not as gospel fact.
Posted by dougboude at 5:14 PM | PRINT THIS POST! | Link | 2 comments