Objective C, readability, and language design
For the last several months, I’ve been teaching myself Objective C and Cocoa. On the plus side, the framework is well designed. It’s the Objective C syntax that still has me tearing my hair out.
Square brackets
The biggest difference between Objective C and C++/Java/C#/ActionScript is the syntax for sending messages to objects. Instead of using dots or arrows, you use square brackets:
ActionScript / JavaScript
foo=object.method()
Objective C
foo=[object method]
Looking at it like this, the syntax doesn’t look half bad. The problem comes when you start chaining these methods together.
Let’s say you want to get the screen bounds of the window that holds a view object:
NSRect screenRect = [[[myView window] screen] frame]
Reading this syntax isn’t bad, but writing it is a pain. Every time you want to add a new method call at the end, you have to go all the way to the beginning of the line to add an open square bracket.
Long names
To compound matters, most of the method names are much longer than above:
sortedDocuments = [[[documents allKeys] filteredArrayUsingPredicate:predicate] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
By shortening some names (e.g., filteredArrayUsingPredicate -> filter) and using dots and parentheses instead of square brackets, you might end up with something like this:
sortedDocuments = documents.keys.filter(predicate).sort(caseInsensitive);
Strings and collections
Some languages, such as C# and ActionScript define string classes as an integral part of the language. This allows those languages to add common operations like string concatenation directly into the language. Others, like C++, do not define strings directly in the language, but allow class designers to override operators to, in effect, extend the syntax of the language.
In Objective C, string objects are only barely integrated into the language. The only concession to usability is that there is a syntax to define string literals (@”xxx”).
In order to concatenate strings, you end up doing something like this:
ActionScript / JavaScript
"The file " + filename + " could not be found."
Objective C
[[@"The file " stringByAppendingString:filename] stringByAppendingString: @" could not be found."]
The same is true of collection classes, such as arrays and hash tables.
Objective C
[wordMap setObject:[words objectAtIndex:i] forKey:key]
ActionScript / JavaScript
wordMap[key] = words[i]
Frankenstein – Not 100% object-oriented
Like all of the C-based languages, there are weird cracks in the language where the object-oriented and non-OO worlds meet. In Objective C, you can define structs and objects, which work totally differently. You can define both functions (denoted by parentheses) and methods (denoted by square brackets). To confuse matters further, Objective C 2.0 defines getters and setters, which are accessed using dot notation, even though the implementation is done through methods, which normally don’t use dots.
One of the classic ways in which the OO and non-OO worlds meet is in dealing with primitive numeric types. Should an int be represented in the most efficient way possible (e.g., 4 bytes of raw data), or should it be a full-fledged object, so it can be used in places that expect objects (e.g., collection classes).
Many languages provide both primitive and object versions of things like integers, and Objective C is no exception. Modern languages like Java 5 and C# simplify this through automatic boxing/unboxing, which means that these languages automatically convert between primitive types (e.g., int) and the object types (e.g., Integer).
Here is a line of actual code that I wrote the other day:
Objective C
[dict setObject:[NSNumber numberWithInt:prio++] forKey:[NSNumber numberWithInt:matcher.type]]
Now you might look at that line of code and say that it is too complicated to put on a single line. Well, if the language (a) had built-in hashes, and (b) did auto-boxing/unboxing, the above line would look like this:
Hypothetical Objective C with hashes and boxing/unboxing
dict[matcher.type] = prio++
Syntax is important
From a mathematical point of view, the specific syntactic choices are not all that important in defining what a language can do. But from a human point of view, the purpose of a language is to make it easy to express and communicate ideas. Computer programs are hard enough to read and write as it is. To the extent that a syntax makes it hard to express ideas clearly, it makes the task of programming harder than it needs to be.
For those of you who like Objective C, I know… I know… every language has its warts. I spent a good chunk of my life working in C++, and I know that a badly written C++ program is as hard to read as the worst Perl program.
To be fair to the other side, maybe the issue is that I know the warts of C++, whereas I am only now learning new warts in Objective C. So maybe I’m just overreacting when I tear my hair out and throw things across the room.
Yeah, right.
yeah that does sound annoying. Which begs the question, why are you learning objective C?
I have to say, I think a lot of things about ObjC suck a bit, but I’d say the one thing I really like about it is the ease of dynamic typing and reflection. That’s about it though really, the attempt to mix OO features like get/set is ugly and very counter-intuitive. It feels like a lot of the libraries are quite nifty for building out UI objects and handling messaging and callbacks but the core language itself isn’t nearly as helpful when trying to do anything else, which might be an accidental design decision (i.e. “let’s focus on this to the exclusion of other things”).
I can completely understand where obj-c is coming from – unlike C++ it is a strict, backwardly compatible, extension of C, with the object extensions influenced by Smalltalk (and as I’m sure you’ll have discovered, the OO implementation is far closer to dynamic languages than C++/Java).
But I’d agree with most of your criticisms – the long method names smack of an ‘IDE-only’ language (Interface Builder has been around almost as long as ObjC) – I can accept the point of view that the method names say exactly what they do, which is a big argument that experienced obj-c developers will use. I’m also a big fan of named parameters in calls, but . . . well your example says it all.
It’s a bit like comments and constants – the idea behind them is to increase code clarity, but I’ve seriously seen a programmer code constants for ONE,TWO,THREE, etc, all the way up to TEN, and reference the numbers by name, because they only understood ‘numbers should be constants’ not ‘well named constants add to code clarity’.
Which is a roundabout way of saying that for simple cases, as in the above, the shorter code is clearer, even without all the extra type information.
There was an attempt to modernise the syntax at one point, but it died, because existing developers didn’t embrace it, and any new developers only had old-style literature to refer to.
Personally – I have high hopes for increasing first-class support of other languages against the Cocoa runtime – i.e. Ruby / Python / Smalltalk / Nu / fscript. You’re still going to have the issues with the length of the Cocoa method names, but you get to work with an ‘OO only’ language rather than OO extensions.
Jesus wept. That has turned me off ObjC forever ;-)
Us Python programmers are still asking for “c++” rather thatn “c += 1” thank god it’s not as ugly as your example…
Wouldn’t OMeta solve all these problems? Mini, domain specific languages….
monk.e.boy
Felix: I’m learning Objective C for the only thing it’s really good for these days: writing Mac and iPhone applications.
Joshua/Jules: Totally agree about the positives of Objective C. I love how dynamic it is, although as far as I can tell, it is not much different than ActionScript 3 in its balance of dynamic/static typing.
I also love using categories. Being able to extend classes in this way (similar to C# 3.0 or Ruby).
Moke.e.boy: OMeta? Never heard of it. What does it do?
Objective-C is a great concept as a language but I agree that the bracket syntax is hard work. I’m not sure of the origins but maybe it took a signal from Smalltalk’s use of brackets for code blocks? (Smalltalk does not need brackets for message passing in general and is much, much easier to read because of it)
@JulesLt, as a former member of the ANSI C++ Standards Committee I’ll say that we worked very hard to allow all C programs to have equivalent meaning in C++ because we valued compatibility. We didn’t even drop support for implicit int until the ANSI C committee dropped it! However, one of the guiding principles for C++ was “as close to C as possible but no closer” and the strictness of the C++ type system meant there had to be some incompatibilities (as well as some syntactic clarifications, as I recall – it was a decade ago).
> Reading this syntax isn’t bad, but writing it is a pain. Every time you want to add a new method call at the end, you have to go all the way to the beginning of the line to add an open square bracket.
(defun objc-wrap-brackets (&optional count) (interactive “*p”) (backward-up-list count) (insert “[“) (forward-sexp +1) (save-excursion (insert “]”)) (just-one-space))
> Long names For typing them: M-x dabbrev, for reading: I agree. However, I prefer meaningful names over arc’s or perl’s line noise.
> Strings and collections [NSString stringWithFormat: @”The file %@ could not be found”, filename];
> Frankenstein – Not 100% object-oriented Well, that’s what you get if you tack on stuff to C. Ways to add new syntactic abstractions would be nice to have, I agree.
Cool emacs macro. I used to use emacs exclusively, but not these days. Also, in situations where you have to supply an arg, doesn’t it get a bit hard figuring out what the count should be? Maybe that situation just doesn’t come up that often…
Long names: I kind of agree about the meaningful names, but my personal opinion is that shorter names would have been better for the most commonly used items. Also, the fact that type/usage information is tacked onto every argument sometimes adds unneeded (IMHO) words.
For example, instead of
stringByReplacingOccurancesOfString:withString
, I would prefer something likereplace:with
. I know it doesn’t fit the convention of adding type and usage information to the names/arguments, but it’s not like that convention is universally followed in the first place. At the very least, couldn’t it bestringByReplacing:with
?For less commonly used classes/methods, I am fine with longer names.
As for dabbrev (and code hinting in general), it’s a life-saver, but it doesn’t help when you have a long common prefix for method names (e.g., ‘stringBy’ or ‘dictionaryBy’ or ‘NSMutable’). Maybe I am a lazier typist than most. :-)
I, too, find myself using stringWithFormat where I should probably use stringByAppendingString, but I’m bothered by the fact that I would choose one over the other over readability as opposed to picking the best method for the job. (come to think of it, stringWithFormat might be more efficient in this case, since the stringByAppendingString method would require an intermediate string to be created.. hmm…)
@8: “I, too, find myself using stringWithFormat where I should probably use stringByAppendingString, but I’m bothered by the fact that I would choose one over the other over readability as opposed to picking the best method for the job.”
stringWithFormat vs. stringByAppendingString is purely a readability issue. As far as efficiency goes ObjC is compiled and good ol’ g++ handles the efficiency part.
As far as the article goes, I think JavaScript syntax can be far more annoying than ObjC. Anon functions and closures get pretty ugly (like regex ugly).
Let’s be honest, ObjC is a great language, but the syntax is just ugly and painful.
With MacRuby, Apple is making ruby a real option for writing Cocoa apps. They’ve rewritten the ruby runtime so it uses the ObjC runtime. All ruby objects are ObjC objects (NSObject), and can be passed between ruby and objc without conversion, and you can use Cocoa, callbacks, everything. But with ruby syntax.
MacRuby includes HotCocoa that gives you nice ruby ways to do many of the common things in Cocoa, like instantiating GUI objects, etc, using shorter method and constant names, easy defaults and ideomatic ruby constructs.
Ruby and ObjC play very well togther, but ruby syntax is just so much more pleasant.
I’d heard burblings about Ruby and Cocoa, but I’d always assumed that it was a standard Ruby runtime communicating with an Objective C library.
I’ll have to check it out!
Ok.. after a quick look, MacRuby seems very exciting, but perhaps not 100% ready for commercial use. It will be interesting to see how it progresses.
visit…
[…]while the sites we link to below are completely unrelated to ours, we think they are worth a read, so have a look[…]…
I blog frequently and I really thank you for your content.
This great article has really peaked my interest. I will take a
note of your site and keep checking for new information about once per week.
I opted in for your Feed too.
Have a look at my blog post :: chiropractic care for ear infections (rocklandchiropractic.blogspot.com)
What’s Going down i am new to this, I stumbled upon this I have found It absolutely useful and it has aided me out loads.
I’m hoping to contribute & help different customers like
its aided me. Great job.
The best affiliate partners will be the ones offering this data with their affiliates to boost their success rates.
Look into what seems to be moving the needle, and figure out
how your brand or company can be doing the same.
You must make sure that you hire the best web
hosting company India to get the best deals and offers for web server hosting.
Figure out what it is you need and want and from there shop around to see what web hosts matches these expectations.
What search results will offered up with unless you possess a website or
perhaps a blog to market your business.
Une association hors du commun dans l’univers Brassicole :
Zlatansheim
bangkok rent scam paper scam in thailand thailand bar scam scam city thailand
taxi scam bangkok airport https://siam-shipping.com/