Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Object-Oriented Programming in ColdFusion

You're reading from   Object-Oriented Programming in ColdFusion Break free from procedural programming and learn how to optimize your applications and enhance your skills using objects and design patterns

Arrow left icon
Product type Paperback
Published in Oct 2010
Publisher Packt
ISBN-13 9781847196323
Length 192 pages
Edition 1st Edition
Languages
Arrow right icon
Author (1):
Arrow left icon
Matthew Gifford Matthew Gifford
Author Profile Icon Matthew Gifford
Matthew Gifford
Arrow right icon
View More author details
Toc

Protecting your local variables


In our previous personalGreeting() method, we included two separate functions, sayHello() and getName(), into the main method. This is not an uncommon practice, and is what you would expect when writing detailed components with relationships between its included functions.

One issue that can arise when developing in this way is when two or more methods contain a variable of the same name and the value of that variable is accessed or changed by one of the methods.

As an example, the following code contains two functions, baseNumber() and multiplyNumbers().

While the cfcomponent tag has been excluded in this example, this could also easily be turned into a CFC by wrapping the functions within cfcomponent tags.

<cfoutput>
<cffunction name="baseNumber" returnType="numeric">
<cfargument name="a" type="numeric" required="true" />
<cfset x = arguments.a />
<cfreturn x />
</cffunction>
<cffunction name="multiplyNumbers" returntype="string">
<cfargument name="a" type="numeric" required="true" />
<cfargument name="b" type="numeric" required="true" />
<!--- multiply our basenumber value by 10 --->
<cfset x = 10 />
<cfset y = baseNumber(a) />
<cfreturn y & " multiplied by " & x & " = " & x * arguments.b />
</cffunction>
<cfloop from="1" to="10" index="i">
#multiplyNumbers(i,i)#<br />
</cfloop>
</cfoutput>

Listing 1.15 two user-defined functions

A cfloop tag runs a loop from 1 to 10. The multiplyNumbers() function accepts two arguments. In this example, these are both the index numbers of the loop. We want to multiply our baseNumber value (argument 'a'), by 10 for each loop, creating a 10 times table list. To do this, the multiplyNumbers() function has a hardcoded value (x) that is set to the value of 10.

The desired results you would expect from this code should be:

1 multiplied by 10 = 10
2 multiplied by 10 = 20

However, this is not the case. If you save the code to a .cfm template and run it in your browser, you will get the following result:

This is clearly not the result you would expect. So what's happening to cause this issue? Let's take another look at our two functions:

<cffunction name="baseNumber" returnType="numeric">
<cfargument name="a" type="numeric" required="true" />
<cfset x = arguments.a />
<cfreturn x />
</cffunction>
<cffunction name="multiplyNumbers" returntype="string">
<cfargument name="a" type="numeric" required="true" />
<cfargument name="b" type="numeric" required="true" />
<!--- multiply our basenumber value by 10 --->
<cfset x = 10 />
<cfset y = baseNumber(a) />
<cfreturn y & " multiplied by " & x & " = " & x * arguments.b />
</cffunction>

Listing 1.16 examining the two methods

You can see that both functions have a variable called x. The baseNumber() function stores the value of the argument as the x variable, which it returns into the multiplyNumbers() function for use in the equation. The multiplyNumbers() function also has a variable called x, which is the hardcoded number we wish to use as a multiplier, in this case 10.

Within the function, the returned value from the baseNumber() method is assigned to y for use in the equation, but as this included function is run, it overwrites the value of the hardcoded x variable with its own x value. This, in turn, is passed into the equation, which throws off the expected results.

In the previous example, the x value in both functions is public, meaning that it can be altered or overwritten by any included functions, or if in a CFC, any defined method within the component. They are, in essence, set as 'open' variables that can be accessed and amended.

By running the two functions in this way, with openly accessible variables, it has the effect of ruining our ten times table. Imagine that we had a method controlling the shopping cart in an e-commerce application, updating quantities and costs, perhaps even stock levels of products. If we left these public variables open, they could be accessed by any included functions, and the values could change dramatically altering our shopping cart and its data.

Using the Var scope

To avoid this issue, the best practice is to set any local function variables to only be accessed by that particular function. This is achieved by using the Var keyword when setting variables. By applying variable to the Var scope, you are restricting public access to them and declaring that they are only accessible within the method in which they are defined. This removes any chance that external functions will corrupt the values.

Note

You should always use the Var keyword on variables that are used only inside of the function in which they are declared.

Let's alter our code to include the Var keyword to ensure the variables are available only to the functions in which they are written:

<cffunction name="baseNumber" returnType="numeric">
<cfargument name="a" type="numeric" required="true" />
<cfset Var x = arguments.a />
<cfreturn x />
</cffunction>
<cffunction name="multiplyNumbers" returntype="string">
<cfargument name="a" type="numeric" required="true" />
<cfargument name="b" type="numeric" required="true" />
<cfset Var x = 10 />
<cfset var y = baseNumber(a) />
<cfreturn y & " multiplied by " & x & " = " & x * arguments.b />
</cffunction>

Listing 1.17 Var scoping our variables

If we save the code with the Var keyword applied to the variables and view the page in the browser, you will now see the correct results displayed:

Regardless of the type of variable you are using within your component methods, (a query, string, integer, array, or structure) if it is used only within the function in which it is declared, it needs to be Var scoped to protect it and to avoid any unwanted amendments by other functions.

Placing your Var scoped variables

Up to ColdFusion 8, all Var scoped variables were required to be placed after any arguments within the function (if there are any included), and before any CFML.

Enhancements in ColdFusion 9 removed this restriction, and Var scoped variables can be placed anywhere within a code block or function.

Naming your Var scoped variables

While there are no strict conventions when naming your Var scoped variables, be aware that a naming conflict will arise if your local variable name is the same as any defined argument name (or the name of another local variable).

<cffunction name="baseNumber" returnType="numeric">
<cfargument name="x" type="numeric" required="true" />
<cfset Var x = arguments.x />
<cfreturn x />
</cffunction>

Listing 1.18 baseNumber function

For example, if we have written the baseNumber() method as in the previous code, with the argument and local variable both called x, this would display an error, as a local variable within a function cannot be declared twice.

You have been reading a chapter from
Object-Oriented Programming in ColdFusion
Published in: Oct 2010
Publisher: Packt
ISBN-13: 9781847196323
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image