テストコードを読んでライブラリの難しいコードを理解する

こんにちは、@toshi0383 です。

この1年間振り返ると様々なライブラリにお世話になってきました。ライブラリは中身の実装は知らなくても使えるよう、「まアいつものアレでしょ」という処理が抽象化されているというのが便利な点なわけですが、ソースコードを読んで動きを理解する必要がどうしても出てくると思います。ドキュメントが充実しているライブラリばかりではないですしね。今日はそんな時に効率よく理解を深めるために私が実践している方法をご紹介します。

ズバリ一言で、「テストコードを読め」です。

例えば、このReactiveKitの処理があります。

var operation: Operation<Int, TestError>!
operation = create { observer in
    observer.next(1)
    observer.next(2)
    observer.next(3)
    observer.success()
    simpleDisposable = SimpleDisposable()
    return simpleDisposable
} 

はじめちょっと何をやっているのかわからなかったのですが、対応するテストコードはこうなっていました。

var disposable: DisposableType!
disposable = operation.observeNext(on: ImmediateExecutionContext) {
    observedEvents.append($0)
} 
...
...
expect(observedEvents) == [1, 2, 3]

これだけ見れば、observeNextにImmediateExecutionContext とかいうのを渡すとoperationが発火して、値が観測できるようだ、ということがわかります。 このレベルであれば、下手にググるよりはテストコードを読んだ方が、素早く正しい使い方がわかるわけです。

もう一つ例を載せておきます。SwiftStateのテストコードです。

var invokeCount = 0 
        
let machine = StateMachine<MyState, NoEvent>(state: .State0) { machine in
        
    // add 0 => 1 => 2
    machine.addRouteChain(.State0 => .State1 => .State2) { context in
        invokeCount++
        return
    }
        
}   
        
// tryState 0 => 1 => 2
machine <- .State1
machine <- .State2
        
XCTAssertEqual(invokeCount, 1, "Handler should be performed.")

addRouteChainは、指定された遷移通りに状態が遷移した時に一度だけCallbackを呼び出す、ということが理解できますね。

そんなところで、我々はコードを読み書きしているわけで、コードの解説記事を読むくらいだったら、コードを説明しているコードを読んだ方が早いケースもそれなりにあるかな、と。まあ後は、気軽に 作者に聞いちゃう、ということで、よろしくお願いいたします。

草々