太字は個人的に気に入った文の引用。
はじめに
APIとはなにか
ソフトウェアコンポーネントに対するクライアントの操作方法を定義したもの。
ソフトウェアコンポーネントとは、ある抽象化された問題に対するソリューションを実装したもの。
APIを設計する目的
実装の詳細を完全に隠蔽しながら、コンポーネントの機能に対する論理的なインターフェースを提供すること。アプリケーションを機能、レイヤーごとにコンポーネント化し、それぞれが独立したAPIを備えることで、分業して開発されたものを統合するだけでアプリケーション開発ができる。
APIの構成要素
- ヘッダファイル: クライアントコードにコンパイルさせるインターフェースの集合。
- ライブラリ: APIの機能を実装したスタティック/ダイナミックライブラリ。クライアントアプリケーションはこれらをリンクする。
- ドキュメント: APIの使用に関する概要情報。
API設計の特殊性
アプリケーション開発と違うところ。
- APIは開発者のためのユーザーインターフェースである。使いにくいとユーザーは離れていく。
- APIは複数のアプリケーションで再利用される。APIのエラーはそれを使うすべてのアプリケーションに影響する。
- APIに変更を加えるたびに後方互換性に配慮することが重要。バージョンアップのたびにクライアントコードがコンパイルできなくなったり、動作が変わったりしてはならない。変更のたびにAPIレビューを行い、妥当な変更であることをチェックしなければならない。優れたAPIはクライアントに迷惑をかけずに根本的な変更や改善を行っていける。
- 優れたドキュメントが必要。ユーザーがコードを見て使い方を類推するのでは、適切な使われ方がされない可能性がある。
- 自動テストが必要。APIの正確性は数千人もの開発者とエンドユーザーに影響する。変更するたびにリグレッションテストを行うこと。すべてのリリースが安定していること。
APIの必要性
自分を助けるために。
- 実装を隠すことで、ユーザー(開発者)を混乱させずに変更を加える事ができる。クライアントコードに変更を強いるAPIはユーザーが離れていく。
- アプリケーションの各コンポーネントがAPIの抽象インターフェースのみに依存していれば、モジュール化が促進され、疎結合となり、保守可能性が上がり、製品の寿命が伸びる。
- コードの重複を削除できる。コードの重複はソフトウェア工学における大罪であり、可能な限り撲滅しなければならない。インターフェースの元にロジックをまとめておけば、1箇所の変更ですべてのクライアントコードに影響をあたえることができる。
- ファイル名や各種定数値などをAPI呼び出しでアクセスできれば、ハードコードされた値を撃退できる。
- 実装が隠れているので、リファクタリングや最適化も用意になる。
- 優れたAPIは再利用可能であり、複数のアプリケーションに組み込むことができる。それにより開発サイクルを短縮でき、アプリケーションのコアロジックに専念できる。
- 並行開発が可能になる。自分が作成したAPIを同僚が使って別のプログラムを開発する際に、APIの仕様を予め取り決めておき、ヘッダとスタブ実装のみ提供しておけば、同僚はAPIの完成を待つことなく自身の作業を進められる。
APIを仕様すべきでない場合
サードパーティ製のAPI選定基準。
- ライセンス条項による制約がある場合。商用アプリケーションに対するGPLなど。
- 機能が足りない、プラットフォームのサポートがない場合。
- APIにバグがあるのに、実装ファイルが公開されていないためにバグを追跡できない場合。開発がAPIの問題で律速される。
- ドキュメントがない場合。使用方法が明確でなかったり、特定の条件での動作が不明なAPIや、時間を割いて自分のコードを説明しようとしないエンジニアの仕事は信用できない。
APIの種類
- OSAPI。POSIXだとfork()でWindowsだとCreateProcess()だとか。
- 言語API。C++だとlibcやSTL。システムコールを隠蔽したり、抽象アルゴリズムのセットを提供したり。
- 画像API。libjpeg,libtiffなど。画像ファイルの操作のまとまりを提供する。
- 3DグラフィックスAPI。OpenGL、DirectX。グラフィックカードドライバへのアクセスを抽象化する。
- GUI API。Qt、GTK+など。OSによるGUI APIの差異を吸収する。
ファイル形式とネットワークプロトコル
独自のファイル形式を作成した場合や、クライアント/サーバー間でやり取りされるデータ形式を用意した場合、それとセットでAPIも必ず作成すること。そうすることで仕様の詳細や将来的な変更も集約させて隠蔽できる。
クライアント/サーバーがAPIのみに依存し、通信の詳細が隠されていれば、UDPからTCPへの変更なども容易となる。