翻訳:Microsoftクラウドプラットフォーム用のAPIを開発して学んだこと

Windows Azure APIの開発方法に関する投稿の翻訳にご注目ください。難易度、成功と失敗の決定、結論に達しました。 次は著者のテキストです。



REST API について同僚と話し合った後、Windows Azure Service Management APIを作成したチームを組織し、協力した経験について話すアイデアを得ました。 この記事は、Foursquareの記事やNetflixのDaniel Jacobsの記事など、すばらしい「私が学んだこと」の記事から書かれました。



警告:カットの下で言うことはすべて私の個人的な意見です。 チームの他のメンバーが私に同意するかどうかさえわかりません。 そして、表明された考えのいくつかがかなり矛盾していることを確信しています。



まえがき



Windows Azureサービス管理API(SMAPI)は2008年に作成され、開発者がWindows Azureアカウントを制御できるようにしました-新しいコードの展開、設定の変更、サービスのスケーリング、ストレージの管理など。 ところで、ここにドキュメントがあります 。 特定の番号を指定することはできませんが、APIは開発環境、ユーティリティ、自動化システム、悪意のあるボットなど、毎日さまざまなクライアントからの膨大な数のリクエストを処理したと言えます。 素晴らしいチームとこのAPIに取り組むことができて幸運でした(この機会にZhe、Dipa、Frankに挨拶しましょう!)そして、私たちが作成したものを誇りに思います。



この間に何を学びましたか?



REST URIの命名は重要ではありません...ほとんど



これを言って、私は多くの友人や同僚の怒りを被る危険があります。 APIの作業の最初の段階で、最も「クリーンな」URLデザインを作成するために数週間を費やしました。 私たちは皆、フィールディングの作品を読んでおり、特に白熱した議論の中でこの本を振り回すのは普通でした。 しかし、結局、私は気づきました-私たちはただ時間を無駄にしているだけです。



URI + HTTP動詞+ワイヤの形式は関係ありません




そして、ここに理由があります。 APIを使用する開発者には、HTTPリクエストとレスポンスは表示されません。 少なくとも何らかの形でAPIが成功する場合、プログラミング言語のバインディングが-あなたまたはコミュニティによって作成されます。 もちろん、朝の3時に目を覚まし、記憶からカールリクエストを作成する機能により、バインダーの寿命が少し楽になります。 基本的なRESTイディオム(たとえば、状態を変更するGETリクエスト)を無視すると、開発者は苦労します。 しかし、PUTを使用するかPOSTを使用するかを問わず、2回に1回の会議で議論が行われ、これが数週間続く場合、学術的な議論に時間を浪費していることになります。

証拠? Amazon API(S3ではなく、そこにある他のすべて)を見てください。 これらのAPIはすべて、RPCスタイルで作成された最もgliいXMLモンスターです。 しかし、このAPIの成功を否定することはできませんか?



APIを使用して開始します。



APIの作業中に行った最高のことの1つは、このAPIを使用するコードから始めて、それを見て、RESTインターフェイスを作成したことです。 API自体はまだ存在していなかったため、重要なスクリプト用にさまざまなプログラミング言語で擬似コードを作成しました。 これにより、API仕様を簡単に読んだときに明らかではなかった多くの欠点を回避できました。 たとえば、意味のあるAPI呼び出しの間に開発者にあまりにも多くの中間オブジェクトを作成させようとしていることを発見しました。 また、ユーザーは、APIを介して受け取った構造を、変更することなく送り返すことはできません。 擬似コードを使用した予備検証がなければ、これらの欠点をすべて検出することはできず、それらの欠点ははるかに後で発生し、修正ははるかに高価になります。 さらに悪いことに、そのようなAPIをリリースして、設計の失敗に長時間使用することもできます。

開発者がAPI機能を提供しないというルールを、それらがどのように機能するかを理解するための少なくとも数行の擬似コードがあるコメントに導入しました。 このルールは、開発者が通常のパラメーターと戻り値のリストの代わりに使用例を見ることができるAPI設計会議も改善しました。

APIを作成する悪い方法は、サービス内部へのRESTインターフェースに焦点を合わせています。 結果として得られる「API」は、通常、感謝の気持ちのあるユーザーに対して、彼らが考えていることを聞かないほど高い壁に投げ込まれます(翻訳者のメモは、「壁を越えて」というイデオロギー表現です)。 マイクロソフトや他の企業が作成したこのようなAPIの多くは、開発者を傷つけます。



開発者によく考えさせないでください



APIが公開する「エンティティ」の数を最小限に抑えるようにしてください。 APIが動作する各概念は、開発者の理解を複雑にし、学習曲線に悪影響を及ぼします。 わずかに異なる「エンティティ」を1つにまとめる必要がある場合でも、「エンティティ」の突き出しをカットするという積極的なポリシーを遵守しました。 同様に、各「エンティティ」で利用可能な操作の数を積極的に削減しました。 これにより、最初の設計と比較してAPIが大幅に簡素化されました。



キーアクションをすばやく簡単に



API設計の最終段階で発生した問題の1つは、「N + 1問題」として知られています。 この問題は、子オブジェクトにアクセスするために、まず親オブジェクトからリストを取得する必要があり、次に受信した各オブジェクトに対して個別のHTTP要求を作成する必要がある場合に発生します。 私たちの場合、最も人気のある操作は、Windows Azureサービスを要求し、そのステータスを取得することでした。 すでにリリースの準備をしていたので、APIの設計を変更する時間がありませんでした。そのため、親オブジェクトの「再帰」パラメーターである「巨大な松葉杖」と呼ばれるものを実行しました。 驚いたことに、この松葉杖は非常に効果的で便利なソリューションであることが判明しました-APIのユーザーとサーバーの両方にとって。 もう1つの類似したことは「部分的な回答」であり、現在 GData によってサポートされています。 そのような場合それぞれ、実装は最も成功しませんでしたが、主要な使用シナリオの下でAPIを磨くというアイデアは非常に役立ちました。 私たちのデザインのこれらの「クランチ」が毎日何百万ものAPI呼び出しを節約しても驚かないでしょう。 そして、彼らは私たちのプラットフォームに便利な顧客を迅速に作成できます。

このような結果を達成するための良い方法の1つは、API自体の開発と並行してプロトタイピングクライアントを開発することです。 たとえば、アセンブリの公開用のクライアントバージョン、監視用のクライアント、その他の一般的なシナリオ用のクライアントをサポートしました。 APIを使用するコードの記述を開始すると、新しく作成したAPIがどれほど悪いものになるかは驚くべきことです。 APIデザイナーとして、感謝の気持ちのあるユーザーがAPIにアクセスする前に、これを見るのが最善です。



すべてを測定して記録する



本当にうまくやったのは、測定することでした。 APIにメトリックを取得するよう指示し、結果の数値を非常に注意深く監視しました。 毎日、ユーザーが何をしているか、最も人気のあるAPIコール、最も一般的な間違いなどを把握していました。 これにより、APIが実際にどのように使用されているかがわかりました(たとえば、ハックN + 1が保存した呼び出しの数を言うことができました)。 新しい機能をリリースするとき、私たちはそれがどのように使用されるかを監視し、人生の厳しい真実が意図した使用と異なる場合はすぐに調整しました。 そして、おそらく最も重要なことは、ユーザーが遭遇するエラーを監視し、それらを注意深く調査する機会があったことです。 ユーザーがシステムで作業しているときに何が起こっているかを理解できるように、エラーメッセージを追加または変更しました。 長い間、これらすべてがAPIの使いやすさを改善するのに役立ちました。



バージョン管理と拡張性



APIは変化しており、これらの変化がどうなるかを予測することは困難です。 変更が小さい場合があります-オブジェクトにフィールドを追加するか、要素のリストに別の要素を追加する場合。 他の変更はより複雑です-認証メカニズムを変更するか、古いバージョンのAPIのサポートを停止します。 いずれにせよ、最初からバージョニングの面倒を見るなら、あなた自身に感謝するでしょう。 変更の問題からAPIを保護する方法は多数あります。 独自の方法で行うことができます。クライアントはヘッダーでAPIのサポートされているバージョンを送信し、サーバーはこのバージョンで期待される動作を示します。 別の方法は、RESTメソッドのURLにバージョン番号を追加することです。 いずれにせよ、APIの最初のバージョンに保護方法を追加すると、その後の大きな頭痛から解放されます。



別に、APIの「小さな変更」を考慮してください。 最初からAzure SMAPIを改善できると思います。 たとえば、Foursquare APIは、興味深い方法を使用して間接的に構造を展開します。



{ type: "special", item: { special: { ...specialdata... } } }
      
      







これにより、これらのタイプが予期しない既存のクライアントとの互換性を失うことなく、新しい「タイプ」を追加できます。 Azure APIに対して同様の処理を行わなかったことは残念です。 これにより、小規模な変更が発生した場合に私たちの生活が大幅に簡素化され、バージョン番号を絶えず増やしたり、古い顧客との互換性を壊したりする必要がなくなります。



スリラム・クリシュナン

me@sriramk.com



All Articles