comment

Fancy Bread Blog Turns One Today!

2008 March 29
No Comments
Thanks to all the folks who have read and commented on this blog over the past year. I've met a lot great people and learned more than I imagined. A quick review of my stats for the year shows 44 posts with an average of 865 views and just under 2 comments per post. The top three categories are ColdFusion, ColdSpring and Transfer. I started blogging to share my learning experiences and ideas. Year two will be a lot more of the same. :)

Taming the MXUnit Ecplise Plugin with Apache Alias

2008 March 09
No Comments
If you are into Unit Testing and haven't yet heard of MXUnit, I definitely recommend giving it a whirl. Some things that stand out for me, thus far in my evaluation, are the simple, but extensible, assertions, the ecplise plugin, and the debug output. One gotcha that has come up for people when using the eclipse plugin, is that is was designed assuming that the package path to your components resolves directly from your web root. For people who run separate server instances, virtual machines, or develop locally with Apache virtual hosts, this is a show stopper. Luckily, for folks, like myself, who prefer to develop locally with Apache, getting the MXUnit eclipse plugin to work is simply a matter of adding a couple of Alias directives to your vhost.

read more...

ColdFusion 8 Application Mappings and Sub-folders

2008 February 27
No Comments
Now that I'm on a CF8 hosting plan, I've started leveraging some of that goodness in my applications. The first thing I have implemented is application level mappings to keep my configuration files and components out of the web root. Here's how my current project layout rolls.
/project
  /config <-- Coldspring and Transfer config files
  /model <-- model components
  /root <-- web root
    /admin  <-- secure admin screens
Basically, I want to create mappings to config and model. I did a little googlin' and found a nice snippet on Sean Corfield's blog on looping over a list to build the mappings. I aped that code with a slight mod for my setup. <cfif (ListLast(CGI.HTTP_HOST,".") eq "local")>
<cfset mapPath = "../">
<cfelse>
<cfset mapPath = "../" & this.name & "/">
</cfif>

<cfloop index="p" list="config,model">
<cfset this.mappings["/" & p] = expandPath(mapPath) & p />
</cfloop>
I dev on Mac and deploy on Windows and my local folder structure is slightly different from my host. The first part of the code is just a test of whether the site is being served up locally. When on the production server, the mapped folders are in a folder with the same name as the app. This is a great alternative to using Apache Alias or Virtual Directories in IIS for mappings. That is, until I tried using the mapping from within the admin folder. Suddenly the path was not recognized. I initially thought this was a transfer issue, but that was not the case. I tried several variations and workarounds. Eventually, I figured out that the mappings were fine for files in the web root where Application.cfc resides. So why was the path not available to files in a folder below the web root? The answer was pretty simple. The admin folder had no Application.cfc, thus no mappings. Remembering another gem by Mr. Corfield regarding extending Application.cfc via a Proxy, I created an Application.cfc in the admin folder and the required proxy in the web root. Instead of repeating the code for creating the mappings with only the path prefix changed, I wrapped the creation of mappings up in a method. <cffunction name="createMappings" access="private" output="false" returntype="void">
   <cfargument name="pathPrefix" type="string" required="false" default="../">
   <cfif (ListLast(CGI.HTTP_HOST,".") eq "local")>
      <cfset variables.mapPath = arguments.pathPrefix>
   <cfelse>
      <cfset variables.mapPath = arguments.pathPrefix & this.name & "/">
   </cfif>
   <cfloop index="p" list="config,model">
<cfset this.mappings["/" & p] = expandPath(variables.mapPath) & p />
   </cfloop>
</cffunction>
And call it from the Application.cfc in the admin folder using the appropriate prefix. <cfcomponent displayname="Application" extends="ApplicationProxy">

<!--- set mappings in this directory --->
<cfset createMappings(pathPrefix="../../")>

</cfcomponent>
Application level mappings are handy, but the per directory limitation does not make for a tad more code. Overall, I think it's a small price to pay for the benefit gained.

UPDATE:

After testing this on my Windows machine, it appears that using "this.mappings" inside a method does not properly set the mappings. I've changed things around so that the createMappings() method returns a struct and I set it as a pseudo-constructor. <cfset this.mappings = createMappings(pathPrefix="../") >

Of Views and Models and Working With Transfer ORM

2008 February 05
No Comments
Yesterday, I asked Mark Mandel for some advice on tuning my object model for performance. Mark, being an ever-so-helpful (P)OSS author, gave me a few suggestions. Turns out that someone asked basically the same question on the transfer list today. Jaime Metcher made a couple of excellent points on choosing between queries and object composition. Paraphrasing, Jaime, when working with large data sets (the type of thing you might be tempted to use arrays of objects for), you will get better performance using a query. If you want to display a single instance of some object and the view is truly a composite, then your model should reflect that composition. Understanding this helps with choosing between onetomany or manytoone relationships for your object compositions.

read more...

My Journey into Test Driven Development

2008 February 02
No Comments
If you wonder about Unit Testing and Test Driven Development, but are afraid of commitment, do yourself a favour, read Terrance Ryan's thoughts on "How to convince yourself to Unit Test". A couple of months ago, I made a commitment to start unit testing. I'll admit that it took a little while to wrap my head around the terminology and process. A good practice point for me was to run some of my first CFCs though Seth Petry-Johnson's var scope checker. When I discovered a plethora of un-scoped vars, I used the opportunity to write tests against the methods I was going to change. After only a few tests, I started to get this warm feeling of security. By the time my updates and tests were complete, I had a nice little suite that I could return to any time a change was required.

read more...

Services, DAOs and Functional Organization

2008 January 29
No Comments
While cleaning out the office recently, I ran across a couple of textbooks I kept from my business school courses. I didn't care much for business school, but I did learn some valuable concepts. A few of which came from a course on Organizational Behaviour (OB). OB is a "management science" which can be briefly described as the study of groups in organizations. A goal of OB is to determine the best strategy to use within an organization to maximize employee performance (productivity) and, as a result, profitability. If you think of an organization with managers and employees, where each employee performs specific duties, you might find it strange to have a manager for every employee. You rarely see this in the real world, because it is grossly inefficient.

read more...

Working with Transfer ORM: TQL, MSSQL and Reserved Words

2008 January 25
No Comments
I'm definitely marking this down in the "I should have known better" category. If you use MSSQL, you probably know by know that "user" is a reserved word. So, unless you use [user] as a table identifier it's imperative that you name your table something like "tbl_user" or use the plural "users". I don't like plural table names, so I opted for tbl_user. I just ran into a gotcha with my TQL for a query against tbl_user. Why? Here's a snippet from my method to check the uniqueness of a user e-mail.
// local vars struct
var local = StructNew();
// default result
local.result = false;
// tql for list
local.tql = "from user.User as user where user.Email = :Email AND user.Id != :Id";
//create a query object
local.query = getTransfer().createQuery(local.tql);
//set the named parameters
local.query.setParam("Email", getEmail(), "string");
local.query.setParam("Id", getId(), "numeric");
//run it
local.userList = getTransfer().listByQuery(local.query);
// if no records exist e-mail passes unique test
if (local.userList.recordcount eq 0)
{
	local.result = true;
}	
return local.result;

My transfer object class name is user.User, so why not alias that as "user"? That's a logical alias, right? Wrong! After pulling my hair out debugging the ever-so-descriptive error message, [Macromedia][SQLServer JDBC Driver][SQLServer]Line 1: Incorrect syntax near '.'. I finally decided to write up a unit test to try and get some meaningful debugging information. From there I pulled a query, ran that in the Query Analyzer. Scratched head a bit more, then...voila! Reserved word issue. How silly.... Of course, this is not purely a Transfer or even TQL problem, merely a cautionary tale regarding reserved words in MSSQL that I happened upon via Transfer TQL. For the record, the new TQL query reads:
local.tql = "from user.User where user.User.Email = :Email AND user.User.Id != :Id";			
The other big a-ha moment for me is that if an error occurs within a method invocation, I should debug by unit testing, not re-initializing, rinsing and repeating on the client side.

Two Utility Classes to Help Keep Your Controllers Lean

2008 January 23
No Comments
I have really enjoyed reading the perspectives on application architecture that have sprouted up on the mailing lists lately. It comes a at good time for me, since I'm beginning my first fully OO MVC project. One of the best recommendations, I feel, is to keep your controllers as dumb as possible. While this is a fine aspiration, there are plug-ins and convenience methods available to frameworks that just make life easier. In particular, the availability of "beaner" methods. I'm currently using Model-Glue, so I'll use the makeEventBean() method as an example. MakeEventBean() is really useful for populating a bean with any setter methods that match the keys in the Model-Glue event. While convenient, I think it provides a slippery slope for business logic to slide into controller methods.

read more...

Still Running ColdFusion 8 Beta? Here's How To Find Out...

2008 January 18
No Comments
When the Coldfusion 8 Beta came out, I jumped at the chance to install. The beta release had a few issues, but nothing that I ran into until I tested out multi-threading for MachII 1.6. After a bit of back and forth with the MachII team, I finally realized that I was running the beta and not the final release. If you are running into issues with any ColdFusion OSS and you think it's time to open a ticket. When you're getting the house-cleaning done (listing your OS and the version for CF, Java, etc.), double check the ColdFusion Version. ColdFusion 8 Beta: 8,0,0,171647 ColdFusion 8 Final: 8,0,0,176276 Another clue that will tip you off for running the beta is if ColdFusion will not re-start after installing either hotfix 1 or 2 for CF8.

One Giant Leap Backward - Consistency in (HTML) Email Marketing

2008 January 04
No Comments
Depending on the complexity of the design, bashing out a pixel perfect cross-browser website is somewhat less frustrating nowadays. Not so for an HTML Email campaign. Aside from the fact that image-suppression is the norm, if you want consistency across most major clients (especially HTML clients like Gmail, Yahoo!, Hotmail), you're gonna need a time machine. While doing a bit of research on whether it's still relevant to offer users a choice between plain text and html e-mail, I stumbled upon this excellent piece . The discovery was apropos, because I spent the better part of the morning cursing Gmail and it's draconian re-rendering policy for html e-mail. When I read the following bit, I was laughing so hard the crew here was wondering if I'd lost it completely.
I was talking to an email HTML developer the other day, and kept having to make this point: regress your code. It's possible to have a single template render properly in various webmail browsers. You just have to pretend it's 1995.
That gem sums up my feelings completely. Here's hoping the Email Standards Project makes life easier sometime in the future. Since I didn't find a definitive answer on the plain text vs. html e-mail subject, anyone out there with large e-mail marketing campaigns still provide both? If so, what is the primary reason for that decision?