Please join me at my new location bryankyle.com

Tuesday, September 21, 2010

Some Thoughts on Cocoa and Objective-C

I originally started writing this about a year and a half ago. It's been sitting on my desktop waiting to be published but for one reason or another I never got around to it. My thoughts now seem trite, but it's interesting to look back. One of these days I should write a post that covers the more interesting aspects of Objective-C's design; more than just what's covered here.


I've been dipping my toes in Cocoa again lately, and I'm really starting to enjoy it. I first played with Cocoa when I got my first Mac in 2004. I really thought there was something promising there but I couldn't wrap my head around how all the pieces fit together. After being abused by other OOP languages and their GUI frameworks Cocoa seemed really backwards. Delegation instead of subclassing. Freeze dried objects and connections that are brought back to life at runtime, etc. And the language. Why this bizarre language with it's odd syntax?

Each of the choices in isolation appear to be fairly arbitrary, or different for difference's sake. But as you learn more about the development model you can definitely see a method to their madness. The choice of language is a rather interesting one because it forms the foundation of how applications are written for the Mac. So why Objective-C? In order to understand why Cocoa, OS X's native framework is written in it it's important to know where OS X came from.

In the late 80s NeXT Computer was building high end computer workstations for education and businesses. The crown jewel of NeXT was its operating system: NextSTEP. NeXTStep was a performant, object-oriented, preemptively multitasking operating system with a graphical user interface. In order to quickly build the operating system and its application software a very performant, dynamic, reflective language was needed. At the time the best choice was probably a little-known superset of C called Objective-C.

In the early to mid 90s Apple was looking for a successor to its aging operating system. After several failed attempts to build one in-house Apple was approached by NeXT. NeXT convinced Apple that it had the technology that Apple needed. In the end NeXT Computer was bought by Apple, and NeXT Step was transformed into Mac OS X. If you've ever wondered why classes are prefixed with NS in Cocoa now you know why.

I've found Objective-C to be a really interesting and fairly elegant language. One of the more interesting things I found was that Objective-C uses a completely different calling metaphor from traditional OOP languages that I've learned. What most languages refer to as calling methods, Objective-C calls message sending. The distinction is more than skin deep, it's a fundamentally different paradigm. If you're experienced with the mainstream OOP languages you've spent a great deal of time thinking aboout class taxonomy and how classes relate to each other. You're trained to think that classes are types and methods are associated with the types. This makes a lot of sense if you look at the problem from a compiler's perspective. If you know the class and method at compile time then you can statically jump to the appropriate address. It's faster than a dynamic lookup but you pay for the boost in performance and the currency is developer time.

A message sending paradigm on the other hand is quite different. When you want an object to perform some operation you send a message to that object with some arguments. The object that receives the message will dispatch the appropriate method for the message. Typically there is a one-to-one mapping between messages and methods but in some cases you might want to respond to messages that don't correspond to a method.

You might boil the difference between method calls and message sending down to a difference in who is responsible for finding and invoking the appropriate code. In the method calling convention the caller is responsible (via the compiled code) for determining the address to jump to. Message sending on the other hand leaves the receiver of the messag to determine what method to invoke. Another interesting side effect of message sending is that sending a message to a non-existant object is perfectly legal whereas calling a method on a non-existant object is not. In Objective-C sending a message to nil returns nil. You can chain these together without any problems.

    return [[[a firstChild] nextSibling] nextSibling];

As I mentioned earlier, when an object receives a message that it doesn't understand it is allowed to perform any operation that it wants to.