When to use properties & dot notation

I listened to a recent episode of the [cocoaFusion:][1] podcast about properties and dot notation today. There were a few interesting points brought up, but I felt a couple of the most important reasons to use `@property` declarations and dot notation weren’t addressed.

The biggest reason I see to use a different notation for both property declaration and property access than for method declaration and sending messages — even if property access ultimately results in a message send, as it does in Objective-C 2.0 — is **separation of state and behavior**.

In the ur-OOP days of Smalltalk, state was supposed to be *encapsulated* within objects *entirely*. This has become Smalltalk dogma and some developers have tried to propagate it to Objective-C: The idea that objects should *never* expose their state to each other, but instead only vend *behaviors*. It makes a certain amount of sense if you see objects purely as actors.

However, in today’s modern world we understand that objects aren’t *just* actors. Objects both “do things” *and* “represent things;” they’re nouns. And they have both *internal* state that they use in managing their behavior and *external* state they expose to the world.

You can use the same mechanism to do both, as Smalltalk does and as Objective-C did before 2007. However, it turns out that it can make a lot more sense to use different syntax to represent the distinct concepts, even if they’re handled by the same underlying mechanism.

For example, I might have a Person class and an NSViewController subclass that presents a Person instance in a view. The API to my Person class might look like this:

@interface Person : NSObject
@property (copy) NSString *name;
@property (copy) NSImage *picture;
@end

This sends a strong signal to the users of the class that `name` and `picture` are *external* state for a Person instance, leading me to write code like this:

Person *person = [[Person alloc] init];
person.name = @”Chris”;
person.picture = pictureOfChris;

The intent of this code is clear: I’m not asking `person` to do anything, I’m just manipulating its external state. That may cause it to do things as a side-effect, but at least in the code snippet I’m looking at, I’m just interested in changing some state.

Now let’s see what the NSViewController might look like:

@interface PersonViewController : NSViewController
@property (retain) Person *person;
– (BOOL)updatePicture;
@end

And let’s see how I’d use one, assuming it’s been instantiated and wired up in my view hierarchy already:

selectedPersonViewController.person = person;

if ([selectedPersonViewController updatePicture]) {
// note elsewhere that the person’s picture is updated
}

Even though the `-updatePicture` method has no arguments and returns a `BOOL` I (1) don’t make it a property and (2) don’t use dot notation to invoke it. Why not, since it fits the *form* of a property? Because it doesn’t fit the *intent* of a property. I’m actually telling the view controller to perform some action, not just changing some state, and I want the intent of that to be clear to a reader of the above code.

That brings me to the other major reason to both declare properties using `@property` and use dot notation to access them: Xcode. The code completion technology in Xcode tries hard to provide you with a good default completion and good choices in the completion list. But this can be very difficult, especially with the combination of Objective-C’s dynamic dispatch and the sheer size of the frameworks: There are hundreds (!) of methods declared in categories on NSObject as a result of categories describing informal protocols, and any of those methods could be valid on an arbitrary instance.

Dot notation, on the other hand, is **not** valid on arbitrary objects. Even though it compiles to exactly the same sort of `objc_msgSend` dynamic dispatch that bracket notation does, from a type system perspective it actually **requires** a declaration of the property being accessed to work correctly. The reason for this is that the name of a property is not necessarily the name of the message selector to use in dispatch; think of a property `hidden` whose underlying getter method is named `-isHidden`.

This means that tools like Xcode can provide a much more streamlined experience for properties using dot notation. If I write the above code in Xcode, rather than MarsEdit, Xcode will not offer completions like `-autorelease` and `-retainCount` when I type `person.` — it will only offer me the properties it knows are on Person.

Now, you *can* invoke arbitrary getters or setters (so long as they have a corresponding getter) using dot notation. The compiler doesn’t require an `@property` declaration for the use of dot notation, just a declaration. I could have declared the `Person.name` property like this:

@interface Person : NSObject
– (NSString *)name;
– (void)setName:(NSString *)value;
@end

The compiler will compile `person.name = @”Chris”;` just fine with this declaration, to an invocation of `-[Person setName:]` — but Xcode won’t offer you code completion for it if you don’t use `@property` to declare it. By not offering to complete non-`@property` properties for dot notation, Xcode avoids offering you *bad* completions like `autorelease` and `retain` that are technically allowed but are abominable style.

Of course, one complication is that many frameworks on Mac OS X predate `@property` declarations and thus don’t expose their state this way. That means Xcode won’t offer you completions for their state with dot notation until those frameworks do. Fortunately for iPhone developers, UIKit uses `@property` declarations pervasively. You should too.

To sum up:

* Use `@property` to declare the state exposed by your objects.
* Use dot notation to get and set objects’ state.
* Use method declarations to declare the behavior exposed by your objects.
* Use bracket notation to invoke objects’ behavior.

This results in intention-revealing code that clearly separates state and behavior both in declaration and use.

[1]: http://www.cocoafusion.net/ “cocoaFusion: podcast”

18 Comments

  1. Joe Ranieri
    May 27, 2009

    My only complaint with properties is that the compiler requires you to know the type of the object. For example:
    NSSize size = [NSImage imageNamed:@”foo”].size;

    If you wanted that to work you’d either have to use a temporary variable or use a cast. Or, you could just use the message sending syntax, which would be inconsistent with the rest of the uses of the property in the project.

    Reply
  2. eschaton
    May 27, 2009

    I’d probably write that with a temporary variable rather than as a one-liner:

    NSImage *foo = [NSImage imageNamed:@"foo"];
    NSSize fooSize = foo.size;
    
    Reply
  3. Andy Lee
    May 27, 2009

    Very nice.

    I never thought too hard about properties and dot notation. I only knew that they bugged me at first and I gradually warmed to them (though I’ve only used dot notation in a couple of quick non-work experiments).

    Reading this article gave me the immediate feeling of a light bulb going off. The distinction between state and behavior made immediate sense, and it also helps understand when not to use dot notation. In addition to this theoretical motivation, I like the very practical benefits in code completion, which had never occurred to me.

    Reply
  4. Roman Busyghin
    May 27, 2009

    You recommend to use dot notation even for self? For example:
    self.property1 = @”NO”;
    self.property2 = person.age;
    self.property2.name = person.name;

    Reply
  5. eschaton
    May 27, 2009

    Roman:

    It’s critically important to understand that accessing a property via self.foo and accessing an instance variable via foo are completely different in Objective-C.

    The construct self.foo in Objective-C is not the same as the construct this.foo in Java and it is not the same as the construct this->foo in C++.

    Thus in Objective-C if you want to to access the instance variable underlying a property, you use foo. If you want to invoke the getter or setter of a property, you use self.foo. They aren’t interchangeable in any way.

    Reply
  6. Jim Roepcke
    May 28, 2009

    The other important thing about dot notation is it encapsulates memory management idioms.

    Instead of having to worry about getting your getters/setters right, you focus on the task… rvalues retrieve a property, lvalues set a property, all with memory management done properly regardless of the GC’ness of your app/platform.

    I always declare ivars that have properties with an underscore in front of their name, like so:

    { NSString* _foo; }
    @property (…) NSString* foo;
    @synthesize foo=_foo;

    This way I won’t accidentally type:

    foo = bar;

    when I meant to set foo using the property’s synthesized setter like this:

    self.foo = bar;

    (because foo doesn’t exist, only _foo and self.foo)

    Reply
  7. Jim Roepcke
    May 28, 2009

    Oh, and setting ivars using properties is nice because it means anyone with a reference to your object can observe changes to its properties using KVO.

    Reply
  8. Danny Greg
    May 28, 2009

    As I pointed out on the podcast, I am against dot notation, but not strongly. I understand the clear separation between state and behaviour is awesome but I think in Objective-Cs case it can be a bit misleading as to what is actually going on compared to the likes of Java.

    You are sending messages when you invoke properties, you aren’t directly accessing instance variables. The fact that you loose the suggestion that you are sending a message when you use dot syntax, comparatively compared to square brackets anyway, I think has the potential to mislead.

    That said, I am warming to dot syntax and probably will use it in some new projects to get a bit more of a feel for it in cocoa.

    Jim: I use that trick of underscoring iVars for that exact purpose as well. Damn handy.

    Reply
  9. Steven
    May 30, 2009

    I tend to agree with Danny. While I recognize that people like the DOT syntax due to the fact it reminds them of Java/C++, it obfuscates the fact a message is being called. This is one of the things that initially attracted me to Objective-C in the first place. A clear distinction of message passing VS direct attribute access. With DOT syntax, that is gone.

    Properties are little more than a formalization of what Obj-C programmers had been doing for years. They make life easier and much more consistent. DOT syntax tends to make the code look more cluttered (IMO) and sometimes harder to read as you go between two different syntaxes to call methods.

    Reply
  10. leeg
    June 1, 2009

    Yep, I agree with you, and argued this very point at the panel discussion in NSConference – state and behaviour are different even if they work the same. I summed up by saying that if you have a line of code and you can’t tell if the dot means a property on an object or a member on a struct, it’s time to refactor that file.

    BTW, I truly believe that anyone who’s offended by the notation for properties (an odd state of affairs in itself) should go back to Rhapsody and try using “New-style Objective-C” syntax :-/

    Reply
  11. John C. Randolph
    June 5, 2009

    I may be kind of old school, but I would still write:

    NSSize fooSize = [[NSImage imageNamed:@”foo”] size];

    That just looks more natural to me than applying the property syntax to this particular situation.

    -jcr

    Reply
  12. Jason Morley
    August 12, 2009

    Coming from relatively more ‘modern’ languages such as Java, the logical separation you have outlined here feels extremely natural.

    However, I have often found, when using dot notation to set properties instead of doing so in the constructor, I risk leaving my instance in a relatively un-initialized state. For example, in the ‘Person’ code above, your instance of Person doesn’t really make much sense until at least the name has been set. This feels inherently wrong and may potentially lead users of one’s API to write bad code?

    Reply
  13. Elise van Looij
    February 16, 2010

    I’m firmly in the just-use-the-dot-notation-as-Apple-intended camp: especially when you use Key-Value Coding it is vital to understand that self.someProperty accesses the setters and getters while someProperty doesn’t. However, this plays no role with NSSize and other constructs: they’re not Objective-C 2.0 properties. That said, [[NSImage imageNamed:@”foo”] size]; can’t possibly be more natural looking than foo.size: nothing in nature ever looks like nested square brackets while dots are not uncommon.

    @Jason Morley: the problem you outline is not solved by boycotting the dot notation but by writing designated initializers or class methods (+ (id)personWithName: (NSString *)name), making name a private property and implementing a changeName method.

    Reply
  14. Barthold Van Acker
    May 11, 2010

    I strongly agree that state and behavior should be, have to be separated. Why not, at least already for that reason, use a syntactically different notation to express a semantically different idea: state or behavior. Even if the underpinning is basically the same, uses the same messaging paradigm. State is also more permanent, less volatile then behavior. An object can go from one state to another.

    I wished that objects in Objective-C would also not have been so clearly linked to pointers (*), as in C, because an object is so much more than a pointer to a memory structure, conceptually. But, here I dwell off. Sorry.

    Reply
  15. Dalmazio
    July 9, 2010

    Good article.

    “To sum up:

    Use @property to declare the state exposed by your objects.
    Use dot notation to get and set objects’ state.
    Use method declarations to declare the behavior exposed by your objects.
    Use bracket notation to invoke objects’ behavior.”

    What about the case of state that you don’t really want exposed, since it’s private? Should we still use @property thereby making such state public, or forgo and handle it manually keeping it private?

    Reply
    1. eschaton
      July 11, 2010

      If it’s truly never exposed outside your class, you can just manipulate your instance variables directly.

      If it’s an implementation detail but used by several classes, put the @property declarations in a class extension in a separate file that includes your public header, e.g. put them in “MyClass_Private.h” which includes “MyClass.h”.

      You can do this for private methods that you need to expose outside your class as well.

      Why would you expose private properties or methods outside a class? Because it may have cooperating classes in the same module that need access, but you don’t want to expose those methods outside that module.

      For example, you may expose just a view controller in some API, but the controller interacts with a bunch of private subviews in its implementation.

      Reply
  16. Mark Wagner
    April 24, 2011

    Excellent article. I agree with your position on this topic.

    Reply
  17. Jeffery Martin
    October 25, 2012

    What is your opinion on mixing dots and brackets with passing a message. For example, in a UIViewController subclass:

    NSUInteger count = [self.childViewControllers count];

    OR

    NSUInteger count = [[self childViewControllers] count];

    “childViewControllers” is a property of UIViewController that returns an NSArray, but “count” is a method call of NSArray only, not a property.

    My guess is, to stick with your reasoning, the all-brackets syntax is preferred since the most deeply nested token in a method/message and not a property accessor.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *