Dot notation for messaging isn’t just an Objective-C code smell. It’s evil, I tell you!
Update: I recently changed my mind! See my post In Which I Embrace Dot Notation…
This post is part of the Code Smells in Objective-C series.
…Yes, that’s hyperbole. I do manage to coexist with dot notation in projects that have it. But I won’t write it myself. Here are 3 reasons I avoid dot notation in my code:
1. Dot Notation Confuses Objects with Structs
Tell me, what does the following code do?
foo.bar = 10;
In C, it’s clear what this code is doing: foo is either a struct or a union. It’s assigning 10 to foo’s bar
field.
Underneath the hood, the compiler writes code to calculate a memory offset from foo, then write the value 10 into the storage at the calculated address. Very fast & lightweight.
Objective-C is a strict superset of C, so all of this could apply to Objective-C code as well. Or not. …You can’t tell, can you?
2. Dot Notation Obscures Messaging
Because dot notation is syntactic sugar for messaging, you could write code like this:
NSMutableArray *a = NSMutableArray.array;
Of course, that’s beyond evil. But why? “Because array isn’t a property, it’s a method.” Oh, so the decision to use brackets or dots depends on whether the thing is a property? But it’s messaging either way! Why add a second messaging syntax at all?
The addition of dot notation to Objective-C smacks of someone at Apple saying, “Java is such a popular language. Our square brackets freak out Java programmers. Let’s replace brackets with dots; it’ll look just like Java which will increase adoption of Objective-C.”
But before getting into Objective-C, I wasn’t a Java developer. I was a C++ developer. And in C++ (which is almost a superset of C),
foo.bar = 10;
this is member access. foo could be a class, a struct, or a union, but this is member access regardless.
But how does an object access its own members? In C++, you could write
this->qux = 10;
But it’s more common to omit the this-arrow and simply write
qux = 10;
because qux is a member variable with class scope.
Now come over to Objective-C. In the evil new land of dot notation, you often see this:
self.qux = 10;
where qux is a property. A typical Objective-C newbie mistake is to say, “Well, that self-dot is redundant,” and change it to this:
qux = 10;
This compiles and runs without any problems. So what’s all the fuss?
The problem is that in the former case, we’re sending a message to the qux method. In the latter case, we’re making a direct assignment to the qux instance variable. These are two very different things! With scalars, it may not matter, but it makes a huge difference with objects, especially for writing correct memory management.
Now see what happens if you avoid dot notation:
[self setQux:10];
There is no ambiguity. This is clearly a message.
3. Dot Notation Encourages Law of Demeter Violations
How often do you see code like this? How often do you write it?
foo.bar.baz.qux = 10;
What’s wrong with that? Let me rewrite it without the dots, to make the messaging explicit:
[[[foo bar] baz] setQux:10];
People who complain that square bracket notation “looks weird” point to examples like this, to show how unreadable it is.
The problem is, it’s unreadable for a reason: it’s violating the Law of Demeter.
If you’re not familiar with the Law of Demeter, it’s about polluting the clear boundaries between objects by letting them become overly familiar with each other. Here’s a quick way to remember it: You can pick your friends. You can pick your nose. But you can’t pick your friend’s nose.
All those lumped-up brackets are a clue that you may be poking around where you don’t belong (in your friend’s nose). It’s a code smell that responsibilities may be misplaced. But now, dot notation makes it possible to keep using that same stinky violation, but look good doing it!
Your Turn!
Since almost all Objective-C code I see uses dot notation, I realize I’m swimming against the current here. Well, unless you count a couple of heavy-hitters, like Big Nerd Ranch and Cocoa Is My Girlfriend.
Question: Agree? Disagree? What do you think? Leave a comment below.
But also see my follow-up post In Which I Embrace Dot Notation…
Did you find this useful? Subscribe today to get regular posts on clean iOS code.
Disagree.
Objective-C is a smelly smell smell, even without dot notation. It is a weird engineering compromise between two different programming models. It gets your feet into a slightly more dynamic world, ( but only slightly, e.g. performSelector is a vomitous mass ), while still letting you speak quite comfortably to C and C++ APIs. It is a Frankenstein language though, and is nothing like elegant.
Sure, it is smell-ier with dot notation, but the smell isn’t that confusing, or hard to explain, and the code does look cleaner and simpler. Plus Apple is moving that way, so you are going to have to get used to it, or it will look weird for you to use one method for getters and setters in your code, and one method for writing them when using a system object.
Mr. Toy,
So if I read you correctly: I say, “Eww, this syntax mixes two models.” But you say, “Eww, the whole language mixes two models.” And you’re right. I certainly hit the discomfort of that boundary when I write test support tools (like OCHamcrest and OCMockito) that have to support both objects and scalars.
What do you mean, “Apple is moving that way”? Because there’s nothing that keeps me from making my code consistent, whether I’m invoking my code or Apple’s.
After reading up on this (Hillegass, et al) I went and changed all the code that I could that’s headed for app store approval and eradicated dot notation. But the code is more hellish to read now. So while I agree with the argument that the dot notation is schizophrenic, “The Misfit Toy”‘ has a point: Objective-C come across as being not quite sure what it is and the “dot notation is evil” argument is only one of many you encounter with a language that, while being an able workhorse, leaves a lot to be desired in terms of clarity, consistency and elegance.
I’m not changing my code back to the dot notation now. I will instead try to rethink how I’m coding if I end up wanting to use it a lot to “clean up” my code for readability.
Nick, what do you find “hellish to read” in your dot-free code? I agree there’s an elegant sparseness to the dots. But I do think it covers up LoD violations.
Hi Jon,
I’ve tossed around whether I like the dot notation or not in Objective-C, and have reserved judgement for quite some time. Having said that though I’ve noticed myself using it less and less.
Initially I did like it as it does have that Java feel, and I have some history with Java. However, after getting caught in some memory management issues in the past I realized that it was just as you said… I was directly assigning to instance variables. Not only was I doing that, I was mixing it with using dot notation and messaging, and I was just simply confused all around.
Fast forward to now and I find myself having dropped the use of dot notation and have gravitated to passing messages. Why? I just simply like the deliberateness of messages. It became obvious to me that dot notation had to have been added to appeal to developers from other languages. But as a developer, you should be used to using multiple languages and getting used to their syntax rules. Now, the syntax of passing messages to object’s feels quite natural. Dot notation for fields of an object does not get you around needing to pass messages to objects. So if you have a hard time with wrapping calls to objects in square brakets, then you’re going to have to be patient with yourself and your learning. In time, it will become muscle memory and will just happen naturally.
The Misfit Toy does make a point that dot notation looks cleaner and simpler, and I don’t entirely disagree with him. The problem I see for sure is that people will mix them, and for those that are unfamiliar with the rules of the language and just getting started on the platform, it will be confusing for them.
Cory,
Good point on really learning the guts of a language, and how it’s different from other languages. It’s natural to say, “Oh, this is just like ____” and miss important nuances, particularly around the interaction between objects, messages, and methods.
I agree that dot notation is evil due to ambiguity. It’s particularly evil because of cases this, which leads to the false intuition that this statement *ought* to work:
myView.frame.origin.x = 0;
But of course that statement doesn’t compile, because you’re calling a method that returns a struct, then changing from calling a getter to accessing a member of a struct, all with the same syntax.
With that said, dot notation does have one good side-effect — it enforces proper typing for getters and setters, thus avoiding creating not-a-setter-but-close:
– (BOOL) setMyProperty:(id) someValue
Because you then can’t write this statement:
BOOL aResult = anObject.myProperty = aNewValue;
Whereas you could do this:
BOOL aResult = [anObject setMyProperty:aNewValue];
I’ve also evolved my ObjC style over time, to always prefix my ivars with an underscore. Xcode automatically offers this as a completion choice for @synthesize statements:
@synthesize myProperty = _myProperty.
This guarantees you cannot make the mistake of assigning directly to an ivar when you meant to call a setter. Others I know have taken to using the Microsoft C++ notation style of “mMyMemberIvar” naming.
One of the things I dislike intensely about C++ is the widespread misuse of operator overloading, and ObjC dot-syntax has the same unsavory smell. In concept, operator overloading is a compelling idea, but in practice, it’s widely misused, making it unclear without lots of class cross-reference lookups what a statement like this does:
class aGuiWindow
…
class aNetworkConnection
aGuiWindow = aGuiWindow / aNetworkConnection;
Yes, I’ve actually seen code like this (a decade or more ago) in some old terminal server code, where “dividing a window by a network socket” had the effect of splitting the window pane for two different concurrent connections. Some developer was just trying to get far too clever.
Kevin,
I’m puzzled about your first example that you say “*ought* to work.” Doesn’t it? …Oh, I see! Wow, that’s subtle.
Great point on synthesizing ivars with an underscore prefix! I was intrigued when I saw you doing that. Then I noticed how Apple’s project templates used it, and how Xcode supports it in code completion. We’ve all made the “ivar or property?” mistake. When it popped up at work fairly recently, we talked about ways it could be detected or avoided. My conclusion to go with underscores.
Maybe it’s kind of like the folks who have expressed that dot notation is easier to read: The underscores have made my code a little uglier — but a lot more explicit. I like pretty, but I prefer clear.
Hi Jon,
thank you for the nice article. Dot syntax for messaging is really confusing and I agree in avoiding it completely. And I will be doing it from now on.
Just one remark about C++: this returns a pointer to the object, so qux should be accessed writing
this->qux = 10;
instead of
this.qux = 10;
Harry,
Ouch! Thanks for the catch. I couldn’t have written a more obvious statement that “It’s been a while, so my C++ has gotten rusty.” :-P
Jon,
I have to disagree with your assessment. I was sympathetic to these arguments when properties were first introduced into the language, however, I’ve never found this to be a point of confusion in practice. There are only a small handful of struct types you use regularly (save for your own) and I’ve never found the potential for ambiguity to be a problem.
I also disagree that this encourages people to violate the Law of Demeter. If your method takes an argument of type foo solely so it can access qux, the problem is with the person driving the keyboard, not the language.
-Bob
Bob,
It sounds like you’re much more comfortable with Chris Hanson’s explanation of When to use properties and dot notation. His assertion is that properties are an inherent part of object design.
But here’s the ambiguity regarding the Law of Demeter: In foo.bar.baz.qux, is there a LoD violation or not? Well, it all depends on whether it’s member access or method chaining, right? At my workplace at least, people see chained dots and, without determining what’s going on underneath, decide that “chaining dots is an Objective-C idiom” and apply it mercilessly.
Whether my coworkers use brackets or dots, I want them to become familiar with LoD. …Which is part of the reason I wrote this article. :)
Hi Jon,
I am a newcomer to iOS development and software engineering in general (I briefly learned C and C++ at school, and I self thought myself Java and Obj-C), and the dot notation when used properly makes it easier for me to manage memory issues and results in simpler code. I use the dot notation as accessors to properties created with @synthesize command and I prefix my ivars with an underscore. This makes it easy to understand how memory is managed just by looking at the @property decleration (ie weak, strong, retain, assign, copy).
For custom setters and getters using messaging syntax could be a better way since someone who is reading your code would cmd+click the method or property name (depending on whether you use dot notation or messaging) to see what that is and go to the @synthesize line if dot notation is used and to the method implementation if messaging syntax is used. It’s true that it might be misused and might be confusing but when you use it as intended and and love it for what it does best I believe it simplifies the work to be done.
Ahmet,
The @property attributes are one of their best features, for sure!
Great point about what happens when you command-click to go to the definition.
I’ve also encountered an interesting hybrid approach: to use dot notation for getters only, but to always invoke setters explicitly. That’s an improvement, but I think still leads people down the road of Law of Demeter violations.
Interestingly,
The bracket syntax was originally introduced to provide a clean segregation between C and Objective-C syntax. Where the “dot” syntax was acting as an operator to access a field in a local dereferences/local struct.
Which makes it strange that they would introduce dot syntax in Objective-C to support properties. It certainly wasn’t necessary.
A good rule of them, which you address, is to avoid using the dot syntax on non-accessors or messages.
Justin, it does seem strange to me, especially since “use dots for properties, not for other methods” is a human convention, not a compiler requirement.
Hello, Jon
Great post. I was talking with a co-worker the other day and he remarked that he didn’t like how I used the dot syntax all over the place. I figured it’s a benefit of the language why not use it. He figured it was more of a personal preference thing , and that’s as far as it went. Oh how wrong I was.
Anyway I know this isn’t the best place for this but I am using OCMockito(Love It!) and I was trying to figure out how to stub a method call and have it throw an exception rather than just return an object. I couldn’t find a solution and I don’t know where I could go to ask the question.
Do you think you could kindly answer the question or direct me to a better forum to ask it?
Thanks in advance for your consideration.
Dean,
Glad you liked the post!
And I’m glad to hear that OCMockito is serving you well, even in its early days. You have a good feature request; go ahead and add it to https://github.com/jonreid/OCMockito/issues
I’m sure there have been internal debates over this at Apple as well. A prominent iOS engineer specifically told me that he doesn’t use dot syntax because it looks like accessing C structs. On the other hand, Chris Hansen has publicly championed them.
I initially resisted dot syntax, then I adopted it for a few years and grew used to. Now I’m reconsidering abandoning it in future projects for the sake of purity and clarity.
Yes, Chris Hanson makes an interesting argument for using properties for state, distinct from behavior. I guess I’m a classicist when it comes to OOP: I see state in ivars, sometimes exposed through accessor methods.
Another benefit of avoiding dot syntax is that I can find just the setters (or just the getters) where they’re used in the code.
Thanks!
Just found these posts this morning as I was working on refactoring a core data project.
After reading the article and then looking at my code, I realized that crazy dot notation had me really abusing LoD (especially across core data many-to-many relationships).
Behaviors are so much more…predictable now =-)
Matthew, you actually got my main point! I’m so excited!
Hi Jon,
I don’t share your point of view because a dot syntax call is not messaging when used on a pure property. In this case the compiler directly inserts code to manipulate the ivar based on the type of property. Way faster too.
So:
1. Using the dot syntax on something that is not a pure property (i.e. messaging is actually involved) is a code smell (Apple should add a warning to clang!). Using the dot syntax on a pure property is not.
2. Breaking the law of demeter has nothing to do with dot syntax. It is even harder to break with dot syntax b/c the compiler has to know the property or you get an error. The bracket syntax will only get you a warning…
Roddi,
Your comments are predicated on the notion that “a dot syntax call is not messaging when used on a pure property.” I see no evidence for this anywhere; can you share any?
As far as I know:
Regarding your two points:
1. I consider dots a smell, period. I can see softening my stance for self-dot, to reference one’s own properties. But using dots for general method calls is becoming popular. Google’s approach is to use dots for all idempotent methods. This at least is interesting.
2. You lost me. Can you offer a code snippet to illustrate what you mean?
2. Dot notation obscures messaging
Except I know it’s messaging, I’m not fooling myself. I know the difference between self.foo and _foo; foo by itself doesn’t work because I’m using properties and foo isn’t an ivar. I’ll take it one step further and say that array.count is okay by me, even though count is not really a property, semantically it acts like one. I would never use NSArray.array though, that is not semantically clear.
3. Dot notation encourages Law of Demeter violations
I have been bitten by ‘poking around where I don’t belong’ before, but that’s because I was using autocomplete to write code and guess at the API, where I hadn’t looked at the docs at all. (e.g. setting an image property for a UIButton directly, rather that using setImage:forState:) I could have made the same error with square brackets, because my thinking was wrong.
Point 3 seems like a restatement of point 2, if you know you are calling a method in either case it’s just a syntactic nicety.
But I propose a better counter-argument altogether.
What about properties. When you are declaring a property, you are actually declaring 3 things, an iVar, a setter and a getter. You are declaring methods when you appear to be only defining an iVar. Even though I knew this, failing to really appreciate the full implications, especially with respect to subclasses, has caused me many more headaches in learning objective C than dot notation.
I don’t think anyone is saying ‘don’t use properties’, but if the issue is hiding method calls is bad, I think hiding method definitions is potentially a much worse trap for newcomers.
I would like to add this reading to the discussion.
http://programmers.stackexchange.com/questions/211292/how-to-solve-train-wreck-properties-problem-that-violates-law-of-demeter
http://haacked.com/archive/2009/07/13/law-of-demeter-dot-counting.aspx
Then if you start mixing dot notation with C++ (Objective-C++). Freeky Geeky….
I wonder what you think of Swift, then.
What about Swift? Dots aren’t the problem. It’s that dots have a prior meaning in C, and that meaning is inherited by Objective-C.
But also, check out my other article where I embrace dot notation.
You miss a few things. Wherever default @property definitions are used – the iVars are named with an underscore prefix, so aux = 10; won’t even compile. it’s either self.qux = 10; or _qux = 10; and the object->ivar ivar access syntax is not just C++, but also supported by OBj-C. Using dot notation is overly OK, as long as you know what it does, and the chain of dots, becoming chains of messages are NOT evil, but the ONLY way to get from one object to another. If your chains become too long, that’s an OOP design issue, not the result of ‘evil syntax’
Motti, thanks for sharing your thoughts. When I wrote this post, dot syntax in ObjC was new. At the time, ivars weren’t automatically prefixed with underscores. This change was definitely an improvement. …I wrote a follow-up post in which I talk about how I gave up the fight and started using dot notation in ObjC. I like Swift, but ahhh, there are things about working in ObjC that I miss…