Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Pretty great article. Though I wish someone could point to the paper or whatever that explains the philosophy of Objective-C having insanely verbose method and parameter names. Like, readable is one thing, but they always end up like stringFromAppendingThingToThingToNumberYieldingThingThx and it becomes unimaginable to use Objective-C without XCode to autocomplete the other 40 characters.


It's because Objective-C methods are named according to the nouns that they return rather than the verbs they perform. For example, "[input stringByAppendingThing:thing]" rather than "input.append(thing)".

Methods are actions, not objects, so the most concise description for a method is usually a verb. Describing it as a noun instead requires adding prepositions and turning verbs to the gerund '-ing' form.

I realized this because I write both Ruby and Objective-C, and sometimes write basically the same thing in idiomatic forms of both languages. In idiomatic Ruby method-chaining, your code is a series of verbs with the relations between the actions defined by the '.' or the '()' signs, rather than by words such as 'to', 'from', 'with', or 'by' present in the name of the method.


Eh, I think that's a little overbroad. The way it works is, methods whose purpose is returning something are named for what they return, while methods whose purpose is creating a side effect are named for what they do. So NSString has `stringByAppendingString:` because you're asking for a new string, while NSMutableString has `appendString:`, which is essentially the same as it would be in Ruby except with an allowance for Objective-C's static type system.

What really creates the impression that Objective-C speaks in terms of nouns is that Cocoa tends to promote immutable objects more than Ruby does (e.g. the only way to get an immutable string or array in Ruby is to freeze a mutable one, while you'll almost never get a mutable array in Cocoa unless you create one yourself), so you probably do spend more time asking your objects for other objects than you do in Ruby.

Although the verbosity can get overwhelming, I actually like this about Objective-C. In terser dynamic languages, I'm constantly having to confirm (either mentally or in the docs) which methods mutate and which return a new object. Cocoa's naming conventions mean I pretty much never have to do that.


The guidelines for Ruby are to add a bang (!) to any methods that mutate the object rather than returning a new one. That's not strictly followed, though, but for most of the commonly used standard library bits, you can be fairly certain that that is the case.


In practice, even in the standard library, this isn't followed often enough to rely on. Here's a (possibly incomplete, since I'm writing this on the fly) list of bangless mutating methods just from Array:

  pop
  push
  shift
  unshift
  <<
  clear
  replace
  delete (and friends)
  keep_if
As an even more extreme example, IO contains precisely one bang-method, despite the fact that probably 75% of IO's instance methods are destructive.

The general rule seems to be that if there's a mutating and non-mutating version of the same method, the mutating one will get a bang, but when there's a mutating method with no counterpart, it might get a bang but probably won't.


The guideline is: if your method does something that the programmer should think twice about or shouldn't use without proper knowledge (e.g. didn't read the docs), use !. An incomplete case of usages:

  - There is a safer alternative (e.g. mutating vs. non-mutating or skipped validation)
  - It should only be called once in a process (e.g. Padrino.start!)
  - It is non-reversible (many statemachine libraries use action! as the way to invoke state transitions, which might not be reversible)
This doesn't mean that every method needs to be suffixed by ! if it does something destructive. `delete` in the context of an ORM is standard, so it doesn't have a bang. The whole point of `pop` is to manipulate the receiver: no point in warning about it. IO is always destructive, so ! doesn't make sense either.


Very well said. I think this also promotes a mindset of making methods that either mutate state or build and return an object. It's often very difficult to follow code that has lots of methods that do both.


Have you read http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom... ?

Yegge basically completely agrees with you. Once I started thinking of OOP in these terms it helped me, as a programmer, a lot.


Thats a hilarious post but it sounds like Steve would love PHP. He could use nouns (objects) when he wanted yet add global functions (verbs) with no attachment to objects. I personally think that's a great way to make a terrible mess, but perhaps he knows something that I don't.


Interesting observation. It is called "Object"ive for a reason :)

I wonder if we can relate your observation to the fact that "messages" (nouns) are preferred to "methods" (verbs) in Obj-C.


Selectors always describe exactly what the method does and what it needs. For example, stringByAppendingStringWithFormat: says "You will get a new string, by appending a format string to the receiver." There is also the mutable counterpart, appendStringWithFormat:, which is shorter because it doesn't return a new string, instead, appending directly to the receiver.

Verbose selectors make Objective-C self-documenting at the cost of extra typing. But autocomplete solves this problem because you only ever have to type 2-5 characters to insert the method you want (once you are experienced enough to predict what autocomplete will spit out).

Objective-C naming conventions form predictable patterns. Inexperienced programmers gripe because they have yet to figure out these patterns, good programmers love Objective-C because they understand these patterns and can therefore predict the name of a method and its arguments and great programmers write their own classes that use these patterns.


Seconded. The first time you write a fully working method using a library you've never used in one shot without looking anything up will make you love ObjC.


I've done exactly as you say, and I still find Objective-C Perlesque in its obnoxiousness. I also manage to achieve that not-terribly-hard feat on a pretty regular basis with Java: intellisense (hi, IntelliJ!) and IDE-provided Javadocs do the same thing, too, and someone who isn't going to write good Javadocs isn't going to name things well.


The idea is that code is written once but read many times. Objective-C's verbose naming make you work a little more when writing it (though a good programmer's editor or IDE like Xcode or AppCode greatly eases this) but it pays off each time you need to read the code, especially code you're not familiar with.

With it's C-based syntax, Objective-C isn't as clean as Python or Ruby, but due to the explicit naming conventions, I think it's more readable than Java or JavaScript.


I actually find it much harder to read as a result of it's verbosity. For example, just yesterday I ran into a bug with these 2 lines:

    if ([[data objectForKey:@"released"] isKindOfClass:[NSNull class]]) {
    if ([[data objectForKey:@"posterUrl"] isKindOfClass:[NSString class]]) {        
They weren't right next to each other, and at a glance, I misread to assume they were doing the same thing. There's too much shit in the way of the actual differences (NSNull vs. NSString in this case) that I have a bad tendency to gloss over the details. Coming from ruby, the closest syntactical equivalent:

    if (data['released'].class == NilClass) {
    if (data['posterUrl'].class == String) {
Is so much clearer to me when glancing through code. That doesn't even touch on how you'd actually write that sort of thing (data['released'].nil?) which is infinitely more concise than either example. I know this is a bit of a contrived example, and I certainly could find better ones. I just find the 120 character long method evocations to consistently blur the details for me, and this just happens to be the freshest instance.

To be fair, I've only been doing iOS stuff for about a month. Does this trend reverse after you've been writing obj-c for a while?


I've found after a while you get really used to the verbosity. I miss it when I return to other languages.

For instance, I look at the first example you posted and I know exactly what it does. It's very natural for me to read.


Is it really easier than `data['poster_url'].is_a? String`? I wouldn't call the Objective-C example unreadable, but it's certainly a lot more line noise for not a lot more meaning.


You do get used to it. Because it's a superset of C, Objective-C has all the syntactic noise of C and some of its own. Ruby is certainly more compact, though with its Perl influence, you can write very cryptic Ruby code. You do pay a price in Objective-C in order to have C directly and immediately available.

FWIW, extracting nested expressions into local variables helps a lot with nested method calls.


Key-value accessors aren't exactly the shining moment of verbose method names (It's even been leaked that 10.8 has dict[key] sugar), but for methods with more parameters, it's much nicer than positional. e.g.:

connection:didReceiveResponse: addObserverForName:object:queue:usingBlock: drawAtPoint:forWidth:withFont:minFontSize:actualFontSize:lineBreakMode:baselineAdjustment:


I've found it pays off at write time too. Having to say something about each parameter when naming a method really helps me to stop and think about what I'm doing every time I add to an object's interface. I'd like to think it ultimately leads to less bloat.


I don't agree with your reasoning, but part of that is my operating definition of "verbose" is "more words than needed." That is, if you're being verbose, then by definition you're using too many words, which is a stance I find difficult to defend.

Personally, once you have more than two humps in your camel case, my eyes have trouble scanning.


True, "verbose" isn't really the correct term, "explicit" better describes Objective-C. Here's an example where I think Objective-C's explicitness is helpful. The Windows API CreateWindow() function call in C:

  HWND hwnd = CreateWindow("MainWClass", "Sample",
                           WS_OVERLAPPEDWINDOW,
                           CW_USEDEFAULT, CW_USEDEFAULT,
                           CW_USEDEFAULT, CW_USEDEFAULT,
                           (HWND) NULL, (HMENU) NULL,
                           hinstance, (LPVOID) NULL);
And here's a long method call in Objective-C:

  NSString *filtered = [unfiltered stringByReplacingOccurrencesOfString:@"verbose"
                                   withString:@"explicit"
                                      options:NSCaseInsensitiveSearch
                                        range:NSMakeRange(0, [unfiltered length])];
Admittedly not equivalent examples, but I couldn't quickly find a Cocoa method call with eleven parameters. My argument is that if you're not intimately familiar with these two calls, CreateWindow() is pretty cryptic. You only get the most general sense of what it's doing without consulting a reference. Objective-C's strange method naming scheme (taken from Smalltalk) makes complex method calls much easier to understand in situ.


> I couldn't quickly find a Cocoa method call with eleven parameters

Allow me to introduce you to NSBitmapImageRep, which holds the dubious honor of being initialized by the longest public selector in all of Cocoa. Here's a contrived example:

  NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:data
                                               pixelsWide:640     pixelsHigh:480
                                            bitsPerSample:8  samplesPerPixel:3
                                                 hasAlpha:NO        isPlanar:YES
                    colorSpaceName:@"NSCalibratedRGBColorSpace" bitmapFormat:NULL
                                              bytesPerRow:0     bitsPerPixel:0];
edit: formatting


Awesome! Thanks for the example. Painfully long but a lot easier to understand in situ than something like CreateWindow().


I agree the second example is more understandable, but I think most of that benefit comes from named parameters (a language feature), not the naming convention itself. That is, were the naming up to me, I would prefer:

  NSString *filtered = [unfiltered replace:@"verbose"
                                   with:@"explicit"
                                   options:CaseInsensitive
                                   range:Range(0, [unfiltered length])];
Of course, I'm making assumptions about what those parameters mean. But I find this much more clear, assuming the intentions are what I think they are.


In Objective-C, those aren't named parameters, like you might find in Python, or faked in Ruby or Groovy. They are called 'Keyword Messages'. In your example above, the method signature is replace:with:options:range:, compared to say a C++ style replaceWithOptionsRange. It's simply a way to interleave arguments in the message send itself, inherited from Smalltalk.


When you use the word "replace", to most people, that signals that you would be changing the current object in place, not returning a new object based on the given one.

On the second line, you didn't mention at all what is passed in.

For the last two, removing the NS prefix would work if Objective-C had some kind of namespacing support. Currently it doesn't, so the NS prefix is kinda needed.


New object versus mutating the current object depends on convention - in Python, there is a "replace" function on the native string type that returns a copy (http://docs.python.org/library/stdtypes.html#string-methods); in C++, std::string::replace mutates the string in place.

I'm not sure what you mean by not mentioning what is passed in. Keep in mind: I have never programmed in Objective-C. I am going on intuition alone.

No namespace support is a bummer - it means you're going to end up with long identifiers all over the place.


That's one of the things I'm finding most annoying about learning Obj-C. The weird thing is that these extra long names make the language less readable to me, because I have to mentally diff very similar looking long strings.


I think the verbose method names are a Cocoa design decision.


The design philosophy behind much of Objective-C is described in Brad Cox's book "Object-oriented programming: an evolutionary approach" [1]. Unfortunately, I don't have a copy handy to give you a quote.

[1] http://books.google.co.nz/books?id=U8AgAQAAIAAJ


It's a technical requirement. Parameter types are not part of the method signature, so you CAN NOT define both [string append:string] and [string append:int] methods. You must give them different names, like [string appendString:string] and [strig appendInt:int] , in order to give them different signatures.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: