Pre- and postconditions for CFML functions?

When using CFC components I often find myself looking into their methods to figure out what exactly values returned are or what values are allowed for arguments. Especially when working with APIs it would be really nice to know upfront what value function return and what possible values for arguments are. Today this information is supplied by documentation. In most cases specification describes that argument X must be of type string and sometimes it even says somewhere in the description what accepted values are. But who likes reading specification? Is there a way CFML developer may know what pre- and postconditions for functions are?

Some time ago I’ve been watching this video. It is about Spec# - extension of the C# language. It gave me the idea of precondition attribute for cfargument and postcondition attribute for cffunction.

Today, when using cffunction I can specify that function returns, for example, number but doesn’t let me specify what the number is. The same problem is with cfargument. I can specify my argument should be of type string but I can’t say it should of value X, Y or Z. Take a look at following code:

<cffunction
 postcondition="result gte 1"
 returntype="numeric"
 name="someFunction">
 <cfargument precondition="value eq 'X' or value eq 'Y' or value eq 'Z'"
  type="string" name="someArg" />
 ...
</cffunction>

The idea is anytime CFML engine finds postcondition attribute used with cffunction it will treat result as keyword representing value returned from function and evaluate whole expression to check if that value meets given condition. The same thing is with precondition attribute. Anytime CFML engine finds this attribute, value will be treated as special keyword representing argument value and expression will be evaluated to check if it meets given condition.

These attributes are there for two reasons. First reason is documentation. Documentation tools may use these attributes to output expressions to the user so he knows what values to pass or expect from a function. For example Adobe ColdFusion CFC explorer might be extended to honour them. Second reason is code readability. Developer does not have to read tons of specifications to know that value will be at least X. This leads us to one small bonus: writing less code. Because CFML engine evaluates expressions at runtime, developer does not need to check argument values and returned values as he may be sure they’re correct. So instead of:

<cffunction name="someFunction" retunrtype="numeric">
 <cfargument name="someArg" type="string" />
 <cfif arguments.someArg eq "X" or arguments.someArg eq "Y" ...>
  <!--- do what should be done:--->
  <cfreturn result="" />
 </cfif>
 <cfthrow ... />
</cffunction>

we use the code from first listing. Similar when calling cffucntion, instead of this code:

<cfset result=someCfc.someMethod("X") />
<cfif result gte 1>
 <!--- do something --->
</cfif>

we get:

<cfset result = someCfc.someMethod("X") />

as CFML engine evaluated postcondition expression and we can be sure returned value is at least 1.

Do you think it would be useful? Share your thoughts in comments.


About this entry