次の方法で共有


{ End Bracket }

完璧な API デザイン

James Waletzky

優れたアプリケーション プログラミング インターフェイス (API) デザインの実現は、それほど難しいことでしょうか。少数の基本メソッドを持つ少数のクラスを寄せ集めるだけで、おしまいにすることができます。

それもいいでしょう。その代わり、他の開発者から悪態をつかれ、自分が作成した API がアンチパターンと呼ばれる事態を覚悟しなければなりません。このような事態はどのようにして回避できるでしょうか。API デザインで完璧を目指すことです。そう、完璧を。

API のデザインは、ユーザー インターフェイスのデザインに似ています。どちらも、アプリケーションのエントリ ポイントであり、ユーザー (または開発者) が最初に対話する対象です。お気に入りの家電器具をその競合製品と共に心に描いてください。筆者のお気に入りは、TiVo デジタル ビデオ レコーダーです。TiVo UI が優れているのはなぜでしょうか。

  • 使い方が簡単
  • 誤用しにくい
  • TiVo は 1 つの機能を適切に実行する
  • 予期しない動作をしない
  • 数年使用しても壊れない
  • 操作/タスクが直感的で、見つけやすい
  • UI に一貫性があり、洗練されていて完璧であるか、それに近い

同じ原則が API デザインにも当てはまります。COM 環境から、筆者のお気に入りの API アンチパターンの 1 つである IOleCommandTarget::Exec を取り上げてみましょう。この API は一般に、数種類のオブジェクト、およびそのオブジェクトが含まれているコンテナが相互にコマンドをディスパッチできるようにするために使用されます。

実装例として、コンテナと通信してメニュー項目とツール バーを変更する COM コントロールがあります。この API は、実装で行われる処理を指示する汎用的な文字列を受け取る、若干厳密に型指定されたバージョンのコマンド インターフェイスです。

次に、IOleCommandTarget::Exec API のシグネチャを示します。

HRESULT Exec( 
  const GUID *pguidCmdGroup,  // Pointer to command group
  DWORD nCmdID,               // Identifier of command to execute
  DWORD nCmdExecOpt,          // Options for executing the command
  VARIANTARG *pvaIn,          // Pointer to input arguments
  VARIANTARG *pvaOut          // Pointer to command output
);

説明した原則に従って、この API を分析してみましょう。

API は直感的で見つけやすいか。この API は、ツール バーを変更するときに開発者が最初に注意を向ける場所ですか。この API に関して仲間の間で継承されている知識がない限り、おそらくそうではありません。MSDN ドキュメントを検索しても、目的を満たせないままに終わるでしょう。

単純か。この API は、汎用的な名前が付いた 5 つのパラメータを受け取ります。各パラメータの使用方法を完全に理解するにはドキュメントが必要です。単純な API は、オブジェクトの名前 (コンテキストを表す) とメソッドの名前だけで意図を明確に示します。

API は厳密に型指定され、誤用しにくいか。いいえ。バリエーションは厳密な型指定ではなく、実行オプションは列挙ではなく汎用的な DWORD です。厳密に型指定されたパラメータは、実行時にではなくコンパイル時にエラーを見つけるのに役立ちます。

API には凝集力があるか。この関数の実装は、通常は 1 つだけではなく多くの処理を行います。ある特定の目的に対して適切に名前が付けられた API (たとえば AddToolbarButton など) は、凝集力がはるかに高くなります。Exec メソッドの実装は、コマンド ID で切り替えられることが多く、この条件に基づいて異なるアクションを持ちます。

API には副作用がないか。確定的なことは言えませんが、API の実装は凝集力が欠けているため、実質的に何でも実行できる可能性があります。

信頼性はあるか。有名なデザイン原理である "インターフェイスに合わせたデザイン" は、オブジェクトのテストを容易にするのに役立ちます。この API は本質的にテスト可能ですが、凝集力に欠けているため、検証が必要なテスト ケースの数が膨大になる可能性があります。信頼性は危ぶまれます。

一貫性はあるか。この API は、HRESULT を返し、GUID を使用して情報のセットを識別するという点で、ある程度の一貫性があります。ただし、オブジェクトのインターフェイスの他の部分がどれほど不適切にデザインされているかを知らないと、一貫性を判断するのは困難です。

IOleCommandTarget::Exec について学習している人は、同僚や書籍からその使用方法を学ぶ必要があります。最も望ましいのは、ドキュメントがなくても使用できる簡単な API ですが、エラー処理などの詳細を理解するにはドキュメントが必要です。

結論として、あなたが作成する API やレビューする API は、TiVo と同じぐらい使いやすいものである必要があります。高い検出可能性、厳密な型指定、および凝集力を備え、副作用がなく、信頼性と一貫性を持つ洗練された API であれば、満足度が高まり、サポート コストが低減されるため、開発者の作業が楽になります。Microsoft .NET Framework の多くのインターフェイスはそれを端的に示す例です。これらすべてのデザインの利点を実現するには、API デザインを考案またはレビューするときに完璧を目指してください。

James Waletzky は、Windows Mobile の Consumer Internet and Developer Experience チームの上級開発責任者です。製品開発チームのリーダーであることに加えて、James はマイクロソフトのエンジニアリング手法の改善にも熱心に取り組んでいます。