I’ve seen questions about whether to always provide accessors for ivars, and recommendations, such as in akosma software’s ObjC code standards, that say
Whenever possible, do not specify ivars in the header file; use only @property and @synthesize statements instead.
This isn’t how I work, which led me to ask the question: is this a good recommendation? Obviously the question of whether coding standards are “good” or “bad” is subjective, so what I’m really asking is whether this is something I’d want to do myself.
How I currently work
If I need to be able to see the state of an object from outside that object, I’ll make a readonly property. If I need to be able to change the state of an object then I’ll create a readwrite property. Whether these are synthesised or dynamic properties depends on how I need to compute their values.
If, in implementing a method, I find I need to make use of some object or value that was generated in another method, I’ll create an instance variable to store the value away in the other method so it can be used from this method. I define this ivar in the @implementation of the class.
This effectively acts as a de facto distinction between public and private data. Public data is accessed via properties which can be seen and called from anywhere; private data is accessed via ivars that cannot be seen anywhere except inside the current class (don’t worry about the visibility modifiers @public and friends: because the ivars are inside the implementation even subclasses don’t know what they are).
If I consistently use the property accessors even inside a class, I can see where an object is making use of state that is accessible to the outside world. That can indicate an encapsulation failure, making the class fragile to external prodding. Of course, it’s also expected that objects do get told about the outside world, so it’s not an automatic fail to do this: but it’s useful to be able to see where it happens.
About the “properties everywhere” approach
As I see it, there are benefits and drawbacks to that technique. The pros:
- Encapsulate memory management. This is less of a benefit with automatic reference counting or garbage collection, but in a manually reference-counted environment you can put the memory management semantics in one place rather than sprinkling your code with retain, release and copy calls.
- Consistency. Rather than having two distinct techniques for accessing ivars, you have just one.
- Properties are new(ish), and ivars are old and busted. :-)
- Broken encapsulation. Now all of your ivars have accessors, and as previously discussed here Objective-C doesn’t have method visibility modifiers. All accessors are public (even if declared in the class extension), so any dev armed with a copy of class-dump might decide to change the internal state of your classes.
- Consistency. This is where it gets subjective, because this was also a pro, but as I said earlier I deliberately make a distinction between internal state and externally-available properties, so making both of these the same is a problem.
- Writing code you don’t need. Even where you never actually use an ivar outside of the object that owns it, you’re still writing public methods for that ivar.
I’m not going to be adopting the “everything is a property” recommendation, I value the privacy of my parts. I’ll carry on with writing instance variables where I need them, and “promoting” them to properties with accessors where that’s necessary.