Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Aspect Oriented Programming

Weizhong Yang
September 12, 2013

Aspect Oriented Programming

Weizhong Yang

September 12, 2013
Tweet

More Decks by Weizhong Yang

Other Decks in Technology

Transcript

  1. Aspect Oriented
    Programming
    楊維中 a.k.a zonble
    [email protected]
    Thursday, September 12,

    View full-size slide

  2. zonble
    ฌᖯ؛ۇ
    Thursday, September 12,

    View full-size slide

  3. ᖯ৵ʔ݊ɓ˂ிϓٙ
    Unmaintainable 的 code 也是
    Thursday, September 12,

    View full-size slide

  4. ⼀一開始,程式邏輯就只有插
    ⼊入資料⽽而已…
    - (void)appendData:(NSData *)inData {
    [_data appendData:inData];
    }
    Thursday, September 12,

    View full-size slide

  5. 後來,我們想確定傳⼊入的不
    是 nil 或空資料
    - (void)appendData:(NSData *)inData {
    NSParameterAssert(inData != nil);
    NSParameterAssert([inData length]);
    length = [_data length];
    [_data appendData:inData];
    NSAssert(length != [_data length]);
    }
    Thursday, September 12,

    View full-size slide

  6. 後來,我們覺得 Release Build
    也應該防⽌止輸⼊入空資料…
    - (void)appendData:(NSData *)inData {
    NSParameterAssert(inData != nil);
    NSParameterAssert([inData length]);
    if (!inData) { return; }
    if (![inData length]) { return; }
    length = [_data length];
    [_data appendData:inData];
    NSAssert(length != [_data length]);
    }
    Thursday, September 12,

    View full-size slide

  7. 後來,我們發現這個 method
    可能會在很多 thread 呼叫…
    - (void)appendData:(NSData *)inData {
    NSParameterAssert(inData != nil);
    NSParameterAssert([inData length]);
    if (!inData) {
    NSLog(@"inData is nil!");
    return;
    }
    if (![inData length]) {
    NSLog(@"Length of inData is 0!");
    return;
    }
    length = [_data length];
    [_lock lock];
    [_data appendData:inData];
    [_lock unlock];
    NSAssert(length != [_data length]);
    }
    Thursday, September 12,

    View full-size slide

  8. 後來,在 Debug Build 裡頭要
    加上 TestFlight CheckPoint
    - (void)appendData:(NSData
    *)inData {
    NSParameterAssert(inData !=
    nil);
    NSParameterAssert([inData
    length]);
    if (!inData) {
    NSLog(@"inData is nil!");
    return;
    }
    if (![inData length]) {
    NSLog(@"Length of inData
    is 0!");
    return;
    }
    length = [_data length];
    [_lock lock];
    [_data appendData:inData];
    [_lock unlock];
    NSAssert(length != [_data
    length]);
    #if DEBUG
    [TestFlight
    passCheckpoint:@"APPEND_DATA"];
    #endif
    }
    Thursday, September 12,

    View full-size slide

  9. Release Build 則要加上 Flurry
    Event Log…
    - (void)appendData:(NSData
    *)inData {
    NSParameterAssert(inData !=
    nil);
    NSParameterAssert([inData
    length]);
    if (!inData) {
    NSLog(@"inData is nil!");
    return;
    }
    if (![inData length]) {
    NSLog(@"Length of inData
    is 0!");
    return;
    }
    length = [_data length];
    [_lock lock];
    [_data appendData:inData];
    [_lock unlock];
    NSAssert(length != [_data
    length]);
    #if DEBUG
    [TestFlight
    passCheckpoint:@"APPEND_DATA"];
    #else
    [Flurry
    logEvent:@"APPEND_DATA"];
    #endif
    }
    Thursday, September 12,

    View full-size slide

  10. 還有 Google Analytics…
    - (void)appendData:(NSData
    *)inData {
    NSParameterAssert(inData !=
    nil);
    NSParameterAssert([inData
    length]);
    if (!inData) {
    NSLog(@"inData is nil!");
    return;
    }
    if (![inData length]) {
    NSLog(@"Length of inData
    is 0!");
    return;
    }
    length = [_data length];
    [_lock lock];
    [_data appendData:inData];
    [_lock unlock];
    NSAssert(length != [_data
    length]);
    #if DEBUG
    [TestFlight
    passCheckpoint:@"APPEND_DATA"];
    #else
    [Flurry
    logEvent:@"APPEND_DATA"];
    idtracker = [[GAI
    sharedInstance] defaultTracker];
    [tracker send:
    [[GAIDictionaryBuilder
    createEventWithCategory:@"data"
    withAction:@"append"
    withLabel:@"user_data"
    withValue:nil] build]];
    #endif
    }
    Thursday, September 12,

    View full-size slide

  11. 每件事情都很重要
    • 確定傳⼊入參數的型態與內容
    • 確定真的有插⼊入資料
    • 加 Lock
    • 加 Debug Log
    • 加 TestFlight Log、Flurry Log…
    Thursday, September 12,

    View full-size slide

  12. 23 ⾏行 code 中,
    ਂ͍ԫ̥ٙϞɓБf
    這還不是最糟的…
    Thursday, September 12,

    View full-size slide

  13. 更糟的是…
    不只⼀一個 method 這樣
    Thursday, September 12,

    View full-size slide

  14. ᒔึॎᕸ೻όٙࠠ͜
    Thursday, September 12,

    View full-size slide

  15. 上個世紀末,就有⼈人覺得…
    வᅵʔБ
    接下來的故事請⾃自⼰己查 Wikipedia
    Thursday, September 12,

    View full-size slide

  16. AOP 的基本想法:
    Ҫ΢၇೷ౢආԸٙ
    Code פᕎԨ܆ༀ
    ⽅方法很多
    Thursday, September 12,

    View full-size slide

  17. Cross-cutting concerns
    …就是這些
    • 確定傳⼊入參數的型態與內容
    • 確定真的有插⼊入資料
    • 加 Lock
    • 加 Debug Log
    • 加 TestFlight Log、Flurry Log…
    Thursday, September 12,

    View full-size slide

  18. Advice






    在原本程式前後
    插⼊入的程式碼
    Thursday, September 12,

    View full-size slide

  19. Decorator
    Syntax
    …Objective C 不⽀支援
    Thursday, September 12,

    View full-size slide

  20. Decorator Syntax
    def add(x):
    print "x:" + str(x)
    result = x + 1
    print "result:" + str(result)
    return result
    Thursday, September 12,

    View full-size slide

  21. Decorator Syntax
    def log(func):
    def inner_func(*a):
    print "args:" + str(a)
    result = func(*a)
    print "result:" + str(result)
    return inner_func
    @log
    def add(x):
    return x + 1
    Thursday, September 12,

    View full-size slide

  22. Objective-C 特性
    Message
    Forwarding
    當⼀一個物件不⽀支援某個 Selector 的時
    候,這個物件可以決定把 Selector 交給
    其他的物件。
    Thursday, September 12,

    View full-size slide

  23. Message Forwarding
    - (void)forwardInvocation:(NSInvocation *)anInvocation {
    if ([someOtherObject respondsToSelector:
    [anInvocation selector]])
    // Advice here
    [anInvocation invokeWithTarget:someOtherObject];
    // Advice here
    else
    [super forwardInvocation:anInvocation];
    }
    See: Objective-C Runtime Programming Guide
    Thursday, September 12,

    View full-size slide

  24. AOP-in-Objective-C
    https://github.com/moszi/AOP-in-
    Objective-C
    Thursday, September 12,

    View full-size slide

  25. Method
    Swizzling
    Thursday, September 12,

    View full-size slide

  26. Objective-C 第⼀一課
    • ObjC 物件都是 C Structure
    • ObjC method 都是 C function pointer
    • 系統有⼀一個動態的索引表格,決定執⾏行
    某個 selector 時,要對應到哪個 C
    function
    • Selector 就是索引表中的 key,型態為 C
    字串
    Thursday, September 12,

    View full-size slide

  27. Objective-C 第⼆二課
    • ⼀一個 Class 有哪些 method,都是在
    runtime 的時候建⽴立的
    • 所以可以在 runtime 新增新的 method,
    例如使⽤用 category 語法
    • 也可以直接使⽤用 runtime API 把已經存在
    的 method 換掉
    Thursday, September 12,

    View full-size slide


  28. BOOL class_addMethod(Class cls, SEL name,
    IMP imp, const char *types);
    IMP method_setImplementation(Method method,
    IMP imp);
    Thursday, September 12,

    View full-size slide

  29. Thursday, September 12,

    View full-size slide

  30. Thursday, September 12,

    View full-size slide

  31. Thursday, September 12,

    View full-size slide

  32. AOP-for-Objective-C
    https://github.com/ndcube/AOP-for-
    Objective-C/
    在繼承關係的部份有些 bug,我⾃自⼰己有
    先修,但是還沒有送 pull request…
    Thursday, September 12,

    View full-size slide

  33. Thank you!
    Thursday, September 12,

    View full-size slide