あなたがどこに住んでいるかを知っている暴力的なサイコパスが同伴するかのようにコードを書いてください。
みなさんこんにちは!
オンラインホテル予約サービスOstrovok.ruの統合開発チームのチームリーダーとして働いており、今日はさまざまなAPIでの経験を共有したいと思います。
外部プロバイダーと連携するシステムの開発者として、私はしばしばさまざまなAPIに遭遇します-ほとんどの場合、SOAP / RESTまたはそれらに類似したものです。 しかし、それらの多くを扱うことは、技術的なルールや常識のいずれにも導かれずに書かれた印象を残します。まるでグリゴリー・オスターの「悪いアドバイス」の本のように。 この記事では、このようなケースを「悪いアドバイス」のスタイルで説明し、XMLに関連する例を検討します。 コメントや議論を歓迎します。
歴史的背景
SOAP (英語版。SimpleObject Access Protocol-オブジェクトにアクセスするためのシンプルなプロトコル)-分散コンピューティング環境で構造化されたメッセージを交換するためのプロトコル。 SOAPはもともと、リモートプロシージャコール(RPC)の実装を主な目的としていました。 プロトコルは、プロシージャを呼び出すためだけでなく、XML形式の任意のメッセージを交換するために使用されます。
例に渡します
1. xmlをurlに渡す
APIユーザーが最も望むものは何ですか? もちろん、シンプルさ、信頼性、簡潔さ。 そのため、リクエストの本文を読み取らずに、XMLをURLエンコード情報としてリクエストパスのパラメーターとして受け入れます。 より良いことができるもの:
http://exapmple.com/xml/form.jsp?RequestName%3DHotelRequest2%26XML%3D%3C%3Fxml%2Bversion%3D%221.0%22%2Bencoding%3D%22UTF-8%22%3F%3E%0A%3CHotelRequest2%2BBuyerId%3D%22test%22%2BUserId%3D%22test%22%2BPassword%3D%22test%22%2BLanguage%3D%22en%22%2BHotel%3D%22-100%22%2BProductCode%3D%221--%22%2BArrivalDate%3D%2223.12.2018%22%2BDepartureDate%3D%2224.12.2018%22%2BArrivalTime%3D%22%22%2BDepartureTime%3D%22%22%2BCurrency%3D%222%22%2BWhereToPay%3D%223%22%2BNumberOfGuests%3D%220%22%2BNumberOfExtraBedsAdult%3D%220%22%2BNumberOfExtraBedsChild%3D%220%22%2BNumberOfExtraBedsInfant%3D%220%22%2B%2F%3E
すべてがシンプルになり、リクエストから何らかのボディを差し引く必要がなくなります。リクエストにどのような問題があるのかはわかりません。
なぜこれが行われたのかわかりません。 ここでの問題は次のとおりです。多くのサーバーでは、通過できるリクエストパスの長さに制限があります。 XMLのデータ量が多い場合、シナリオの1つとして413 Entity Too Largeエラーが発生する可能性があります。 さらに、送信する前にURLエンコードを行うため、情報量が増加しています。
2.データオブジェクトの過剰なネストによる情報転送
回答の情報をできるだけ難しくする方法を考えてみましょう。 ネストされた構造、さらには異なる形式を使用しましょう! 完了しました-
<Request> <InnerRequest> <RQ>[{"someInfo":"base64Data"}] </RQ> </InnerRequest> </Request>
実際、最上位のxmlは内部に別のxmlであり、内部はjsonであり、データはbase64で表示され、その中にjsonがあり、必要な情報が既に含まれています! 卵に隠されたコシュチェイの死に関するおとぎ話のような素晴らしい解決策。
最も顕著な欠点の1つは、ネストされたすべての構造が渡されるまで応答の解析が遅くなることです。その後、エラーコードがより高いレベルではなくjsonで配線されることが判明する場合があります。 xml / json内のbase64でバイナリデータをエンコードすることは一般的な慣習であると理解していますが、別の形式内で別の形式をエンコードすることはすでに善悪を超えています。
3.要求データに関連せず、データ形式内で無効な情報を追加する
要求本文でXMLが送られてきたと仮定し、XMLを処理して答えを出します。 適切に設計され、負荷の高いシステムには複雑すぎるように見えます。 リクエスト本文でデータ型を送信するようユーザーに義務付けましょう。 これを行う方法は? もちろん、リクエストの本文に含まれています。
XML= <Request> ... </Request>
このような簡単な方法で、XML形式のリクエストを受け取ったことを常に知ることができます。
すでに形成されたリクエストの本文に先頭バイトを追加する必要があり、その後のみリクエストを行うことができることがわかります。 要求データのタイプに応じて先頭バイトを変更する必要がない場合は幸運です。 この場合、httpヘッダーを使用してデータ型を示し、リクエスト本文を変更しないことをお勧めします。
4.必要のないデータの複製
XML応答の構造に非常に重要な情報があるとします。 これをユーザーに表示する方法は? 最も明白な-答えの一部としてそれを数回見せましょう、そして彼は間違いなくそれに注意を払うでしょう。
<Response> <Obj Info="Important"> <ObjSetting Info="Important"/> <Name>SomeName</Name> <Info>Important</Info> </Obj> </Response>
その後、エンドユーザーは間違いなく情報フィールドに注意を払うでしょう。
この場合、私はそれについて考え、APIを提供した会社に、Infoフィールドの意味と、異なるレベルのタグの情報が異なるかどうかを尋ねました。 答えは、いいえ、そうではありません-それらは互いに複製します。 なぜユーザーを誤解させ、これが必要でなければ答えをより難しくするのですか?
5.配列ではなく、同じタイプのパラメーターを個別に渡す
ホテルの検索に使用するAPIの1つに、ゲストの年齢を示すフィールドがあります。 この情報を伝えるのに最適なプレゼンテーション形式は何ですか? 形式は次のようにします。各年齢は個別の必須XMLタグであり、値0はこのパラメーターがないと見なします。
<Request> <Age1>20</Age> <Age2>20</Age> <Age3>0</Age> <Age4>0</Age> </Request>
ここには一度にいくつかの問題があります:非拡張性、冗長な情報、さらに、ゲストが新生児の場合、年齢は本当にゼロになる可能性があります。 この場合、一意の名前のタグではなく、配列を使用する必要があります。
6. API呼び出しチェーンの一部として以前のリクエストからの情報を転送する
APIのセキュリティについて考える時が来ました。 ユーザーが以前の回答から情報を受け取ることをどのように理解しますか? もちろん、彼に答えを送らせてください!
<Request> <RequestInfo/> <PreviosResp> ... </PreviosResp> </Request>
APIの操作を続けるには、APIの前のステップからの外部システムの応答全体を送信する必要があります。APIからの重要なデータは送信せず、この回答に確実に対応するハッシュさえ送信する必要はありません。 すべての栄光の過剰なデータ。
7.エラータグやhttpコードなど、発生したエラーのマーカーを使用しないでください
美しいAPIを作成し、世界に紹介しました。 しかし、何か問題が発生すると、内部エラーのためにユーザーへの応答を作成できませんでした。 この場合の対処方法 エラーコードやその他の情報なしで、データなしで応答テンプレートを提供してください。 理想的なAPIが動作しない場合があることを誰も知らないはずです!
そのような答えの例:
<Response> <ImportantInfo/> </Response>
-応答コード200 OK。
犯した間違いを洗い流すことは非常に悪い習慣です。 問題は、すべてが答えに問題がないかのように見えることです。 <Error>
タグはなく、httpステータスはすべてが正常であることを示しています。 この場合、予期しない結果がシステムで既に発生しないように、受信した情報の追加検証を行う必要があります。
おわりに
SOAP / XMLテクノロジーとAPI設計の操作に関する大量のドキュメントがあるにもかかわらず、多くの問題が依然として関連しており、一部のソリューションは常識に反しています。 この記事で、将来の開発者の数を減らすために、最も成功したアプローチではないことに開発者の注意を引くことができることを願っています。