プロトコルにはメタ情報が必要だと言う話

Table of Contents

こんにちは、殿内(@tonoccho)です

IBM社の製品にWebSphereMQというのがあります。この製品はとにかくログの出方が凄まじく、また、マニュアルにも「こういうのが出たらこうしましょう」ということもよく書かれていました。で、この製品では「理由コード」というのと「完了コード」というのが設定されており、これを見ることで「一体何がどうなったのか」というのがわかるようになっています。

で、このアイデアって普遍的だなと言う話です。

プロトコルって何?メタって何?

この話はtech的なものなので、まずは用語の話です。

プロトコルというのは「処理に参加する当事者の間でやり取りするデータの形式」くらいでいいと思います。

たとえばウェブブラウザとウェブザーサーの間ではHTTPというプロトコルが使われていて、送受信されるデータのどこからどこまでにどんな情報が入っているかと言うのがきっちり消えられています。

次にメタですが、これは情報の情報なんて言われて昔煙に巻かれた気分になっていましたが、その情報が一体何かを説明するものです。

例えば

1234567

という数字があったとします。コレ自体が一体何かはわかりませんが

1234567 (単位:円)

となれば1234567がお金だとわかります。このようにデータに付随してそれがないかを説明するのがメタと思えばいいでしょう。

たまにアニメで「メタ発言」とか言うのと見るんですがこのメタが何かはちょっとわかりません。

なにか帰ってきたけど・・・

REST、RMI、CORBA、SOAPなどなどリモートサーバーに処理をしてもらって値を受け取るという方式はたくさんあるんですけど、その結果って「何?」というのがつきまといます。この「何?」というのは

などなどとにかくいろいろあるわけです。この中には普遍的に必要なものもあれば処理に応じて必要なものもあると思います。ただ、クライアントとしては「受け取ったデータが一体どういうものかを検査しないと次の処理ができない」というのは筋が悪いわけです。

「APIからデータが来た、処理は成功なので表示しよう」

「APIからデータが来たけど処理が失敗しているのでリトライしよう」

「APIからデータが来たけど処理が失敗したしリトライも不可なのでエラーメッセージ出して終わろう」

というのを一発で終わらせられるのが良いわけです。

余計なサーバーリクエストもしないで済むでしょうし。

サーバー側でいくつかのケースが想定できる場合

例えば、サーバーが更に別のサーバーにアクセスするような場合です。そうすると向こうのサーバーが一体どうなったのかなんていうのはクライアントにはわかろうはずもありません。なので「向こうのサーバーがあるならこう、ないならこう」というのをしっかりと戻り値に表現させる必要があります。

例えば顧客リストをRESTで取得する、APIサーバーはSOAPで顧客DBにアクセスして一覧を作成して返す、というようなケースですね。

APIが仮に空っぽのリストをぽんと返してきたとします。その時戻り値にリストしかない場合どう書きますか?

と書くことになると思います。でもクライアントとしてはこれでは困るわけです。顧客が0件ならUIに「まだ顧客が登録されていません」と出したいかもしれないし、SOAPサーバーのエラーなら「サーバーエラーです、しばらくしてからもう一度操作してください」と出したいかもしれません。

更にいうと例えば「プロセスID」でもあれば「このIDに紐づく処理は成功しましたか?」と最悪聞けますが、それすらできないわけです。なので、「データは帰ってきたけどどうなったのかよくわからんなぁ」ということになります。

サーバーからクライアントに指示をだす

こういったメタ情報は別の視点で見ると「サーバーはクライアントにこうしてほしい」ということでもあります。例えば「失敗したけどリトライしてもいいよ」とか「失敗したしリトライもしないでね」とか。

で、クライアントはこういった仕様に対してコーディングをすることになるので、変更にも強くなりそうです。

返す情報が増える分には別に良いけど、変えたり減らしたりするときはどうしよう?ということですね。

さすがに顧客一覧をリストで返していたのが急に文字列になるとかはありえないですがこれはパブリックインターフェースにおける契約の問題でもあるのでここでは触れません。

じゃぁサーバーは何を返すべきか?

世の中にはいろんな優秀なWebAPIがあるのでそれらに習うのも手ですが、かと言ってこれらを全部完全にコピーすると実装が大変です。なので、最低限以下のものがあれば社内システムでは困らないのではと思います。

他にはこういうのがあってもいいと思います。

大事なのは「一つのプロパティにたくさんの意味を載せない」ことです。

例えばリトライの可否については「秒数で返す」としながら「-1のときはリトライ不可という意味」にするのは良くないと思います。リトライ可否をbooleanで持たせて次にリトライ可能な経過秒数を数字で、だったら良いと思います。

また、失敗時のメッセージIDでログを検索したらそれが出ていることも大事です。

まとめ

リモートなAPIでなにか情報をやり取りするときは、クライアントにどういうことかをきちんと知らせるようにしないと筋が悪いと思いました。

技術の最新記事

考えの最新記事