Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at Scotch On The Rocks (SOTR) 2011 (Edinburgh) with:

Moving Away From VARIABLES And Getters / Setters

By Ben Nadel on
Tags: ColdFusion

In my quest to become the best ColdFusion programmer that I can be, I have been reading a lot about object oriented programming and looking at framework examples and pretty much anything that I can get my hands on. One of the things that I have picked up over the last two years or so is the use of the VARIABLES scope within ColdFusion Components and the use of Getters and Settings in retrieving information stored within that scope.

Take, for example, a simple configuration component for a web site, Config.cfc. Assume that I have a boolean value in it, IsLive, that determines whether I am working in a development or production environment. Right now, I have that value stored not only within the VARIABLES scope, but within a structure name Instance:

  • <!--- Set default islive value. --->
  • <cfset VARIABALES.Instance.IsLive = false />

Then, I had getters and setters for this:

  • <cffunction name="GetIsLive">
  • <cfreturn VARIABLES.Instance.IsLive />
  • </cffunction>
  •  
  • <cffunction name="SetIsLive"
  • <!--- ... --->
  • <cfset VARIABLES.Instance.IsLive = ARGUMENTS.IsLive />
  • </cffunction>

The idea is that Instance structure could be used as a light weight transfer object (LTO) if I ever needed to get all the configuration settings at once and pass them around:

  • <cffunction name="GetTransferObject">
  • <cfreturn VARIABLES.Instance />
  • </cffunction>

And, I could get and set the IsLive value through the Config.cfc getters and setters:

  • <!--- Get islive. --->
  • <cfset blnIsLive = APPLICATION.Config.GetIsLive() />
  •  
  • <!--- Set islive. --->
  • <cfset APPLICATION.Config.SetIsLive( true ) />

As I was learning, this is the kind of stuff that I read about. And, since I knew nothing about good object oriented programming, I accepted it without question. But now, I am just not seeing the value of it. Granted, I am sure I misunderstand a lot of what I read and I interpreter incorrectly, but as I have worked it into some applications, I am finding only that the use of getters and settings does nothing but add overhead. Like why is this:

  • <!--- Get islive. --->
  • <cfset blnIsLive = APPLICATION.Config.GetIsLive() />

... better than this:

  • <!--- Get islive. --->
  • <cfset blnIsLive = APPLICATION.Config.IsLive />

The first adds the overhead of a method call. The second is direct access. Granted, with the second one, I have KNOW what the name of the variable is called inside the CFC and I have to KNOW where it is stored (ie, VARIABLES or THIS or whatever)... but, how is that any different from having to KNOW that there is a method called GetIsLive()? I would argue that both require an intimate understanding of the structure of the Config.cfc.

Granted, I understand that if the call is made through a getter/setter, then I can change the internal workings of the Config.cfc and the rest of my application doesn't need to know about it. But that begs the question, how often do I change my Config.cfc object? I would say only from project to project, but NEVER in the middle of a project. Now, maybe that is because I am not doing things correctly, or maybe my applications are just small and not scale-worthy... or maybe it's that the information in Config doesn't need to change in a way that impacts everything else. I don't know.

And then there is the idea of the light weight transfer object (LTO). I understand the idea, but have never used it. When I reference configuration information in my application, it's generally in the request as in:

  • <a href="#APPLICATION.Config.GetUrl()#">Home Page</a>

... well technically it's more like:

  • #APPLICATION.ServiceFacotry.GetConfig().GetUrl()#

... but I am not gonna get into that whole mess. The bottom line is that I NEVER pass around a light weight object for configuration. Even when it comes to DSN, which is used everywhere in the application, I don't pass around the Config LTO (which does have DSN info) - I just pass around the DSN object itself:

  • <!--- Create some controller that requires DSN info. --->
  • <cfset objController = CreateObject(
  • "component",
  • "foo" ).Init(
  • DSN = APPLICATION.Config.GetDSN()
  • ) />

Here, I am getting the DSN from the Config.cfc and passing it in as an initialization argument to some controller component. I would rather pass in information during configuration than have another object have to know how to call methods on the configuration object. Isn't that what low coupling is all about?

So, I argue, why can I not move all the INSTANCE variables directly into the THIS scope and then just reference them directly and even, if need-be, pass around the Config.cfc as if it were the LTO? What would I be losing? If anything, I would be cutting out a number of method calls that were doing nothing but adding processing overhead to each page call.

Now, I understand that there is overhead to passing around large objects. Meaning, that it is faster to pass around a LTO than it is to pass around a large, beef-tastic component. But again, I have to ask, when do I even need to pass around so much information? Hardly ever. REMINDER: I am not a good OOP programmer, so I don't know the ins and outs of it all.

And let's talk about security for a second. One of the reasons for getters and settings is that you can create and interface to the data that can stop people from doing stuff. Going back to the IsLive boolean example, I actually do NOT have a setter for that value (the above example was only a demonstration). That is a value that can ONLY be gotten since it is calculated by the configuration entity and NOT by the programmer. So here, the idea is that now, we never have to worry about anyone messing with the IsLive value since there is no setter access to it... phewww! I was worried there about malicious code telling an application on the production server that it was actually on the development server and displaying path and DSN information on the screen.

Oh wait! Who would ever set that value? Only people working on the project. Most of the time that is me. Sometimes it is someone else. But, wait, I don't understand. Am I protecting the programmer from himself? That seems a bit odd doesn't it? It would be like having someone walk around next to me all day long in an attempt to stop me from slapping myself in the face. It's crazy! Heck, if I am going to slap myself in the face, then the only person to blame is ME. Not, the people who didn't think about building in that safe-guard against self-face-slapping.

I would argue that the same logic applies to Config.cfc. If I am stupid enough to fake the application into thinking it is on the wrong server and dumping out secure info... well then, I get what's coming to me. And besides, how is having to know NOT to change that value any different at all than know that there is no setter methods on that value? Both require knowing exactly how the object works?

Now, I know that the IsLive value is very simple example and that there are much more complicated situations. My point though is that, especially on smaller projects, all this private scoping, getters, setters, and what not is just not needed. If I am gonna be malicious, then I deserve to get burned. So, to get to the point, I a moving stuff out of VARIABLES and into THIS. I am referencing things directly in the THIS scope. I am getting rid of method call overheads. I am setting values directly. If I don't know HOW it all works, then I need better documentation, NOT better object interfaces.

Again, I can't stress enough that I am new to all this OOP jazz and I know there are proven "patters" out there that work for time-tested reasons. But in my head, knowing how variables are stored is the same as knowing what interface methods are available. Of course though, if a getter does more than just return a simple value, then naturally it is still needed.

Just some thoughts....

But what about validation? If you can just set a value, the programmer might set the wrong type into the variable?

... Yeah, but isn't the same true for a method. What if they sent the wrong argument type? Same thing.



Reader Comments

Ben,

According to my limited knowledge about OOP (especially in Java), I know that Setters and Getters is a way of getting and setting object Properties value, here in CFC it is THIS or VARIABLES variables, exactly as you explain. And as you said, it's a type of protecting some variables from directly access from out of Class. Variable name is different than property name, where the variable shouldn't be known to the one how will use the Class Objects. Even that Variable must be in Private scope, so even if he knows the variable name he will not be able to access it, but only through the property. In Java, setting and getting value is simple and automatically detected by the Class, where it will know the case of call is it SET or GET. So if programmer writes:

btnStatus = Button.Disabled;

this will be GET, and if he writes:

Button.Disabled = false

In this case it will be SET, if I am not wrong.

And one other feature in Java is that you can have read-only property that will has a value while object creation in the Class Constructor only, where we are using init() function in CFC as a Constructor. One more advantage of using Property is that you can do a lot of things while Setting/Getting value to/from variable. I don't remember what the exact syntax of creating Java Property is, but I'll write a pseudo code simulating that:

// Creating Boolean Button Disabled Property
Property Disabled …{
Set{
// …. So here is you can write what ever code you need
// …. Changing other related property, calling function… etc.
set the variable value}
Get{
// …. So here is you can write what ever code you need
// …. Changing other related property, calling function… etc.
return the variable value}}

So if we can implement something like that in ColdFusion component, it will be pretty. A question in my mind is come now that, what the use of CFProperty tag in ColdFusion component is? Does it even do a little bit of what Java Property do?

As I said I have limited knowledge about OOP, I don't know if I'm wrong in some where or no.

Reply to this Comment

You are in a maze of twisty little Java VMs, all alike ... welcome to the dark underbelly of OOP.

You are 100% - the theory sounds good, but the practice is a little suboptimal. Properties, which CF doesn't have, came from the proliferation of getters and setters, which came from the need to keep programmers from shooting themselves in the foot. And really, they are much more applicable to black-box binary libraries than they are to the "we're all friends here"-type approach that CF has. There's not much you can really do in CF to prevent someone else from twiddling with your internal variables.

But the theory, as you discovered, is that properties/getters/setters allow you to do validation on the incoming data. Not just type validation, but maybe also range validation, sanity checks, etc. This means that your code has a theoretically longer shelf-life, as there are a lot more sanity checks built-in, and it'll be harder to break later on, and you'll lave less chance of getting the urge to throw it out and recode it from scratch. (And, for me, it means that I can put in chastising and condescending error messages that shame coder-monkeys into doing things the right way instead of the lazy way. And I love doing that.)

Personally, I use getters and setters for things that have some kind of meaning to them and can have "right" and "wrong" values. But if it's just a simple value, such as a multiplier or a static text string, or something that doesn't require any sanity checking, I don't bother.

But, having said that, I'll also say that I rarely use getters and setters. My (current) coding model is that you should have exactly one chance to set properties for an object: at creation. If you don't set it in the init(), why are you setting it later? Do you have a really good reason for it? Yeah, there is the occasional exception to this, but stopping to think about it helps me immensely. (It has the additional benefit of making for more thread-safe and scalable code - you don't have to worry about when values might change.)

YMMV. There's no "right" answer. But it's great that you're thinking about it and not just regurgitating what you've been taught!

Reply to this Comment

My biggest irritation with the whole thing is that I don't quite feel that my current style of programming is bad. I feel quite productive. I am not often hitting road blocks where I think to myself "There has got to be a better way!" I think there is a "better way" because I am not doing it the way the programming veterans do it.

Sometimes, I get so frustrated because I feel like I am trying to solve a problem I don't have.

Of course, if I could just wrap my head around all the OOP stuff, I might feel differently. But no matter what, I just want to be doing stuff in the best way possible.

Reply to this Comment

Depends on the implementation, if you are passing a lot of varables which may be of one type, maybe sending them as an array or all at once into the class or object or if the varables are only used to set up the object, send it as a constructor...

eg.
instead of:
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}

do:

public void setCords(int x, int y) {
if (x != null) this.x = x;

if (y != null) this.y = y;
}

OR

public void setCords(int[] cords) {
if (cords.length < 2) this.x = cords[0];

if (cords.length < 3) this.y = cords[1];
}

and

public int[] getCords() {
return new int[]{this.x, this.y};
}

[note: example done in java code, code has not been tested]

there is also overloading as well that can get rid of a lot of setters and the use of overloading

......

In a nutshell, only use setters and getters when you have to and if you do, make sure you get your variable types and names right beforehand ;)

Reply to this Comment

Hi Ben,
Quick question mate!
5 years after this post was written, do you still feel the same towards setters and getters in your code?
I only came across this post as I come from a PHP background and I was explaining to my CF friend about setters and getters and he came back with this article! Hardly extolling the virtues of the practice! haha
Thanks

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
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.