views:

1378

answers:

10

Being new to Objective-C (but a long term C/++) programmer I'm looking for advice/recommendations on naming conventions for variables.

My personal preference would be to utilize a prefix for instance variables both for clarity within functions and to prevent shadowing of function parameters. However I'm a fan of properties which rules out prefixes (unless you also prefix your property names, which doesn't work too well and looks daft). Similarly I could use the "self.variable" convention, but only if I make EVERYTHING a property.

So given the code below what's your preferred naming style for instance/function variables? And if you don't bother, how do you deal with shadowing on function params?

@interface GridItem : NSObject
{
    CGRect _rect;
    ...  
}
@end

-(void) initFromRect:(CGRect)rect
{
    _rect = rect;
    ...
}

Cheers!

+1  A: 

I don't like using underscores as prefixes for any identifiers, because C and C++ both reserve certain underscore prefixes for use by the implementation.

I think using "self.variable" is ugly.

In general, I use unadorned identifiers (that is, no prefixes nor suffixes) for instance variables. If your class is so complicated that you can't remember the instance variables, you're in trouble. So for your example, I'd use "rect" as the name of the instance variable and "newRect" or "aRect" as the parameter name.

Kristopher Johnson
+2  A: 

Personally, I follow the Cocoa naming conventions, using camel-casing for functions and variables, and capitalized camel-casing for object names (without the leading NS of course).

I find type prefixing makes code more opaque to anyone who didn't write it (since everyone invariably uses different prefixes), and in a modern IDE it's not really that difficult to figure out something's type.

DannySmurf
+12  A: 

Most Cocoa projects use underbar as a non-IBOutlet instance variable prefix, and use no prefix for IBOutlet instance variables.

The reason I don't use underbars for IBOutlet instance variables is that when a nib file is loaded, if you have a setter method for a connected outlet, that setter will be called. However this mechanism does not use Key-Value Coding, so an IBOutlet whose name is prefixed with an underbar (e.g. _myField) will not be set unless the setter is named exactly like the outlet (e.g. set_myField:), which is non-standard and gross.

Also, be aware that using properties like self.myProp is not the same as accessing instance variables. You are sending a message when you use a property, just like if you used bracket notation like [self myProp]. All properties do is give you a concise syntax for specifying both the getter and setter in a single line, and allow you to synthesize their implementation; they do not actually short-circuit the message dispatch mechanism. If you want to access an instance variable directly but prefix it with self you need to treat self as a pointer, like self->myProp which really is a C-style field access.

Finally, never use Hungarian notation when writing Cocoa code, and shy away from other prefixes like "f" and "m_" — that will mark the code as having been written by someone who doesn't "get it" and will cause it to be viewed by suspicion by other Cocoa developers.

In general, follow the advice in the Coding Guidelines for Cocoa document at the Apple Developer Connection, and other developers will be able to pick up and understand your code, and your code will work well with all of the Cocoa features that use runtime introspection.

Here's what a window controller class might look like, using my conventions:

// EmployeeWindowController.h
#import <AppKit/NSWindowController.h>

@interface EmployeeWindowController : NSWindowController {
@private
    // model object this window is presenting
    Employee *_employee;

    // outlets connected to views in the window
    IBOutlet NSTextField *nameField;
    IBOutlet NSTextField *titleField;
}

- (id)initWithEmployee:(Employee *)employee;

@property(readwrite, retain) Employee *employee;

@end

// EmployeeWindowController.m
#import "EmployeeWindowController.h"

@implementation EmployeeWindowController

@synthesize employee = _employee;

- (id)initWithEmployee:(Employee *)employee {
    if (self = [super initWithWindowNibName:@"Employee"]) {
        _employee = [employee retain];
    }
    return self;
}

- (void)dealloc {
    [_employee release];

    [super dealloc];
}

- (void)windowDidLoad {
    // populates the window's controls, not necessary if using bindings
    [nameField setStringValue:self.employee.name];
    [titleField setStringValue:self.employee.title];
}

@end

You'll see that I'm using the instance variable that references an Employee directly in my -init and -dealloc method, while I'm using the property in other methods. That's generally a good pattern with properties: Only ever touch the underlying instance variable for a property in initializers, in -dealloc, and in the getter and setter for the property.

Chris Hanson
Apple's UITextView prefixes ivars with m_.
Christopher Lloyd
...and? That doesn't make it a good idea. :)
Chris Hanson
+1  A: 

Andrew: There actually are plenty of Cocoa developers who don't use instance variable prefixes at all. It's also extremely common in the Smalltalk world (in fact, I'd say it's nearly unheard-of in Smalltalk to use prefixes on instance variables).

Prefixes on instance variables have always struck me as a C++-ism that was brought over to Java and then to C#. Since the Objective-C world was largely parallel to the C++ world, where as the Java and C# worlds are successors to it, that would explain the "cultural" difference you might see on this between the different sets of developers.

Chris Hanson
+2  A: 

With the introduction of properties I see no need for prefixing "_" to class instance variables. You can set a simple rule (described in your header file) that any variables to be accessed external to the class must be accessed via the property, or by using custom methods on the class to affect values. This to me seems much cleaner than having names with "_" stuck on the front of them. It also properly encapsulates the values so that you can control how they are changed.

Kendall Helmstetter Gelner
+3  A: 

You can use the underbar prefix on your ivars and still use the non-underbar name for your properties. For synthesized accessors, just do this:

@synthesize foo = _foo;

This tells the compiler to synthesize the foo property using the_foo ivar.

If you write your own accessors, then you just use the underbar ivar in your implementation and keep the non-underbar method name.

Scott Marcy
+1  A: 

My style is hybrid and really a holdover from PowerPlant days:

THe most useful prefixes I use are "in" and "out" for function/method parameters. This helps you know what the parameters are for at a glance and really helps prevent conflicts between method parameters and instance variables (how many times have you seen the parameter "table" conflict with an instance variable of the same name). E.g.:

- (void)doSomethingWith:(id)inSomeObject error:(NSError **)outError;

Then I use the bare name for instance variables and property names:

Then I use "the" as a prefix for local variables: theTable, theURL, etc. Again this helps differentiate between local and and instance variables.

Then following PowerPlant styling I use a handful of other prefixes: k for constants, E for enums, g for globals, and s for statics.

I've been using this style for something like 12 years now.

schwa
Not convinced on the k, E, g and s thing, but I like the idea of adding in and out.
Steven Fisher
+7  A: 

I follow Chris Hanson's advice in regards to the underscore ivar prefix, though I admit I do use underscore's for IBOutlets as well. However, I've recently starting moving my IBOutlet declarations to the @property line, as per @mmalc's suggestion. The benefit is that all my ivars now have an underscore and standard KVC setters are called (i.e. setNameField:). Also, the outlet names don't have underscores in Interface Builder.

@interface EmployeeWindowController : NSWindowController {
@private
    // model object this window is presenting
    Employee *_employee;

    // outlets connected to views in the window
    NSTextField *_nameField;
    NSTextField *_titleField;
}

- (id)initWithEmployee:(Employee *)employee;

@property(readwrite, retain) Employee *employee;
@property(nonatomic, retain) IBOutlet NSTextField *nameField;
@property(nonatomic, retain) IBOutlet NSTextField *titleField;

@end
Dave Dribin
This is actually what I do now, thanks to IB's support for IBOutlet on properties. :)
Chris Hanson
A: 

While I love using the underscore prefix for ivars, I loathe writing @synthesize lines because of all the duplication (it's not very DRY). I created a macro to help do this and reduce code duplication. Thus, instead of:

@synthesize employee = _employee;

I write this:

ddsynthesize(employee);

It's a simple macro using token pasting to add an underscore to the right hand side:

#define ddsynthesize(_X_) @synthesize _X_ = _##_X_

The only downside is that it will confuse Xcode's refactoring tool, and it won't get renamed, if you rename the property by refactoring.

Dave Dribin
+1  A: 

Along with what's been said here, be sure to read the Cocoa documentation on Key Value Observing compliant naming. Strictly following this pattern will help you greatly in the long run.

Marc Charbonneau