2003
01 02 03 04 05 06 07 08 09 10 11 12
2006
01 02 03 04 05 06 07 08 09 10 11 12
2007
01 02 03 04 05 06 07 08 09 10 11 12
2008
01 02 03 04 05 06 07 08 09 10 11 12
2009
01 02 03 04 05 06 07 08 09 10 11 12
2010
01 02 03 04 05 06 07 08 09 10 11 12
2011
01 02 03 04 05 06 07 08 09 10 11 12
2017
01 02 03 04 05 06 07 08 09 10 11 12
2018
01 02 03 04 05 06 07 08 09 10 11 12
 
Jun
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 不約而同 😀”

---ericsk. 12/30, 2008
 
 

Write Concisely