Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
Ben Nadel at Scotch On The Rock (SOTR) 2010 (London) with: Roman Schlaepfer
Ben Nadel at Scotch On The Rock (SOTR) 2010 (London) with: Roman Schlaepfer@appleseedexm )

Trying To Find My Preferred Format For Method Annotations In Lucee 5.3.2.77

By Ben Nadel on
Tags: ColdFusion

One of the many differences between Adobe ColdFusion (ACF) and Lucee CFML is that Lucee won't alter the runtime behavior of the ColdFusion code based on JavaDoc-style annotations. As such, for method annotations to be applied, they have to be in the actual method declaration following the arguments list. This isn't a style that I've used before, so I don't have a good instinct for it. And, as someone who is notoriously maniacal about formatting, this doesn't feel good. Therefore, I decided to sit down, play around with different formatting options for method annotation in Lucee CFML, and figure out which one I feel the most comfortable with moving forward.

Here are the variations that I could come up with. Specifically, in this code, we are looking at the placement and organization of the output, cachedWithin, and localmode annotations:

<cfscript>

	// ------------------------------------------------------------------------------- //
	// VERSION ONE: On a single line immediately following the argument list.
	// ------------------------------------------------------------------------------- //

	/**
	* I got a record; I was Zero Cool.
	*/	
	public void function myMethod1() output = false cachedWithin = "request" localmode = "modern" {

		echo( "They're trashing our rights!" );
		echo( "They're trashing the flow of data!" );
		echo( "Hack the planet!" );

	}


	/**
	* I got a record; I was Zero Cool.
	* 
	* @myArgument I represent some bits and bytes.
	*/	
	public void function myMethod2( required string myArgument ) output = false cachedWithin = "request" localmode = "modern" {

		echo( "They're trashing our rights!" );
		echo( "They're trashing the flow of data!" );
		echo( "Hack the planet!" );

	}


	/**
	* I got a record; I was Zero Cool.
	* 
	* @myArgument I represent some bits and bytes.
	* @myArgument2 I represent some bits and bytes.
	*/	
	public void function myMethod3(
		required string myArgument,
		required string myArgument2
		) output = false cachedWithin = "request" localmode = "modern" {

		echo( "They're trashing our rights!" );
		echo( "They're trashing the flow of data!" );
		echo( "Hack the planet!" );

	}

	// ------------------------------------------------------------------------------- //
	// VERSION TWO: On a single line, starting on the line after the argument list.
	// ------------------------------------------------------------------------------- //

	/**
	* I got a record; I was Zero Cool.
	*/	
	public void function myMethod4()
		output = false cachedWithin = "request" localmode = "modern"
		{

		echo( "They're trashing our rights!" );
		echo( "They're trashing the flow of data!" );
		echo( "Hack the planet!" );

	}


	/**
	* I got a record; I was Zero Cool.
	* 
	* @myArgument I represent some bits and bytes.
	*/	
	public void function myMethod5( required string myArgument )
		output = false cachedWithin = "request" localmode = "modern"
		{

		echo( "They're trashing our rights!" );
		echo( "They're trashing the flow of data!" );
		echo( "Hack the planet!" );

	}


	/**
	* I got a record; I was Zero Cool.
	* 
	* @myArgument I represent some bits and bytes.
	* @myArgument2 I represent some bits and bytes.
	*/	
	public void function myMethod6(
		required string myArgument,
		required string myArgument2
		)
		output = false cachedWithin = "request" localmode = "modern"
		{

		echo( "They're trashing our rights!" );
		echo( "They're trashing the flow of data!" );
		echo( "Hack the planet!" );

	}

	// ------------------------------------------------------------------------------- //
	// VERSION THREE: Each annotation on a separate line, starting on the line after
	// the argument list.
	// ------------------------------------------------------------------------------- //

	/**
	* I got a record; I was Zero Cool.
	*/	
	public void function myMethod7()
		output = false
		cachedWithin = "request"
		localmode = "modern"
		{

		echo( "They're trashing our rights!" );
		echo( "They're trashing the flow of data!" );
		echo( "Hack the planet!" );

	}


	/**
	* I got a record; I was Zero Cool.
	* 
	* @myArgument I represent some bits and bytes.
	*/	
	public void function myMethod8( required string myArgument )
		output = false
		cachedWithin = "request"
		localmode = "modern"
		{

		echo( "They're trashing our rights!" );
		echo( "They're trashing the flow of data!" );
		echo( "Hack the planet!" );

	}


	/**
	* I got a record; I was Zero Cool.
	* 
	* @myArgument I represent some bits and bytes.
	* @myArgument2 I represent some bits and bytes.
	*/	
	public void function myMethod9(
		required string myArgument,
		required string myArgument2
		)
		output = false
		cachedWithin = "request"
		localmode = "modern"
		{

		echo( "They're trashing our rights!" );
		echo( "They're trashing the flow of data!" );
		echo( "Hack the planet!" );

	}

	// ------------------------------------------------------------------------------- //
	// VERSION FOUR: Each annotation on a separate line, starting on the line after the
	// argument list, with an additional indentation.
	// ------------------------------------------------------------------------------- //

	/**
	* I got a record; I was Zero Cool.
	*/	
	public void function myMethod8()
			output = false
			cachedWithin = "request"
			localmode = "modern"
		{

		echo( "They're trashing our rights!" );
		echo( "They're trashing the flow of data!" );
		echo( "Hack the planet!" );

	}


	/**
	* I got a record; I was Zero Cool.
	* 
	* @myArgument I represent some bits and bytes.
	*/	
	public void function myMethod9( required string myArgument )
			output = false
			cachedWithin = "request"
			localmode = "modern"
		{

		echo( "They're trashing our rights!" );
		echo( "They're trashing the flow of data!" );
		echo( "Hack the planet!" );

	}


	/**
	* I got a record; I was Zero Cool.
	* 
	* @myArgument I represent some bits and bytes.
	* @myArgument2 I represent some bits and bytes.
	*/	
	public void function myMethod10(
		required string myArgument,
		required string myArgument2
		)
			output = false
			cachedWithin = "request"
			localmode = "modern"
		{

		echo( "They're trashing our rights!" );
		echo( "They're trashing the flow of data!" );
		echo( "Hack the planet!" );

	}

	// ------------------------------------------------------------------------------- //
	// ------------------------------------------------------------------------------- //

	// For funzies, dump out the metadata on each method.
	for ( i = 1 ; i <= 10 ; i++ ) {

		method = variables[ "myMethod" & i ];

		dump( var = getMetadata( method ), format = "simple" );
		echo( "<br />" );

	}

</cfscript>

Version One is clearly garbage. Not only does this version go way off screen (at least potentially), it's hard to see where one annotation ends and another annotation begins.

Version Two is a bit better in that it limits the possibility of long lines. But, like Version One, it still suffers from poor visual parsing, as one annotation seamlessly flows into the next.

Version Three feels like the best one so far. It will never lead to long lines and has good visual parsing; but, at the same time, doesn't take up too much vertical space.

Version Four was an attempt to call-out the annotations a bit more by indenting them. But, I am not sure such special treatment is necessary. Method annotations are not terribly relevant to the method logic, so I would prefer to see them recede into the background a bit more.

Honestly, I don't really love any of them. Postfix annotations on the method signature feel so awkward. This is why I used Adobe ColdFusion's JavaDoc style annotations. That said, for now, I am going with Version Three. It seems to strike a nice balance between readability and brevity.

Method annotations in Lucee CFML must come after the arguments list.

Of course, the above code is, let's call it, the "worst case" scenario - three different annotations on a single method. In the vast majority of scenarios, I only have one annotation, output. Let's see how a single annotation looks with Version Three:

<cfscript>

	// ------------------------------------------------------------------------------- //
	// VERSION THREE: Each annotation on a separate line, starting on the line after
	// the argument list.
	// ------------------------------------------------------------------------------- //

	/**
	* I got a record; I was Zero Cool.
	*/	
	public void function myMethod7()
		output = false
		{

		echo( "They're trashing our rights!" );
		echo( "They're trashing the flow of data!" );
		echo( "Hack the planet!" );

	}


	/**
	* I got a record; I was Zero Cool.
	* 
	* @myArgument I represent some bits and bytes.
	*/	
	public void function myMethod8( required string myArgument )
		output = false
		{

		echo( "They're trashing our rights!" );
		echo( "They're trashing the flow of data!" );
		echo( "Hack the planet!" );

	}


	/**
	* I got a record; I was Zero Cool.
	* 
	* @myArgument I represent some bits and bytes.
	* @myArgument2 I represent some bits and bytes.
	*/	
	public void function myMethod9(
		required string myArgument,
		required string myArgument2
		)
		output = false
		{

		echo( "They're trashing our rights!" );
		echo( "They're trashing the flow of data!" );
		echo( "Hack the planet!" );

	}

</cfscript>

Yeah, I guess that still works for me. It's clearly a separate part of the method, but not too loud. My eye gets drawn to it more than I'd like. But, I think I can live with it for now.



Reader Comments

Definitely prefer the "garbage" one line style! I never seem to run out of line space. Maybe I never use enough arguments and I have a high resolution screen. My eye likes to follow as few lines as possible. I'm probably dyslexic or something.

I guess this comes from the style pattern we use in conditional clauses:

if ( ) {
}

So, I want my all arguments & properties on a single line. So this would translate to:

if ( arguments ) properties {
}

Now, I know conditionals don't have the 'property' part, but I feel writing CFSCRIPT based functions, should follow the same structure.

function signature ( arguments ) properties/metadata {
}

Interestingly, when I am creating functions, using the TAG based form of CFML, I put each argument on its own line, which thinking about it, is pretty normal.

So maybe you are correct about version 3. I need to think on this a bit more.

Nice exploration. The spacing in your code makes things very easy to read.
I only wish, I could be bothered to make the effort to add more spacing myself:)

Reply to this Comment

Sorry, the conditional clause structure should have been:

if ( conditional statement ) properties {
}

The 'properties' part, was my attempt to justify why I think all parts of a function's signature should be on one line. It's a bit confused. But my mind works like this.

Reply to this Comment

@Charles,

To be sure, this is 100% subjective :D I'm only trying to find the format that makes my eyes and brains hurt the least. It's also the first time I've tried to work with this particular syntax; so, it's very possible that my feelings about this will change over time (as has much of formatting preferences).

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
NEW: Some basic markdown formatting is now supported: bold, italic, blockquotes, lists, fenced code-blocks. Read more about markdown syntax »
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.