The amazing adventures of Doug Hughes

This morning I received an email from Jason, whom I met at CF.United():

We are working to adopt/increase OO in our environment. We were debating over what may be best practice for object properties as far as ColdFusion components are concerned. For example:

<cffuntion name="init" ...>
	<cfset this.foo = "bar">

Vs.

<cffuntion name="init" ...>
	<cfset variables.instance.foo = "bar">

From the conference, conventions seemed mixed. We understand from blogs the benefits of the later example from a practice standpoint in mirroring OOP. However, are you aware of any performance advantage or future directions of either? One of use remembered hearing something particular about using “this”.

First, allow me to give a little background for those who may be new to the concept. In the same way that ColdFusion provides a plethora of scopes including the variables, request, session, and application scopes, CFCs provide two scopes of their own: “this” and variables.

The “this” scope is public. Anything can set values into this scope from outside the component. Essentially, it treats a component like a structure with methods. The result is that you have no protection over the data in your component. Programmers can accidentally (or intentionally) add bad data into your CFC which may break it or change its behavior in ways you do not want or intend.

In CFCs the variables scope is private. Only the component itself can write to the variables scope. This allows you to hide the component’s data and control and validate access via methods on your component. Getters and setters are typically created for this purpose. This also allow you to do more than just set values. For example, let’s say your component had an email address property. When you call setEmailAddress(), the setter could set variables.emailAddress, but it could also split the string on the @ sign and set variables.username and variables.domain as well.

Well, to directly answer your question, use of the “this” scope is faster. Presumably, this is because each function in a CFC is compiled down to a Java class. Orchestrating all the Java classes required for a CFC instance may add some overhead. In fact, In Model-Glue 3 Joe is actually preferring the use of the this scope due to the performance benefits and the ease of programming.

I’m still a fan of the variables scope with getters and setters. I like the notion that, if I need to, I can change the implementation of these functions. So, if I initially had an email address property that was accessed via a getter and setter I could add validation and/or the extra logic to set the username and domain without breaking the rest of my system. If I were using the this scope I would be unable to do that without modifying any code that touches the CFC. But, I pay a price for that in the time it takes to write the extra code and the overhead that extra code adds.

Beyond that, the use of “instance” variable in the variables scope is not even really a convention. Some people like it because they can now copy variables.instance out of the component easily. I don’t tend to do this.

Comments on: "The Differences Between This and Variables" (7)

  1. Raymond Camden said:

    To be anal:

    “Well, to directly answer your question, use of the this scope is faster.”

    What you mean to say – using the This scope and not get/set methods is faster. You certainly could write get/set methods that modified the This scope. It’s silly, but I’ve seen it before.

    Like

  2. Doug Hughes said:

    @Ray – you’re absolutely right. I was operating under the assumption that there were no getters and setters for the this scope.

    Like

  3. Raymond Camden said:

    Well there aren’t – unless you write them. Ditto for the Variables scope. You could use Variables w/o get and set methods. For example, your init func could set all the Variables you need and the rest of your CFC would have no get/set. Many of my CFCs that do API type stuff have an init that lets me pass in a few values, but I don’t bother with get/set since the info is just initial config type information.

    Like

  4. Paul Carney said:

    I agree. We lockdown the attributes within our CFCs using the variables scope, then create getter/setter functions for them.

    It is a clean way to handle data, with a bit more coding. We also tend to put the getter/setter functions at the end of the CFC (other functions at top) as they are not modified often after creation.

    We also religiously use the “init” function for the same reasons: consistency and control. If there are things that the component must do as it is created, then it should be in the “init”, which should be called every time the object is created (like in Java), so that we don’t have to worry about other places that are doing their own init items.

    Like

  5. Joe Rinehart said:

    > In fact, In Model-Glue 3 Joe is
    > actually preferring the use of
    > the this scope due to the
    > performance benefits and the ease of
    > programming.

    Just to clarify this – I recommend having domain objects with an API that properly hides data behind accessors. In the innards of Model-Glue, I have a bunch of things (like a representation of a Message) that are simply messages, and the use of a simple memento with everything “public” was a tradeoff – there’s a few places this made doing something that would’ve been “automatic” if encapsulated more difficult and harder to maintain. It’s a tradeoff for some of the needs of MG – lower execution stack,etc.

    Like

  6. Daniel Roberts said:

    I generally go with the idea that get/set is preferred with objects except when working with optimization of data structures or processing with-in a package.

    Structs are used all the time for passing data around and then accessing it with the dot (or array) notation. If we find that using an object is more efficient (isn’t it?) than passing a struct around then adding the set/get just because it is an object would be silly IMO.

    Like

  7. Adam Cameron said:

    I think this-scoped variables have a place.

    A CFC instance could *expose* certain values in the THIS scope, for ease of access and performance gains.

    There’s no harm at all – and good benefits – in doing this:

    However I think – for reasons cited – it’s slippery ground for a CFC instance to ever have to subsequently process that variable after its initialisation, without suitable (and time-wasteful) validation first, because the calling code might have changed “marmoset” to “pangolin” in the mean time (not so good if the CFC instance is one of primate.cfc, for argument’s sake).


    Adam

    Like

Comments are closed.

Tag Cloud

%d bloggers like this: