34-API設計の黄金律

プログラマが知るべき97のこと」の34個目のエピソードは、APIの設計におけるユニットテストに関する話です。APIApplication Programming Interface)は文字通りにプログラム(コード)間の境界を定めます。あるフィーチャを実現するプログラムを書くことは難しいケースも簡単なケースもあります。しかし、そのフィーチャを外部に適切に公開すること、すなわちAPIを設計する事は常に難しいものです。
例えば、「カンマ区切りの文字列を分割し、整数として合計を求める」という機能を持つプログラムのAPIを考えてみます。この機能を実現するコードは簡単でしょう。ですが、この機能を満たすAPIを考えるとなると、それほど単純ではありません。一度公開したAPIは簡単には変えられませんし、ユーザの細かい要求を満たすためにクラスの一部をオーバーライドする必要性も考慮すべきです。忘れがちですが、APIにもユーザビリティは必要ですから、同じ機能を同じような品質で実装している2つのプログラムがあれば、使いやすいAPIを選択するはずです。いえ、自分であれば、品質が多少低い程度であれば使いやすいAPIを選択します*1
最近のことですが、API設計の重要さを強く実感しました。Google App Engine/Java用のフレームワークであるSlim3は、非常に高いレベルでAPIが設計されているのです。クライアントからのリクエストを捌く部分はServlet FilterのFrontControllerで行っています。ユーザ(API利用者)は自分のアプリケーションの要件がデフォルトの振る舞いで実現できない場合、このクラスを拡張することで対応します。FrontoControllerはリクエストのパスから実際に処理を行うControllerを生成して処理を委譲する単純な構造ですが、適切にprotectedメソッドに分割されている事でほとんどのカスタマイズはサブクラスでオーバーライドすれば良いのです。これまで1年以上使ってきましたが、「ここを修正したいな」と感じた部分で、単純なオーバーライドで実現できなかったのは1箇所だけでした。

APIを提供するときは、API自身のテストだけではなく、必ずそのAPIを利用するコードのユニットテストも書く」APIの設計者は、これを黄金律にして欲しいと思います。

ユニットテストは行っている前提です。ユニットテスト、特にテスト駆動開発APIを書く最大のメリットの1つはAPI開発者自身がそのAPIの最初のユーザとなることです。テストを書くことで自らAPIを利用するため、APIが使いにくい問題やテストしにくい問題を防止する効果があります。このエピソードでは更に一歩踏み込み、APIを利用するコードを書いてそのテストを書くことを提案しています。
APIユニットテストをする事でAPIの設計は洗練されます。しかし、開発者が最初のユーザになることでユーザ視点も考慮はされています。しかし、それでも開発者がユーザ視点で考慮しているに過ぎません。本物のユーザとして使っているわけではないのです。本物のユーザであれば、APIを使ったコードのユニットテストを書きます。このプロセスを踏むことで、APIを使ったコードの単体テストを書くことが難しい事を再認識できるのです。
これも身近に感じた事がありました。EtupirkaCMSではテンプレートエンジンPirkaEngineを使っています。ところが、実際に本物のユーザとして使っていると、不具合・課題・テストビリティなどが明確に見えてきます。テンプレートエンジンだけをユニットテストしていたのでは気付かなかった点です。テンプレートエンジンはまさにAPIです。それを利用したCMSを作り、そのユニットテストを書きました。これは、結果としてこのエピソードで提唱されている黄金律の適用を体感した事になりました。
API設計はプログラミングスキルの中で最も習得に時間のかかるスキルだと思います。自分もまだまだ未熟なので、たくさんの良いAPI・悪いAPIを読んで・使って、そして作ってスキルアップしたいですね。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

*1:結果としてバージョンアップで品質が向上する可能性も高いだろう