Sunday, August 9, 2009

Dot Notation Redux: Google's Style Guide

Before I get into this post, let me make a few things absolutely clear. I do not want my intentions misunderstood.
  • When coding for yourself, do what feels right to you. If you don't like dot notation, don't use it, and don't feel like you should apologize for not using it.
  • When coding for a client or employer who has a coding style guide or other published coding conventions, use those, even if they disagree with your personal opinion of the "right" way to code. In a group programming environment, consistency is extremely valuable.
My goal here is not to tell you that you must or should use dot notation, it is only to refute the idea that dot notation shouldn't have been added to the language and that it inherently makes code harder to read.

My illustrious writing partner, Dave Mark tweeted today about the Google Objective-C Style Guide's argument against using dot notation in Objective-C, which reads as follows:
  1. Dot notation is purely syntactic sugar for standard method calls,whose readability gains are debatable. It just gives you another way to make method calls.

  2. It obscures the type that you are dereferencing. When one sees:
    [foo setBar:1]
    it is immediately clear that you are working with an Objective-C object. When one sees = 1
    it is not clear if foo is an object, or a struct/union/C++ class.
  3. It allows you to do method calls that look like getters.
    NSString *upperCase = @"foo".uppercaseString;
    which is not only confusing, but difficult to spot in a code review.
  4. It hides method calls.
    bar.value += 10;
    is actually two separate method calls (one to set and one to get) and if your properties are not simple you may find a lot of work being done in a hidden manner.
As you read through these, they sound rather logical, and possibly even compelling. But in reality, they are not logical at all. In fact, the whole argument is basically one series of logical fallacies. Let's look at the specific arguments in order and then put the pieces together at the end.

The First Argument: the Non Argument

Dot notation is purely syntactic sugar for standard method calls,whose readability gains are debatable. It just gives you another way to make method calls.
This first "argument" contains no actual argument against the use of dot notation. The first part of the first sentence is taken almost verbatim from The Objective-C 2.0 Programming Language on Apple's site and is just a restatement (out of context) of how dot notation is implemented.

The second half of the first sentence is an attempt to discount one of the benefits of dot notation by simply dismissing it offhand without evidence or support.

The second sentence is simply an attempt to bolster the arguments that follow by trivializing dot notation as "just" something we can already do. It's sort of like saying that jet engines do not add value over propellers because they're "just" another way to create thrust. Every construct in any programming language that's higher-level than assembly is "just" another way to do something we can already do. This sentence has no semantic or logical value, it's simply here to set a negative tone toward the use of dot notation without actually offering any facts or reasons not to use it. This first "argument" is rhetoric, nothing more.

The Second Argument: the Invalid Assumption

It obscures the type that you are dereferencing.
This argument brings to mind the arguments for Hungarian Notation. The argument for Hungarian Notation is that when you look at a variable, you know right away what it is. By prefixing every variable with a jumble of individual letters, each with its own meaning, you know (in theory) all that there is to know about that variable just by glancing at it.

In reality, you don't see much Hungarian Notation these days. Variables with semantic meaning - those that use words that are recognizable by and have meaning to the brain - work much better. We may not know the variable's specific type, but we know what purpose it serves, which is really more important.

Dot notation doesn't "obscure" the type you are dereferencing unless there's some reason why you would know the type from looking just at that line of code. This argument makes the assumption that we already know and that we should know what the type of foo is. Sure, with bracket notation, we know we're dealing with an object, but we don't know what kind of object it is from looking at this one line of code in a vacuum.

But, when do you ever look at a line of code in a vacuum? You don't. Code has no meaning taken out of context. If it was vital that we know everything about a variable from looking at it out of context, then we'd all be using Hungarian Notation. Yet we're not.

Somewhere, probably not more than a few lines above = 1
is either a declaration of foo or the start of the method. If you're confused about the type, generally scrolling up a few lines can resolve that confusion. If that doesn't work (because it's an instance or global variable, for example), command-double-clicking on it will take you to its declaration and then you'll know its type.

You can't obscure something that you don't have a reason to know. The amount of information that bracket notation gives us over dot notation is trivial and not enough to make an informed decision about what the code is doing anyway, so you have to consider its context. If it's not your code, you have to look at the preceding code to understand it anyway.

The Third Argument: the Red Herring

It allows you to do method calls that look like getters.
Allows? This argument is that it's bad because it "allows" you to do something? And what it allows you to do is create method calls that look like getters? What are getters? They are a kind of method, right? Am I missing something here?

Any programming language, to be useful, has to allow some kinds of bad code. I doubt it's possible to create a programming language that doesn't "allow" an inexperienced programmer to do all sorts of completely horrible things. I could come up with dozens of examples of ways that Objective-C 1.0 "allows" you to do bad things. This isn't an argument, it's a one-line example of bad code that's being passed off as an argument. It's disingenuous because there's nothing to prevent you from creating methods that look like getters but aren't without dot notation. There's no language-level constraint on that in Objective-C, and no compile-time checks for it regardless of whether dot notation is used. Dot notation changes this in no way whatsoever.

I actually find it hard to believe that an experienced Objective-C programmer would even attempt this argument because, frankly, it sounds like an argument you'd get from a C++ programmer. Objective-C is a permissive language. It's in Objective-C's DNA to let you do things. It's weakly typed and handles at runtime many things that are handled at compile-time in C++ (and all other OO languages based on the Simula object model). These are intentional design decisions. This language is designed to give you a lot of flexibility and puts trust in the developer that you'll use its features appropriately. Objective-C's dot notation doesn't run contrary to that in the slightest. In fact, it's a logical extension of that underlying philosophy. They're faulting dot notation for something that's inherent in Objective-C

The Fourth Argument: Missing the Point

It hides method calls.
Why yes, yes it does. The sample line of code supporting this "argument"
        bar.value += 10;
will result in exactly the expected behavior if you're using dot notation to represent object state. If the value and setValue: methods are something other than an accessor/mutator pair, then this it is true that this line of code could cause unexpected results, but the fault for that lies not with dot notation, but rather with a programmer who made extremely poor method naming choices, essentially lying to the world about their methods by not respecting the naming convention for accessors and mutators. Under this scenario, you'd have exactly the same problem with this line of code that doesn't use dot notation:
        [bar setValue:[bar value] + 10];
In other words, this argument is only a problem when somebody does bad things with their code, and it's just as much of a problem when not using dot notation.
Whoops! It was pointed out in the comments that I sorta missed the point on this one, and that the "problem" is that there are two method calls when someone who didn't understand dot notation might reasonably think there was only one. My response to that is: so what? How is it a problem if the result is correct? The code used to illustrate the problem will achieve the results that you should reasonably expect. After the line of code, value will be correct. The fact that there are two messages sent and not one will not matter in the vast, vast majority of situations. What counts is that the result is correct, and in the example, it would be assuming the accessor and mutator are correctly implemented. If you're having performance problems and determine through profiling that it's caused by the extra message, then you optimize by implementing a method that increments the value in just one call. It's still a non-issue.

Illusory Arguments

The law has an interesting concept called an illusory promise (or condition), which is a promise that really isn't a promise at all. It's something that looks like a promise, and is couched in the language of a promise, but which simply isn't a promise.

These arguments against dot notation in Google's Objective-C Style Guide are illusory arguments. The first one, isn't an argument at all. The second rests on assumptions that are provably untrue (that you know what type a variable is from looking at just its line of code). The remaining two are predicated on a programmer doing something wrong and can both be demonstrated just as easily without using dot notation.

Google makes the case that dot notation is bad because it can result in confusing code when a developer pays no attention to established naming conventions or makes really poor design choices. But these problems have nothing to do with dot notation. Poorly written code is poorly written code. The simple fact of the matter is, if you're trying to read code like that, nothing is going to help. With, or without dot notation, the code will be hard to read because it's bad. The correct solution in that situation is to fire or train the developer who wrote the offending code.

How I Use Dot Notation

But, there are ways in which dot notation can be used to make code more readable. The way I use it (picked up from Apple's sample code) is to use properties and dot notation to represent object state, and bracket notation when calling methods that represent behavior or trigger actions. In fact, it could be argued that using bracket notation for both state and behavior has at least as much potential for causing confusion as using dot notation does. Take this line of code, for example
        [foo setIsOn:YES]
Am I setting state or triggering behavior? It could be either. It could be both. To know for sure, I have to check the documentation for the method being called. If, on the other hand, I've used dot notation and properties to separate out state from behavior, it's instantly understood that
        foo.isOn = YES;
is setting state, but
        [foo turnOn];
is triggering behavior (which may, of course, affect state). Yes, this requires consistent design choices, but all good coding does. If you throw that out as a requirement, you can argue that anything is bad.

Arguing against letting people use dot notation because some people will make poor decisions is ignorant. It's basically saying "I don't like it, so you shouldn't use it", and when you state it like that, it sounds kinda silly, doesn't it?


Jack Nutting said...

I think the point of the third argument, about "hiding" method calls, isn't that a person could be "hiding" methods that do something extravagant (beyond standard getter/setter activity), but just that the syntax makes it not fully obvious, at a glance, that method calls of any kind are happening; One could, for instance, see "a += 10" and presume that "a" is a C numeric type, getting 10 added to it.

Of course, even that argument doesn't hold up to your counterpoint about context, since "a" is likely defined nearby.

joeyoppo said...

I love how totally ridiculous this example is:

NSString *upperCase = @"foo".uppercaseString;

I'm interpreting their argument as, "you shouldn't use it, cause you could screw things up if you don't know what you're doing." oh, ok.

Jens Ayton said...

Jack Nutting: or it could be that a is a C pointer type and the += operator therefore has an implicit multiplication in it. Hey look, C is hiding behaviour! Time to find a new language. ;-)

Jeff LaMarche said...


I see your point. But, even if one method call is hidden, how is that harmful? The code in their example achieved exactly what the programmer should reasonably expect it to achieve. Does it matter that it happened as the result of two message dispatches rather than one? Maybe .0001% of the time it will have an impact on performance, but in those cases, you then (as an optimization, after profiling) add a method to increment that value in a single call.

Steven said...

I also find that people in general and programmers specifically hate change. How many times have you heard someone complain about a new IDE or (in this case) syntactical change that they come up with trumped up reasons to disregard?

I (and you, fellow programmer) must learn to embrace change, change is good! Besides, if we abhor change just as much as the next guy, then the young guy who has learned "the new way" (hey, it's not change to him or her!) will likely come and take our job because we have let so much forward progress pass us by that we are no longer relevant.

Izidor Jerebic said...

"State" and "behaviour" are concepts from procedural programming - you have inert "data" (structs,records,etc.) and active "functions", operating on data.

Object-oriented programming is *exactly* about removing this split and hiding everything inside object, which handles every request appropriately, without outside world knowing what needs to be done.

What if "obj.x = 1" after some time also needs to change "z" because of constraints which developed over time?

So dot notation is introducing inferior concepts into OO - concepts which belong to days of IBM waterfall development plans. Days of predetermined non-changing state/behaviour separation are way past us - today is the day of dynamic languages.

And what about impossibility of "view.frame.origin.x = 1;" ?

Dot notation was probably introduced on the iPhone because "obj.x = 1" can be executed much faster than [obj setX:1]" (directly setting instance variable), and iPhone needs every cpu cycle. This change then trickled down to mac os x.

P.S. Sorry if this is duplicate...

Jeff LaMarche said...


It is true that OO programming hasn't traditionally recognized or utilized the split between state and behavior. That doesn't mean it can't be a valuable addition to the language. Paradigms evolve as we use them and gain experience with them.

Concepts are not "inferior" because they are unfamiliar or untraditional or because they don't suit your way of working. It's downright silly to call a useful abstraction "inferior" because you don't like it or don't want to use it. The object-oriented paradigm isn't "better" than procedural or functional programming simply because it's newer, or because it refuses to recognize the distinction between state and behavior. It's better because it offers us a mental construct that's easier to grasp and because it encourages better design. It's more concrete than procedural or functional programming and makes it easier (not more possible, just easier) to design complex applications that can be broken down into manageable units that the brain can process.

Used improperly, any concept can cause problems and create less readable, less maintainable code. As long as we're judging by the yardstick of "what a bad programmer might do with it", we'll never see any progress or change in programming languages. If programmers of the past had used that yardstick, we'd all still be programming in the procedural languages you seem to loathe (or possibly functional languages, or maybe we'd all still be working in assembly).

The truth is, there is a difference between state and behavior. There are different things and they exist. They don't cease to exist simply because we're using OO, there was just no language-level mechanism to distinguish or separate them before. Instead, we had to come up with naming conventions and write method documentation to communicate to others the relevant parts of the implementation details that might affect them.

Hiding implementation details can have value, I'm not denying that. But it doesn't always have value in every situation. Sometimes it is beneficial to be able to broadcast to anyone who will be reading your code that (including your future self), "hey, this is just state", or "this might cause something to happen".

If you are incapable of seeing the value in that, then simply don't use dot notation. I'm not arguing that you should be forced to use it (it's the rare programmer who uses every language construct on a regular basis), I'm just arguing that those of us who do see the value should be allowed to use it without being constantly told we're wrong. I just want naysayers to accept that maybe, just maybe, the people who designed this feature, and those of us who use it and like it, have put some actual thought into it, and actually have valid reasons for our opinion, even if that opinion differs from yours.

Dot notation was probably introduced on the iPhone because "obj.x = 1" can be executed much faster than [obj setX:1]" (directly setting instance variable), and iPhone needs every cpu cycle. This change then trickled down to mac os x.

No, I'm pretty sure this is not currently the case. It is documented clearly that the two examples you have given are exactly identical. Setting a property does NOT directly set the instance variable. The term that is repeatedly used is "syntactic sugar". They are equivalent.

It may be the case that in the future Apple will be able to provide performance benefits for properties over traditional accessors by optimizing the runtime, but at present, I'm almost positive that the two examples you give will create the same exact result in the same exact number of CPU cycles.

K. A. Barber said...

I'll say that the 2 listed items at the beginning of the post is they way I tend to handle things. I will follow the clients style guide for work on there projects and use my style on my projects. In fact it is so important to me that code I am selling or writing for a client is styled commonly I will if they don't have a style guide use one of the more prevalent style guides for the language I am working in for the sake of readability. Great post BTW.

Jeff LaMarche said...

KA Barber

Yeah, I added that after I wrote the post because I just knew somebody was going to assume that I was saying you shouldn't follow style guidelines, which absolutely was not the point I wanted to get across.

Consistency has value, no doubt about it.


dmac said...

I'm certainly glad this was marked as a rant ;-) I'd hate to see what you think of our C++ guidelines.

First off, we are debating internally right now whether or not to loosen our restrictions on using dot notation. Honestly, I'm amazed that this little topic has incurred as much discussion as it has. Much of the reasoning behind some of these decisions weren't put explicitly in the coding guidelines because we want to keep the guidelines succinct so they can be scanned quickly. All of the discussion that caused the decisions can be found in the archives of our internal mailing lists (which I realize that you can't access). I must admit that when I wrote this I hadn't considered the fact that it was going to be used by someone as a definitive statement on the correctness of using dot-notation in Objective-C.

I'm just arguing that those of us who do see the value should be allowed to use it without being constantly told we're wrong. I just want naysayers to accept that maybe, just maybe, the people who designed this feature, and those of us who use it and like it, have put some actual thought into it, and actually have valid reasons for our opinion, even if that opinion differs from yours.

We never told you that you were wrong. We talked about it extensively internally, voted and this is what came out. Some people agreed, some people disagreed, some people sat on the fence. It is a living document and probably will change in the future. We voiced our opinion about our code and our feelings at the time. If you disagree with our style guide, please don't use it, unless of course you are submitting that code to us in some fashion. There are several bits of our Objective C style guide that I disagree with personally and feel much more strongly about than dot-notation. When we wrote this we felt that the advantages of dot-notation (which we did recognize) were outweighed by what we perceived as negatives. I agree with close examination that some of our arguments aren't as strong as they could have been. Thank you for pointing this out. Maybe we will revise it in the future. In actual practice the restriction on dot notation hasn't been near as irritating as our 80 column requirement (IMHO).

One of the major reasons that isn't in that document is that we have to support 10.4 with some of our code, and it makes it far easier to share code with a 10.4 project when we don't have to worry about dot notation. Now that we are supporting 10.4 less and less (and iPhone more and more) using dot notation begins to make more sense.

I'm actually currently in the "use dot notation" camp, mainly because of the way that Xcode is starting to support it when doing autocompletions.

If you would like me to respond to your arguments point by point, I can try and do that, but honestly I've got a lot of code to write. Can we agree that different folks like different things and happily coexist? ;-)

Damai Ria said...

thanks for this

Edwin said...

scrub m65 kamagra attorney lawyer body scrub field jacket lovegra marijuana attorney injury lawyer

h4ns said...

What youre saying is completely true. I know that everybody must say the same thing, but I just think that you put it in a way that everyone can understand. I also love the images you put in here. They fit so well with what youre trying to say. Im sure youll reach so many people with what youve got to say.

Arsenal vs Huddersfield Town live streaming
Arsenal vs Huddersfield Town live streaming
Wolverhampton Wanderers vs Stoke City Live Streaming
Wolverhampton Wanderers vs Stoke City Live Streaming
Notts County vs Manchester City Live Streaming
Notts County vs Manchester City Live Streaming
Bologna vs AS Roma Live Streaming
Bologna vs AS Roma Live Streaming
Juventus vs Udinese Live Streaming
Juventus vs Udinese Live Streaming
Napoli vs Sampdoria Live Streaming
Napoli vs Sampdoria Live Streaming
Fulham vs Tottenham Hotspur Live Streaming
Fulham vs Tottenham Hotspur Live Streaming
AS Monaco vs Marseille Live Streaming
AS Monaco vs Marseille Live Streaming
Alajuelense vs Perez Zeledon Live Streaming
Alajuelense vs Perez Zeledon Live Streaming
Technology News | News Today | Live Streaming TV Channels