{"id":160,"date":"2009-05-27T19:14:27","date_gmt":"2009-05-28T03:14:27","guid":{"rendered":"http:\/\/eschatologist.net\/blog\/?p=160"},"modified":"2009-05-27T19:14:55","modified_gmt":"2009-05-28T03:14:55","slug":"when-to-use-properties-dot-notation","status":"publish","type":"post","link":"https:\/\/eschatologist.net\/blog\/?p=160","title":{"rendered":"When to use properties &#038; dot notation"},"content":{"rendered":"<p>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&#8217;t addressed.<\/p>\n<p>The biggest reason I see to use a different notation for both property declaration and property access than for method declaration and sending messages \u00e2\u20ac\u201d even if property access ultimately results in a message send, as it does in Objective-C 2.0 \u00e2\u20ac\u201d is **separation of state and behavior**.<\/p>\n<p>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.<\/p>\n<p>However, in today&#8217;s modern world we understand that objects aren&#8217;t *just* actors.  Objects both &#8220;do things&#8221; *and* &#8220;represent things;&#8221; they&#8217;re nouns.  And they have both *internal* state that they use in managing their behavior and *external* state they expose to the world.<\/p>\n<p>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&#8217;re handled by the same underlying mechanism.<\/p>\n<p>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:<\/p>\n<p>    @interface Person : NSObject<br \/>\n    @property (copy) NSString *name;<br \/>\n    @property (copy) NSImage *picture;<br \/>\n    @end<\/p>\n<p>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:<\/p>\n<p>    Person *person = [[Person alloc] init];<br \/>\n    person.name = @&#8221;Chris&#8221;;<br \/>\n    person.picture = pictureOfChris;<\/p>\n<p>The intent of this code is clear: I&#8217;m not asking `person` to do anything, I&#8217;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&#8217;m looking at, I&#8217;m just interested in changing some state.<\/p>\n<p>Now let&#8217;s see what the NSViewController might look like:<\/p>\n<p>    @interface PersonViewController : NSViewController<br \/>\n    @property (retain) Person *person;<br \/>\n    &#8211; (BOOL)updatePicture;<br \/>\n    @end<\/p>\n<p>And let&#8217;s see how I&#8217;d use one, assuming it&#8217;s been instantiated and wired up in my view hierarchy already:<\/p>\n<p>    selectedPersonViewController.person = person;<\/p>\n<p>    if ([selectedPersonViewController updatePicture]) {<br \/>\n        \/\/ note elsewhere that the person&#8217;s picture is updated<br \/>\n    }<\/p>\n<p>Even though the `-updatePicture` method has no arguments and returns a `BOOL` I (1) don&#8217;t make it a property and (2) don&#8217;t use dot notation to invoke it.  Why not, since it fits the *form* of a property?  Because it doesn&#8217;t fit the *intent* of a property.  I&#8217;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.<\/p>\n<p>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&#8217;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.<\/p>\n<p>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`.<\/p>\n<p>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.` \u00e2\u20ac\u201d it will only offer me the properties it knows are on Person.  <\/p>\n<p>Now, you *can* invoke arbitrary getters or setters (so long as they have a corresponding getter) using dot notation.  The compiler doesn&#8217;t require an `@property` declaration for the use of dot notation, just a declaration.  I could have declared the `Person.name` property like this:<\/p>\n<p>    @interface Person : NSObject<br \/>\n    &#8211; (NSString *)name;<br \/>\n    &#8211; (void)setName:(NSString *)value;<br \/>\n    @end<\/p>\n<p>The compiler will compile `person.name = @&#8221;Chris&#8221;;` just fine with this declaration, to an invocation of `-[Person setName:]` \u00e2\u20ac\u201d but Xcode won&#8217;t offer you code completion for it if you don&#8217;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.<\/p>\n<p>Of course, one complication is that many frameworks on Mac OS X predate `@property` declarations and thus don&#8217;t expose their state this way.  That means Xcode won&#8217;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.<\/p>\n<p>To sum up:<\/p>\n<p>* Use `@property` to declare the state exposed by your objects.<br \/>\n* Use dot notation to get and set objects&#8217; state.<br \/>\n* Use method declarations to declare the behavior exposed by your objects.<br \/>\n* Use bracket notation to invoke objects&#8217; behavior.<\/p>\n<p>This results in intention-revealing code that clearly separates state and behavior both in declaration and use.<\/p>\n<p> [1]: http:\/\/www.cocoafusion.net\/ &#8220;cocoaFusion: podcast&#8221;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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&#8217;t addressed. The biggest reason I see to use a different notation for both&hellip;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[3],"tags":[9,4,18,123,59,22,17],"class_list":["post-160","post","type-post","status-publish","format-standard","hentry","category-technology","tag-cocoa","tag-mac","tag-objective-c","tag-oop","tag-podcasts","tag-programming","tag-xcode"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p74loH-2A","_links":{"self":[{"href":"https:\/\/eschatologist.net\/blog\/index.php?rest_route=\/wp\/v2\/posts\/160","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/eschatologist.net\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/eschatologist.net\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/eschatologist.net\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/eschatologist.net\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=160"}],"version-history":[{"count":5,"href":"https:\/\/eschatologist.net\/blog\/index.php?rest_route=\/wp\/v2\/posts\/160\/revisions"}],"predecessor-version":[{"id":177,"href":"https:\/\/eschatologist.net\/blog\/index.php?rest_route=\/wp\/v2\/posts\/160\/revisions\/177"}],"wp:attachment":[{"href":"https:\/\/eschatologist.net\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=160"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/eschatologist.net\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=160"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/eschatologist.net\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=160"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}