Read more about this article at my web site.
Like many experienced programmers over the years, I have been exposed to hundreds of different programming styles,
read long philosophical threads about programming methodologies new and old and have been fortunate enough to work with some really expert programmers.
For the most part, I have enjoyed the dialogue and somewhere along the way have learned to let go of of the small stuff,
that is unless of course the small stuff which I would otherwise overlook in the right context, is at risk of becoming
detrimental in the wrong context.
I can remember when I was learning to sail I kept calling those things that hung off the side of the boat bumpers
when in fact I should have been calling them fenders. My instructor immediately corrected me and said "its ok, that really
used to bother me but I've learned to let that one go." What he had learned through unfortunate experience, was that students
needed to understand immediately how to tie fenders on correctly well before the vessel reached the the slip so as not to
damage hull, less important to him was what we called them at the moment of impact. Besides, I would learn the correct
terminology with more practice soon enough.
So back to the subject at hand, properties. Properties are one of the small things I've learned to let go of over the years,
because there is just so much widespread confusion over them that they have become ubiquitous. It would require a huge
investment of resources and time to get emotionally tied to their "proper" use one way or the other, unless, as I mentioned
earlier, I feel they are endangering the codebase.
If you search for the effective use of properties, you'll find literally thousands of conflicting statements about why properties exist,
when to favor properties over member variables and even whether they are evil and should be exercised from all properly
object oriented code completely. Yet in object oriented programming classes, we're told that people have certain properties
like a name or sex or origin, and we should immediately start adding them to the person base class (another thing I'm learning to
let go of..) so that whatever extends that person class will pick up those common properties. OK fair enough, this is exactly how I learned about properties too.
So are properties really a bad idea?
My thesis is that as long as we don't violate some important design principals, properties are absolutely fine under most
circumstances. What are properties exactly? Well, if you wiki property, you'll find that a property is defined as a kind of hybrid
sort of class member somewhere between a data member and a method. In the spirit of keeping it simple, I have highlighted some rules about properties and how to use them without causing too much damage.
Maintainability:
Do the properties you are about to add offer more or less maintainability? In other words, are you writing a class to DoSomething() or are you writing a class that requires the dependant class to get all the information from you and then doSomething(). Good object oriented classes DoSomething(), not the other way around. It is generally acceptable to return an object or interface using property accessors. For instance, if our person class, is used by our personnel system, we expect the personnel system to ask the person for their address and to have the person return the address to the personnel system, what we don't want is to have the personnel system ask the person for the street, city, state, and zip code and then have the personnel system build the address, that would be counterintuitive.
Object Oriented or Procedural Programming:
Are you really writing OO code if you have properties everywhere? Consider for instance that procedural programming relies on local knowledge of objects to perform tasks while OO programming is based on use cases and conversations. Do getters and setters come up during conversations? I will reference the experts Kent Beck and Ward Cunningham for more detailed information but I encourage you to think about the classes you need, and the responsibilities they must perform as well as how they will collaborate. Beck and Cunningham developed some really good practices using CRC cards to model “conversations between classes”.
Encapsulation:
While properties offer better encapsulation than fields do, you shouldn't necessarily start blindly replacing fields with properties in every case. The more accessors you create, the more dependency you create and the more at risk you are to exposing implementation details of your class. Consider your DoSomething() methods, do they take reference or value parameters. Also consider the use of internal and private properties carefully, do you really need them?
State:
Getters and setters which "report" get or "change" set the state of some private member variable shouldn't change the state of the object itself, or any other unrelated object for that matter. Remember when I said that a property is somewhere between a method and a field or member? This is one of the potential hazards of treating your properties as methods. Code in getters or setters which change the state of the object itself will cause unbelievable headaches from adopters. Properties should be reliable, if you call any property repeatedly, you should be able to depend on the value returned from the getter.
Performance:
Impact on performance is another potential pitfall of treating your properties as methods. Performing lengthy or costly operations in getter or setter methods could significantly impact performance. Having for instance a large custom collection or web control object which is dynamically built or retrieved in your getter or setter methods could slow performance as objects are added and increase performance as objects are removed. This can lead to lots of head scratching from adopters, not to mention the loss of hours of productivity troubleshooting mysterious performance issues, which appear and disappear for no reason.
So should you use accessors or not? In my experience, when you start working for large corporations, refactoring decisions sometimes become more about ROI than style and quality is re-defined as the number lines of code over defects or the number of unit tests over uncovered blocks rather than the elegance of design or the implementation of industry best practices. Style and elegance often gives way to brute force. Human beings are certainty freaks, and we have to balance planning and risk with our "drop dead" delivery deadlines. There is never enough time up front but then again, nothing lives forever anyway right? To sum it up, if you are going to use accessors you need understand what they are for and for goodness sakes use them properly because, just to tie the metaphors together, a damaged hull is expensive to fix and if the hole is big enough you may never fully trust the vessel again.
Beck, K. & Cunningham, W. (1989) A laboratory for teaching Object-Oriented Thinking. Apple computer whitepaper, http://c2.com/doc/oopsla89/paper.html#references
Wagner, B. (2008) Choose between Methods and Properties. Visual Studio Magazine p.40 http://visualstudiomagazine.com/columns/article.aspx?editorialsid=2719
Haloub, A. (2003) Why getter and setter methods are evil. http://www.JavaWorld.com