Emily Christiansen
Matt Gifford
A key principle to consider when developing your applications is to not repeat code unnecessarily. This is commonly known as the DRY principle: Don't Repeat Yourself.
Now that some of the basics of programming with ColdFusion have been covered, we can take a moment to discuss code reuse. Writing code that can be used again is an important skill for developers to master; not only does it save time, but it forces the developer to structure their code such that individual routines are isolated and labelled properly. Doing this makes the code easier to read and interpret. In this chapter, simple examples will be used; you can extrapolate from these examples and imagine the effects on a larger scale.
Let's pretend I have a ColdFusion page. The function of this page is to display a greeting. The code would look something like this:
<cfparam name = "firstName" default = "Matt">
<cfparam name = "lastName" default = "Gifford">
<cfset fullName = firstName & " " & lastName>
<cfoutput>
Hello, #fullName#!
</cfoutput>
This code doesn't do much; it takes the first name and last name, concatenates them to make the full name, then outputs it to the screen. What if we wanted to isolate that piece of code that makes the full name and use it over and over again throughout the system? ColdFusion offers several ways to structure your code for reuse. As the language has grown and evolved over the years, it has gone from simple inclusion of files, to making individual functions, and finally embracing object-oriented programming principles. It also offers the ability to create your own custom tags. When discussing code reuse, functions are the simplest place to start.
Functions are reusable blocks of code that have a name, may take in arguments, perform some operations on those arguments, and may return a new value. Breaking complex tasks into smaller, clearly labelled functions will also make them easier to read and comprehend. Functions can be thought of as building blocks for a program.
In ColdFusion, functions are created using the function syntax. A simple function stub would look like this:
<cfscript>
public void function myFunction(){
// Your function content goes here
}
</cfscript>
This basic function implementation does nothing and returns nothing. Before we move on, let's take a moment to go through the available function declarations and options.
Now that the stub of the function is created, it's time to make it do
something. Let's say we have the name of a person stored in our
database. We want to display the person's first and last name in the
interface, but their name is stored in two different fields,
first_name
, and last_name
.
If we already have the first and last names stored in variables, we can pass them into the function as an argument. We can tell our function which arguments to expect by setting them as arguments for the function:
<cfscript></cfscript>
public void function getFullName(
required string firstName = '',
required string lastName = ''
){
// Your function content goes here
}
</cfscript>
In this example we are asking the function to require two arguments, firstName
and lastName
respectively.
Both argument values are marked as required
attributes. The type
is set as a string
for both, and a default value of an empty string has also been provided to make sure the function will not break if nothing is sent in. This is entirely optional.
Take note that the name of the function was changed. The name is much more descriptive of what it actually does; this is an example of refactoring, the process of refining code.
If we want to access the firstName
and lastName
variables, we will need
to look in the arguments
scope. This is one of the many scopes provided
by ColdFusion. Variables in the arguments
scope exist only for the
function in which they are declared. You can access them by using
arguments.yourVariableHere
.
Let's put this to use in the function:
<cfscript>
public void function getFullName(
required string firstName = '',
required string lastName = ''
){
fullName = arguments.firstName & ' ' & arguments.lastName;
}
</cfscript>
Even though the string is constructed, the fullName
variable does not
belong to a scope. We need to make sure that only this function can
access fullName
, so we will var scope it like so:
var fullName = arguments.firstName & ' ' & arguments.lastName;
Now that the new variable is scoped, we can now return the variable. Since the
function is now returning something, we also need to change the returnType
attribute in the function definition. Because we are only returning a string,
we will just set it to string
. Functions can return pretty much anything you
want them to, including structs and objects.
In the end, the function ends up looking like this:
<cfscript>
public string function getFullName(
string firstName = '',
string lastName = ''
){
var fullName = arguments.firstName & ' ' & arguments.lastName;
return fullName;
}
</cfscript>
The function is now built, albeit a very simple one. It is concise and clearly labelled, meaning that it is easy to read and reuse elsewhere in the system.
Now, the question is how to allow people to use it. Fortunately, calling
functions in ColdFusion is only a little different than setting up any
other variable. We use the cfset
tag.
<cfset fullName = getFullName( firstName='Matt', lastName='Gifford' )>
When it comes to passing in arguments, there are a few ways you can do it. Above, the arguments are explicitly named going into the function. This is particularly useful for functions that have a large number of arguments, as it is far easier to keep track of what actually got passed in. Alternatively, something like this could have been done:
<cfset fullName = getFullName( 'Matt', 'Gifford' )>
This approach relies on the arguments being passed in the same order in which they are specified in the method signature above. It can get very confusing for functions with large numbers of arguments.
Another option is available if working within one function and sending
the same arguments to a helper function. For example, the getFullName
function could be used by another, larger function. Let's call it
getGreeting
:
<cfscript>
public string function getGreeting(
string firstName = '',
string lastName = ''
){
var fullName = getFullName( argumentCollection = arguments );
// We can do more with the fullName variable here
}
</cfscript>
In the above example, argumentCollection = arguments
was used to pass
the same arguments from one function to another. This is very handy when
passing a bunch of arguments to another function with the same argument
names. This is much faster than typing out the names of each and every
argument.
In order to call a function, it needs to be put somewhere. There are a
number of ways to accomplish this. The simplest way is to put it in a
.cfm
page and call it.
<cfscript>
fullName = getFullName( firstName='Matt', lastName='Gifford' );
writeOutput( fullName );
</cfscript>
Putting the function into the very same .cfm
page being used to display
our greeting is not very conducive to code reuse.