ColdFusion development, refactoring and common design problems to consider

While talking with a work colleague today he asked why we pass the ColdFusion DataSource around for our methods, the simple answer is that we don't have too, but the design of the application promotes reusability if we do.

The term reusability is something that what I would say in the ColdFusion world,  be very easily overlooked by people who do not think outside the problem at hand. This is not to say that this work colleague doesn't know better, or that he is not experienced enough to not know better.

What it means is that he saw that we are doing this, and questioned why.

So with his question in mind one can still ask it again, does passing the DataSource around via the arguments scope provide any benefits. The answer is that it really depends on your application, and what plans you might have for it in the future, or more importantly how you foresee the application evolving.

Now the question had me thinking some today and the one thing that kept coming to my mind was that he is young, not inexperienced and certainly does know his stuff, however I would like to say that he doesn't plan ahead. The reason I am saying this is that I wish to say that ColdFusion developers in general fall into this category and not by fault of their own, but because the ColdFusion language can promote some very bad habits when it comes to development.

Now before I get into where it is I am trying to get to, I would just like to say that I am just as fallible as well, even thought I do try not to be.

So lets look at something very simple for now.

<cffunction name="getPost" output="false" returntype="query">
   <cfargument name="category" type="string" required="true" />
    ... More code...
</cffunction>

We know by looking at this that we are going to be getting all posts that are related to the passed category, and the one thing that is not shown above is that the cfquery would normally look something like this.

<cfquery name="local.records" datasource="#application.datasource#">
   .... the query to execute.....
</cfquery>

And this is what I would say is very common code, as most would use the application variable to store the DataSource as a global variable. The problem with this sort of code is that it is narrow minded and doesn't think about what could happen in the future, and by that I mean that it could be a requirement in the near future to either open the API up to the public, or even still the requirements of the project could change that we might need to get the info from a DataSource that is not the current global DataSource.

So in this example I have decided to use the method getPost for a good reason, because this is what I would class as a typical example of what someone would do if they had been writing a blog application. Now what would happen if someone came up to you and said we know want to make this application multi user, multi site and we want to provide an API to the outside world?

The first reaction to any developer would be to write code for that situation, so in the case of multi user it is sort of a know brainer unless each user had their own database. But what if this was to be over multiple sites that did indeed have their own database, or even as a remote API?

It means that we would have to write an API that would become a wrapper to the main function, which means we are technically writing two methods/functions that do the exact same thing. If a developer is used to refactoring code, then this would be the one thing that would get changed fairly quickly. But if it is an existing application that has been around a few years, you would have no choice to but to write a wrapper to do this. Which is because nobody had foreseen that this might ever be a requirement, or that we just want to reduce the amount of code we write and/or maintain.

This brings me back to the days when I was in a class learning coding in games development, the one thing we had been taught back then was that you must treat everything you write as a black box. What this means is that the method/function needs to know two things, that is that it needs to know what is coming in, and what is going out, it should not know what environment it is running in nor should it know what is around it. This means that a developer can write a self contained function and not worry about whether it might fail in time, or even have to be revisited because of changes in the direction the application might be going in.

So with all this in mind how should our ColdFusion example now look?

  <cffunction name="getPost" output="false" returntype="query">

    <cfargument name="database" type="string" required="true" />

    <cfargument name="category" type="string" required="true" />

      <cfset var local = {} />

     <cfquery name="local.records" datasource="#arguments.database#">

    </cfquery>

  </cffunction>

Now you can look at this and say that it will never effect me, the reality is that it will and likely to do so quicker than you think. The reason being is that when it comes down to refactoring code, it is usually better and easier when you are writing Test Driven Development code because you are more likely to think outside of the square.

At the end of this what have we done?

We have thought about the fact that we could reuse this in a manner that might not be apparent right now, but at some point in the future it will save us more work.

And that could not be further from the truth, the reason being is that the function could be destined as internal. Then later we need to provide this as a web service, or even as an API to out application and even as a Software as a Service.

So the question at the end of all this, would you prefer to think about the future and write each method/function as a black box, or would you prefer to have to revisit this all again in time?

I know what I would prefer, what would you prefer?


RT @cfbloggers: ColdFusion development, refactoring and common design problems to consider - http://cfbloggers.org/?c=44832 Oct 1, 2010
ColdFusion development, refactoring and common design problems to consider - http://cfbloggers.org/?c=44832 Oct 1, 2010