views:

422

answers:

6

one of the things i like most about cocoa is the readability factor. but... one of the things that annoys me most is the convention of convenience constructors to stutter.

what I mean is this:

[NSString stringWithString:s]

[NSNumber numberWithDouble:d]

[NSValue valueWithInt:i]

[NSDictionary dictionaryWithObjectsAndKeys:]

etc...

why doesn't the convention follow a less stutter/echo pattern and simply start convenience constructors with the word "with"? so then we would have:

[NSString withString:s]

[NSNumber withDouble:d]

[NSValue withInt:i]

[NSDictionary withObjectsAndKeys:]

etc...

it's a minor discussion point, but one I thought I would just throw out there and see if anyone with more clout than me can explain all the echos in my head ;-)

obviously, I'm not going to petition AAPL to re-write the appKit in favour of my suggestion, but are there any arguments against naming my own conv-constr's as such? (of course i can use whatever conventions i want in my own code (duh!) but i hate to swim upstream blindly). Roger, Roger?

A: 

If you don't like it, why not write up a bunch of #define statements that you include in all your projects?

samoz
it's definitely something i can live with, but have many times wondered about. but yes, I do have a handful of macros that make frequently used conv-contr's much shorter and easier to type... technically speaking, don't those defines represent an anti-pattern?
kent
I think this is a terrible idea. Even if it makes sense to you, your code becomes far less readable when someone else has to maintain it.
e.James
thus anti-pattern.
kent
that's not a answer to the question. If he had asked how can I use my chosen convention then your answer would be ok
hhafez
+3  A: 

I think it's just part of the general "say exactly what you mean" wordiness philosophy of the cocoa framework. A few choice selections:

[UIView setAnimationBeginsFromCurrentState]
[UITableView scrollToNearestSelectedRowAtScrollPosition]
[UIApplication didRegisterForRemoteNotificationsWithDeviceToken]

etc.

ETA:

To answer the questions specifically about constructors, one thing I like about the way they are done is that it's easy within x-code to identify which methods are constructor type methods. For example, you start typing:

[NSString string

And the "intellisense" whittles down the list of methods to those that start with "string" which of course are all the constructor methods (and all conveniently grouped together as well). Same thing applies for the "init" convention.

Eric Petroelje
witch is a breeze when you came from C# and get plenty of code to read as int a, b, c; ... :-/
balexandre
@eric: i agree,lol. but in your examples are nice to read in implementation files. but in this "roger roger" case the implementations stutter and but the declarations look sensible: irony becuase you end up typing the declaration once, but implementations for the rest of your life...
kent
+9  A: 

Because it's consistent.

There are methods like:

[NSDictionary dictionary]
[NSArray array]

Getting rid of everything up to with is obviously not an option here. Keeping these, but shortening others would introduce inconsistency in naming of convenience methods.

And convenience methods are consistent with init and initWith… methods.

porneL
......roger, roger.
kent
+3  A: 

Ultimately, I believe the Objective-C philosophy, as embodied by the Cocoa frameworks (and the NextStep frameworks before it) is that being explicit, and easy to maintain takes precedence over terseness of code. The main evidence for this philosophy is that Objective-C selectors have named arguments (e.g. -[NSObject performSelector:withObject:]). In the case of factory methods such as +[NSString stringWithString:], you must remember that subclasses may override these class methods to return subclasses (for example class clusters such as NSNumber). So, you may end up with a call like [MyPoorlyNamedSubclass stringWithString:] in which case -[MyPoorlyNamedSubclass withString:] would not be obviously informative as to the type of object returned (recall that many factory methods return type id). stringWithString:, on the other hand makes it clear that the method will return a string (or subclass thereof).

Barry Wark
+7  A: 

There is actually a technical reason for it to be that way. If every shoelaceWithString:-type method were changed to just withString:, we would end up with a fearsomely huge number of classes with identically named methods and different signatures. This plays mean tricks on the compiler's static type checking and can cause it to throw up all sorts of annoying and unnecessary warnings.

There's also an aspect of Cocoa culture where developers like their code to be self-documenting. This means that method names indicate both what their arguments are and what they return. Apple's coding guidelines actually warn about methods with vague names, suggesting that adding words to the name to make it clear what a method does is preferable.

Chuck
thanks alot, Chuck. this is very useful information, I appreciate your response.
kent
+2  A: 

They also use that one extra word to tell if the object is autoreleased or not. initWithFormat is for non-autoreleased, and when its stringWithFormat it is autoreleased... I guess they just went with that way of telling the reader what kind of memory management the object uses...

micmoo