'No-brain' getter and setters

| 29 Comments | No TrackBacks

Brainless getters and setters (those that serve only the purpose of exposing a private member variable) don't belong in your class files. Here's why.

Object Orientated Programming is about interfaces. You create an instance of an object because you need it to do something, whatever that something may be. How it does that something is determined by it's interface. The interface to an object is everything that is marked "public" inside of it class definition.

In Flash there are 3 elements that can be made public to compose the interface of an object - variables, properties, and methods. The key to everything I'm about to say comes from the basic principle that variables and properties have the exact same behavior from an interface standpoint. That is, properties look exactly like variables even though behind the scenes they are very different. See the livedocs for more information about properties. The beauty of OOP is that the "behind the scenes" stuff does not matter to users of a class.

What does this mean to you, the creator of a class? It means that you can have the exact same interface to your class regardless of whether you use public variables or public properties. A user of class knows they can set "name" to "Darron" because the interface to your class says they can. What happens behind the scenes is not important since the implementation is encapsulated by the interface. Encapsulation is one of the main principles of OOP, so let's use it to our advantage.

Consider this example. This is a typical Person class with a firstname and a lastname.

class Person {

	// private backing variables for public properties
	private var _firstname:String;
	private var _lastname:String;

	public function Person(firstname:String, lastname:String) {
		this.firstname = firstname;
		this.lastname = lastname;
	}
	
	public function sayHello():Void {
		trace(this.firstname + " " + this.lastname + " says hello!");
	}
	
	// create a "firstname" property
	public function get firstname():String {
		return this._firstname;
	}
	public function set firstname(value:String):Void {
		this._firstname = value;
	}
	
	// create a "lastname" property
	public function get lastname():String {
		return this._lastname;
	}
	public function set lastname(value:String):Void {
		this._lastname = value;
	}
}
// create myself as a person
var p = new Person("Darron", "Schall");
p.sayHello();

// like magic, turn me into Jesse Warden
p.firstname = "Jesse";
p.lastname = "Warden";
p.sayHello();

Is there anything wrong with the above example? Obviously there is since I'm using it as an example, but it's not so obvious by just looking at the class. I was always taught in college to make class variables private. There is a lot of merit to that statement - you don't want someone using your class to have access to the private internals of your class because they might be able to break it by setting "bad" values. To keep your class in a consistent (not broken) state you provide accessors and modifiers (getters and setters) to control access to the private data of the class.

So I did everything by the book and created public firstname and lastname getter/setter pairs that allow users of my Person class to modify internal data. The problem is... what I just did was completely unnecessary and added extra bloat and filesize to my Person class. Because those getter/setter pairs have "no brain" and just provide access to the private variables, I should not have made public properties at all. They don't add anything to the class file that couldn't have been gotten by simple making the private variables public, so they're useless.

Again, we're talking about interfaces here. This new Person has the exact same interface as the old person:

class Person2 {

	public var firstname:String;
	public var lastname:String;

	public function Person2(firstname:String, lastname:String) {
		this.firstname = firstname;
		this.lastname = lastname;
	}
	
	public function sayHello():Void {
		trace(this.firstname + " " + this.lastname + " says hello!");
	}
}
// demonstrating the interface remained the same
// create myself as a person
var p = new Person2("Darron", "Schall");  // just changed Person to Person2
p.sayHello();

// like magic, turn me into Jesse Warden
p.firstname = "Jesse";
p.lastname = "Warden";
p.sayHello();

You can see the Person2 is a whole lot smaller and I would argue more maintainable because there's less code in the class file to wade through. Because it has the exact same interface, Person and Person2 can be used interchangeably. There's nothing wrong with making a variable public if you have a "no-brain" getter/setter pair that exposes it anyway.

In fact, here are some reasons to use public variables over "no-brain" properties:

  • You remove the overhead of having to call a method everything you access the property, since you can access the variable directly
  • There is no "set calls get" bug since we're not dealing with properties anymore.
  • Easier to read, less typing, easier to code, less clutter in source code. All of these can be filed under easier to maintain.
  • Smaller filesize - since your class files are downloaded with the .swf, the less code in your class file means the less that users need to download.

Additionally, if you decide that you should later need to switch to using a property for a consistency check, it's very easy to refactor Person2 to support this. Again, the interface remains exactly the same so everyone using your class does not have to change their code. Rather, "it just works" because the implementation is encapsulated.

An example of the refactoring... let's say you want to only set the firstname if the value it is being set to is not an empty string. With a public variable we can't check this, but with a property we can. Here's the refactored Person2 class, which I named Person3.

class Person3 {

	private var _firstname:String;
	public var lastname:String;

	public function Person3(firstname:String, lastname:String) {
		this.firstname = firstname;
		this.lastname = lastname;
	}
	
	public function sayHello():Void {
		trace(this.firstname + " " + this.lastname + " says hello!");
	}
	
	// provide access to private variable
	public function get firstname():String {
		return this._firstname;
	}
	// provide a consistency check in the setter
	public function set firstname(value:String):Void {
		if (value.length > 0) {
			this._firstname = value;
		}
	}
}

There are only 3 changes that I made. First, I marked firstname as private and renamed it to _firstname since firstname will become the property name. Then I added a getter to access _firstname. Finally, I added a setter that checks to make sure firstname is not set to an empty string. That's all there is to it, nothing else in the class file needed to change. Refactoring public variables to public properties is really that simple.

Now, with all of that being said, there are still times that you want public properties over public variables. Here are a few of the common cases:

  • The property is read-only (that is, only a getter is provided)
  • The property doesn't directly relate to a "backing" private variable
    • get date might return month + "/" + day + "/" + year
  • You need to provide a consistency check for the setter (like I did in the above Person3 class)

There may be more, but those seem to be the most common ones.

So, all of that to say this: If you're using "no-brain" getter/setter pairs, considering refactoring to public variables instead. The interface to your class will stay the same, and you can remove some bloat from your class files in the process. As demonstrated, it's always easy to refactor at a later time if you need to.

No TrackBacks

TrackBack URL: http://www.darronschall.com/mt/mt-tb.cgi/32

29 Comments

Great post Darron. I often find myself trying to follow "best practices" (like using getters and setters) just because I trust them, even when they don't make sense or seem like a waste of time. This shows at least one example where you can keep the advantages of a best practice without going all-out right from the start.

I too have a habit of creating 'brainless' getters/setters b/c of best practices. Thanks for the post.

I'd agree with you if:
- you provided a solid example of how much this really impacts performance
- you weren't talking about Flash

I do understand, however, you've got a seriously skilled data modeling background, though. Typically in Model classes, your data is just there to hold stuff, and very little validation is done after the fact.

I, as a primarely GUI developer, have to massage my data ALL the time, every time. The reason I write no brainer gettter/setters all the time is because EVERY time my class gets near done, I'm doing some sort of either minor, in class validation, or the properties greatly affect how the View shows them.

Your jump from Person2 to Person3 is a perfect example of why I just start at Person1, and add validation code (usually minor) and it becomes Person3; but the key is I start with the no brainers. Not to mention the fact that my class itself always sets the private itself, and very rarely actually class the actually setter (excluding when it instantiates, which is just 1 time).

So, while I agree with you from a Model/Data standpoint, I disagree from a View/GUI one.

I can't say more then using no-brainer getter/setters just feels more logical, especially working with components. Even with the possible performance and filesize hit in mind, which is a good point.

In any case I always use the private variables inside the class code itself, not the getter/setters. Unless there is some needed logic in the getter/setters off course. And mixing public vars and properties at some point might feel a bit ackward perhaps?

Wow, interesting from Jesse-- because being more of the GUI side of things is exactly why I try _not_ to ever get ahead of myself with the code. I can't count how many times I've started with carefully structured classes when creating some GUI widgets - getters and setters included- only to pitch the whole idea the next day.

Although I guess it depends on the kind of GUI developing you're doing. I can see how if you're making the final implementation, your post makes total sense. But in the earlier, iterative prototyping phase, it's easy to waste a ton of time creating well-structured classes that end up in the trash...

Then again, maybe all your early prototypes are perfect the first time ;)

Jed, what harm is there leaving them in? You don't have to change them once you do and if it's a prototype, are you really caring about such small speed gains from making them simple public variables?

...I am SO with you on the prototypes, though, I usually make them public; in fact, I ALWAYS do this in Flex because I'm still learning. In Flash, though, I typically know what I want to do for projects. For simple side small projects, or testing out stuff, yeah, I still do public vars there too, but it's not conicious; because I'm in the habit of writing getter/setters all the time, and have written a JSFL script to write them for me, I find myself doing it even when I don't have to.

As far as public variables feeling weird, that's fine internally, but externally, the user/class users/class using your class doesn't know the difference, nor should they, and that's awesome.

Besides, getters/setters are function looking things anyway; I add a line break, and that's enough of a difference to me; bunch of 1 liner props, and a ton of tiny functions. I see your point, but if you call them properites vs. variables like Darron did, that may help.

right- I don't care about such small speed gains from performance- it's more about the speed gains from me not typing more than I have to. But like you said, once it's second nature then no biggie- you probably only lose 20 seconds of typing time.

I disagree with having public variables and always make them private with no-brain getter/setters. If they are public, you are killing encapsulation in that you are exposing a variable that may get used in private methods. In your simple examples, you don't see it, but most likely in a real class you would have additional private methods that made use of your public variable. Now, what if you decide to change your implementation of that private method and you need that variable to be an object instead of a string for example. You've just changed your interface. Can't do that. Now you need to make your public variable private, change its name to something else, and probably finally make your getter setter that allows the interface to stay the same, and convert it to the new type.
OK, so you say well, if that happens, I can go ahead and do that, but for now, it's ok for it to be public. True enough, but I feel that's a bad way of designing. Good design anticipates and encapsulates potential change, and makes future changes have less impact on the design. Starting out with getter/setters means you never have to massage your interface to deal with internal changes.

A public variable and a no brain getter/setter pair have the exact same effect on encapsulation. Remember, encapsulation is hiding the implementation of the class. Whenever something is public though, it's part of the interface by default. So, using a no-brain getter/setter or a public variable in a private method is one in the same, since all the getter setter does is proxy the private variable and in a sense make it public by association.

Now, if you getter/setter is used to keep your class in a consistent state, then it's no longer a no-brain getter/setter and this argument and entire blog post no longer applies.

Remember here, I'm talking about interfaces to classes. Once you decide on the interface to your class, you're free to implement it however you like. No brain getter/setter and public variables are the same thing.

I'm glad I generated so much discussion on this. Instead of just mindless copy and pasting code, or adopting suppsed best practices "just because," it's good to think about what you're actually doing and what kind of effects that code may have on a system.

I don't start out with getters and setters, because most of the time they end up as no-brainers and that never changes throughout the life of a project. There have been a few times where I needed to refactor a public variable, but it was always just a quick few lines to change. Of course it varies by project and what you're using it... but the beauty of properties is that we can add getters/setters behind the scenes without any noticable change to the interface.

I have to agree with Keith... There have been times in my classes where initially it seemed as if the public vars would be enough, but as a project evolved, it became evident that events would have to be fired when certain properties were changed. Using the brainless getters and setters made my life a lot easier... All I had to do is go in there and add a dispatchEvent call and I was done. No refactoring or anything. Isn't that the whole reason that the "brainless" getters and setters are there in the first place? (to make potential changes in logic easy to implement without changing the interface)

I think Keith is right. It is all about encapsulation. The "no brainer" setters and getters give you a possibility to change the internal implementation of the method later, if needed. Also, it is a good practice to keep things consistent (not mixing public vars and set/get). You could, of course, first use public variables, and then change them to be accessed with getters and setters, but it makes things confusing.

If we are talking about Flash, the performance penalty of getters and setters is minimal in all cases.

I do agree that it is annoying to write the extra lines of code. It would be better to just keep things as small as possible... :)

Good article Darron.

I have to be honest - part of the reason for my post is about the refactoring aspect for making a public variable a public property.

I'll take this time to plug the ASEclipsePlugin - http://sourceforge.net/projects/aseclipseplugin/

I'm currently adding in support for a "Generate Getter/Setter" dialog, which will allow you with just a few clicks to turn a public variable in a private variable and a public getter/setter pair automatically without you having to code it yourself. So, if you need to refactor it will take 2 seconds to generate the getters/setters, then you can add in additional code as necessary.

It'll be avaialble sometime, once I get around to finishing it and checking it into CVS. :-)

It would also be a cool feature in code editor if one could just press a button and the editor would create the setters and getters automagically based on the private variables. That would save some nerves some times :)

I would only use "Person 2" if that class was implementing an Interface in a design I was doing since you can't put setters and getters in an Interface. Otherwise I would be all over my getters and setters ala "Person".

I personally never use properties mainly because of the set get issue. So I typically do what Darron is suggesting seeing that the interface is the same.

If props need some good ol logic I use getProp() setProp() methods.

-erik

I favour the property approach because I often need to trigger events when the property of an instance is changed. However, this aside Darron is absolutely right in terms of 'no-brainer' property modification being simply a wasteful proxy to a public variable.

One question though. What is the seemingly notorious 'set get' issue?!

When you set a property, the getter for that property is automatically called:

http://www.darronschall.com/weblog/archives/000071.cfm

This could be modified to taste; I use it to get me started when I already know my privates (gross):

http://dev.jessewarden.com/flash/jsfl/JXL%20Property%20Writer.mxp

http://dev.jessewarden.com/flash/jsfl/JXL%20Property%20Writer.zip

there is a certain school of thought in best practices that says you should never even use implicit getter/setters, only getter/setter methods. it's a bit of a purist viewpoint based on the fact that objects communicate by sending messages and messages are sent by calling methods. by using implicit getter/setters, you are still using a method, but you are obfuscating the fact that you are doing so.
Personally, I mostly use implicit getter/setters in components, where you almost always have an invalidate call in there as well, to cause the component to redraw on the new data. properties just seem more intuitive on components than setWidth(100), setHeight(50).
for communication between other types of classe though, I generally do go with a regular method.
anyway, congratulations on a fine thread!

Encapsulation aside, what are we doing here all said and done?

Is it a matter of reducing a long winded "no-brainer" methods to public variables for the sake of saving time in typing / maitenance? or do we simply roll the setters/getters as no-brainers on the offchance we come back and verify arguments being sent / in out.

Take coldfusion for example, folk have been going BEAN crazy by creating setter/getters for every public property within a bean - yet all it does is make sure an argument being passed in is of a specific type.

Thats the key, as when I implement a setter/getter at the very worst what i am doing is making sure the arguments being pushed into my class is of a specific type (string, data, object) etc - so no assumptions are made and a contract is established.

I can see the angle in which Darron is approaching and tend to agree - mainly because i freakin hate typing....

On the flipside i can see jess's point, and with UI you need to VALIDATE nearly everything as it just takes one numeric value to be out of sync and ..things happen.

This argument has been made before and one good overview was this:

You can write 115 lines of code to output "hello world" or you can write the code, with a generic interface, output hello world - then if things change refactor its implementation.

Thats what my interpretation of what Darron's saying, in that as long as you keep the interface into that object consistent - the "hows" inside that object is up to the engineer - provided you aren't holding strict type castings in place.. ie i have seen situations where methods have been implemented that assume an objects being passed in, but yet sometimes a string could be passed in? then what? how do you rectify that problem...especially if the argument has no "type" assigned?

There are ways around that which is outside the scope of this post but thats my only basic ruling for having no-brainer setter/getters - type casting.

Good read though!

Thanks for the comments everyone.

@Scott - You can retain type information from switching between a public variable and a public property. See my Person examples above.. trying to set firstname to something other than a String with generate compile errors in "both versions" of the implementation.

Obviously, this one doesn't have a clear cut right and wrong answer. I think it comes down to what you are most comfortable with. The beauty of OOP is that, as stated, interfaces can stay the same but the implementation can vary greatly.

If I got you to think, then this post was a success. :-)

Oh yeah..sorry i forgot about that in FLASH - my bad had CF on the brain while typing this...my dumb assumption ;)

heh..

true, provocation of OOp thinking is good as it sux watching talented folk follow OOP ZEN blindly - why because someone they respected said it was the LAW...

I agree with you, but I don't think you've gone far enough: personally, I consider *all* getter/setters to be brainless, regardless of content. I'm one of those "purist" sorts that feels that what code does should be apparent by casual visual inspection: if it looks like you're setting a member variable, that shouldn't secretly invoke a method under the surface. Does this violate abstraction? Yeah, a little, I guess, but frankly, if you want a method to get or set something, why not make it a method?

Yeah, the getter/setter stuff in AS2 has an effect on code size and speed, but that's not my major objection: it's the hidden-side-effect syndrome.

Of course, keep in mind that I'm also the sort of coder that feels that member variables should almost always be private to the class itself -- not even exposed to subclasses.

I think that the point, special cases aside, is that public variables are simpler than no-brain getter/setters. When I'm going for speed and developing a simple prototype, it makes sense to not put them in at first. If I need to refactor then I do it when necessary.

BTW, where are the refactoring tools for AS?

Well, the reason I'm using Getter/Setter is due to the fact that when you use initObj and define those variables via Get/Set those variables will be defined before the constructor is being called. sometimes it is very crucial.

re: get/set properties versus method calls:

I recall reading something in the Microsoft Design Guidelines (probably via Brad Abrams) saying that what the call does should be your guide: for a simple property that does little to no processing, they suggest using a getter/setter. If it's going to involve a moderate to extreme amount of processing, use a method. If I remember correctly, one of the reasons had to do with accessing object remotely, as a consumer of the object would expect a property call to respond instantaneously, while a method call would be expected to involve some sort of delay (I'm leaving that somewhat simpler than the actual explanation).

I'll see if I can dig up the link to that.

Late to the game on this post, but I agree with Darren's assertion against brainless getters and setters. You can refactor to the getters/setters as needed.

I find Stephen Johnson's comment about side effects interesting, but I think that with proper encapsulation, a class's client does not have to worry about side effects regardless of a getter/setter or use of an explicit function. Skill is definitely important in making this work smoothyl.

I have become very interested in these best-practice-scenario discussions as of late.. Mostly because I have finally wrapped my head around OOP and am just now beginning to see the difficulty in changing your interface at a late point in a project.

How do you feel about using getter/setters with private variables? Is there any good reason to be consistently operating on private var's before they are set?

Leave a comment



About this Entry

This page contains a single entry by darron published on March 2, 2005 10:37 AM.

Know thy Class Library was the previous entry in this blog.

Excellent article on using MTASC, ASDT for Development is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.

Archives

OpenID accepted here Learn more about OpenID
Powered by Movable Type 5.02