Dec
30
2008

My Cocoa Coding Style

最近回頭看我第一個比較成功的軟體 Nally,發現以前實在是不懂事啊。沒有 profile 過 bottle-neck 就擅自想:「我只要把所有的地方都寫得有效率就好了!」,結果證明 Knuth 是對的:「Premature Optimization is EVIL」。結果就是,寫得很醜又難懂。

後來在一些新的 project 上我已經採用了新的 coding style,目前使用上已經穩定下來了。自己有一套原則後,在幫別人看 code 抓漏時只要沒有 consistent coding style 都會讓我很難過。所以,請大家自己也設定一套 coding style 吧。不要有的時候 if 和 ( 中間有空格,有時沒空格的。

Header File:

extern int YLSomeConstant;
 
@interface YLMyClass : NSObject { // Prefix your class by abbreviation
    NSString *_name; // prefix instance variable with underscore
    BOOL _beta;
    IBOutlet NSView *mMyView; // prefix IBOutlet with m
}
 
@property (copy) NSString *name;
@property BOOL beta;
 
/* space between each token except the argument and its type */
- (void) methodDeclaration: (TypeClass *)arg1 anotherArgument: (id)arg2;
@end

在一般變數命名上和大家都差不多,值得注意的是我使用了 Apple 叫你不要用的 prefix 命名系統。重點不在你要隱藏什麼,而是之後你可以明顯看出,一個變數到底是 ivar 還是只是 local variable。排版方面我喜歡較寬鬆的版型,所以 method declaration 除了 argument 與其型別之間一律空一格。雖然這樣讓我沒辦法直接用 Apple 生成的 code 或者從文件中拷貝過來就可以用,但是看起來舒服些。

Implementation File:

int YLSomeConstant = 18;
static CGSize gMySize; // prefix static variable with g
 
@interface YLMyClass (Private)
- (int) _ageOfWoman; // prefix private method with underscore
@end
 
@implementation YLMyClass (Private)
- (int) _ageOfWoman
{
    return YLSomeConstant;
}
@end
 
@implementation YLMyClass
- (YLMyClass *) init
{
    if ([super init]) { // Not (self = [super init])
        // initialize code
    }
    return self;
}
 
- (void) methodDeclaration: (TypeClass *)arg1 anotherArgument: (id)arg2
{
    if (!arg2) return; // short statement takes one line
    if (![arg1 sendSomeMessage: _name withData: [NSData data]])
        return; // long statement takes two lines
 
    int i; // local variable, no prefix
    for (i = 0; i < 100; i++) {
        // Loop here. while, do while follow the same style.
    }
    switch (c) {
        case 1:
            // code
        case 2:
            // code
        default:
            // code
    }
}
@end

而我的 private method 前面也加了底線,雖然這可能會 override Apple 的 private method,但是我沒辦法忍受 YL_thisIsAPrivateMethod 這麼醜陋的寫法。這是從 Wil Shipley 那邊學來的。

而我的 accessor 寫法是這樣的:

- (SomeClass *) myProperty
{
    return [[_myProperty retain] autorelease];
}
 
- (void) setMyProperty: (SomeClass *)aProperty
{
    if (_myProperty != aProperty) {
        [_myProperty release];
        _myProperty = [aProperty retain];
    }
}

自己內部使用時,_myProperty 絕對是唯獨的。要存取一定得叫用 setter。至於 getter 這樣寫是為了避免直接回傳會發生這種情況:

id aProperty = [someObj myProperty]; // assume [aProperty retainCount] == 1
[someObj setMyProperty: anotherProperty]; // aProperty was dealloc'd now!
[aProperty doSomething]; // Crash!
 

Annotations RSS

“雖然我在寫別的語言,不過我除了左大括跟你不一樣以外,其它的 style 不約而同 :D

---ericsk. 12/30, 2008
 
 

Write Concisely