こんにちは。
弁護士ドットコムのテクニカルアドバイザーの@koriymです。
この記事は 弁護士ドットコム Advent Calendar 2020の10日目の記事です。
昨日はSREの@t2ynkmrさんの「ECSのデプロイ方法を見直して任意のタイミングでコミットハッシュをタグに使ったイメージをデプロイできるようにした」でした。(すごい事してます!)
メディアタイプとALPSプロファイル
この記事では初めにメディアタイプの中でもドメイン固有のメディアタイプに注目します。次にプロファイルリンクを使ってアプリケーションセマンティクスを与える方法や、そのプロファイルを情報設計(インフォメーションアーキテクチャ IA)のツールとして使う事を説明します。
記事を通じてインターネットの初期から存在したWebにセマンティクスを与える(対象とするコンテントの意味をマシンに教える)仕組みを、次世代のAPI開発に応用する方法を考察します。
メディアタイプ
Media Typeは、ファイルやインターネット上で転送されるコンテンツの形式を表現する識別子である。 (wikipediaより)
Content Type1やMIME Type2とも呼ばれますが、現在、Media Typeが正しい呼び方です。
メディアタイプはIANA3 が管理していて、一覧は メディアタイプレジストリにリストされています。
例えば最も有名なメディアタイプに text/html があります。IANAレジストリでは、そのメディアタイプの登録者4 、このメディタイプの利用するアプリケーションは何か5、詳細仕様はhttp://www.w3.org/TR/html で定義されている といったことが分かります。
ドメイン固有のメディアタイプ
application/json
がどんな内容でも扱えるのに対して、application/problem+json
はRFC7807 で定義されたクライアントにエラー情報を伝えるためのメディアタイプです。HTTPのエラーコード以上の情報をJSONオブジェクトで伝えることができます。標準を使えば、各社各サービスでエラーを発明する必要はありません。多くのメディアタイプは拡張性があり、アプリケーション固有のエラー情報も既存のメディアタイプに付加できます。
text/html
やapplication/json
はあらゆる事に関し記述する事ができるジェネリックメディアタイプです。それに対してapplication/problem+json
のように、特定ドメインの利用のみに使うメディアタイプをドメイン固有のメディアタイプと呼びます。
以下はapplication/problem+json
の例です。
HTTP/1.1 400 Bad Request
Content-Type: application/problem+json
{
"type": "https://example.net/validation-error",
"title": "Your request parameters didn't validate.",
"invalid-params": [{
"name": "age",
"reason": "must be a positive integer"
}]
}
上記エラーメッセージのtype
やtitle
は、単に人間が読んで理解できるだけでなくapplication/problem+json
を理解するクライアントにとってはそれが特別な意味を持つ語として扱うことができます。
vendor固有のメディアタイプ
メディアタイプレジストリにはvnd
ツリープリフィックスが特定のvendorのためのメディアタイプもあります。
- application/vnd.google-earth.kml+xml (Google Earth)
- application/vnd.ms-excel (MS Excel)
他にも個人/実験のためのprs
や未登録を表すx
などのツリープリフィックスがあります。
メディアタイプによってリソース表現で表されるセマンティクスを理解でき、使われる言葉と正確な意味を結びつけることができます。アプリケーションがメディアタイプによってコンテンツをどのように取り扱うかを決定することができます。
プロファイル
では私たちが作成するアプリケーションやAPIも、利用者のためにセマンティクスを定義したメディアタイプを用意すればいいでしょうか? 例えばapplication/vnd.bengo4.lawer-list
のように? 6 もっといい方法があります。それがプロファイル7です。
プロファイルリンクリレーションは既存のメディアタイプにアプリケーションのための追加情報を付与するための仕組みです。例えば既存のメディアタイプtext/html
やapplication/json
に対して、追加のアプリケーションセマンティクス8を指定します。
アプリケーションやAPIで使用する言葉の意味をアプリケーションセマンティクスとして、HTTPリクエスト・レスポンスの振る舞いをプロトコルセマンティクスとして定義するとアプリケーションやAPIのマニュアルになります。
HTTPヘッダーにプロファイルをリンクします。
Content-Type: application/json
Link: <https://dev.twitter.com/docs>; rel="profile"
JSONレスポンスの内容はprofileリンクで表されたURLを見ればその意味や使い方を知ることができます。これはREST制約の4つの統一インターフェイス制約((a) リソースの識別、(b) 表現によるリソースの操作、(c) 自己記述的メッセージ、(d) アプリケーション状態のエンジンとしてのハイパーメディア)の中の1つ、自己記述的メッセージ の特徴です。9
プロファイルのフォーマットに規定はなく、人間がそのアプリケーションのアプリケーションセマンティクスとプロトコルセマンティクスを理解することができればOKです。HTMLやMD、あるいはプレーンテキストで記述してあっても構いません。
ALPS
プロファイルを特定フォーマットで記述して人間にも読む事ができるだけでなく、マシンにも解析可能なものにしようとするのがALPS (Application-Level Profile Semantics)です。
ALPSフォーマットは、解決策ではなく問題を記述することに集中できるように設計されています。URLやステータスコード、HTTPメソッドのようなものはドキュメントの一部ではありません。その代わりに、アクション(read, write, submit, approve など)やデータのプロパティ(familyName, givenName など)が含まれています。
userName
を説明する「userNameはユーザーの名前です」という自然言語の文章の意味をマシンが理解することはできませんが、userName
というのが何か特別な意味のある語で、それがUser
リソースに含まれ、user-registration
アクションを行うときに必要な語であるということは定義することができます。
セマンティクス
アプリケーションで使う語を定義するのはALPSの重要な役割です。
意味
{"id": "articleBody", "type": "semantic"}
これは ALPSアルプスドキュメントの一部で"articleBody" という語句を定義しています。この段階ではarticleBody
の意味は定義されていません。アプリケーションにはarticleBody
という語があるという事を定義しているだけです。10
意味を記述するのはdoc
を使います。
{"id": "articleBody", "type": "semantic", "doc": {"value": "記事の本文"}}
自然言語で説明するより、もっといいのはボキャブラリサイトにリンクする事です。def
を使います。
{"id": "articleBody", "type": "semantic", "def": "https://schema.org/articleBody"}
schema.orgのarticleBody
にリンクすることで意味を定義しました。このようなボキャブラリのサイトは他にdublincore.org、activity stream があります。
語句を定義した事で、このアプリケーションでarticleBody
を使うときに説明はもう必要ありません。APIの定義で繰り返し同じ文章で説明する必要はなくなります。ボキャブラリのサイトを利用することで表記ゆれもなくなり、文化的によりニュートラルな言葉を使うことができます。11
このarticleBody
など定義した語句をセマンティックディスクリプタ(意味的記述子)と呼びます。ALPSドキュメントはこのセマンティックディスクリプタ定義の集合です。
分類
セマンティックディスクリプタは他のセマンティックディスクリプタを含む事ができます。
{
"id": "BlogPosting", "type": "semantic", "def": "https://schema.org/BlogPosting",
"descriptor": [
{"href": "#articleBody"},
{"href": "#dateCreated"},
],
{"id": "articleBody", "type": "semantic", "def": "https://schema.org/articleBody"},
{"id": "dateCreated", "type": "semantic", "def": "http://schema.org/dateCreated"}
},
上記の例はBlogPosting
ブログ記事がarticleBody
ブログ本文とdateCreated
作成日付を含んでいることを表します。#
を使ってインラインリンクしています。多くの場合、リソース表現(webページやAPI)は特定のセマンティックディスクリプタの集合です。
リンク
リソース間の遷移は以下の3つのタイプのいづれかで表すことができます。
-
safe
リソース状態が変わらない安全な遷移です。HTTPだとGETです。 -
unsafe
リソース状態が変更され冪等性がない遷移です。HTTPではPOSTです。 -
idempotent
リソース状態が変更され冪等性がある遷移です。HTTPではPUTもしくはDELETEです。
以下はBlogPost
への安全な遷移を表しています。遷移先はrt
で示します。
{"id": "goBlogPost", "type": "safe", "rt": "#BlogPost"},
遷移に何かセマンティクスが必要な場合には同じようにdescriptor
で含みます。
{"id": "goBlogPost", "type": "safe", "rt": "#BlogPost",
"descriptor": [{"href": "#id"}]
}
これらのディスクリプタの集合を配列として以下のようになフォーマットでまとめるとALPSドキュメントになります。
{
"alps": {
"title": "...",
"doc": {"value": "..."},
"descriptor": [
{"id": "descriptor1", ...},
{"id": "descriptor2", ...},
{"id": "descriptor3", ...}
]
}
}
下記の例もご覧ください。
作成したALPSドキュメントはasd
を使ってアプリケーションステートダイアグラムにしたり、unifiedを使ってOPEN APIなどIDLに変換することができます。
JSONの入力に不安や不満がありますか? JSON Schemaを使った入力は補完もバリデーションも効くのでスムーズです。IntelliJやVS CodeなどJSON Schemaをサポートしたエディタをお使いください。
次のスキーマを設定してALPSドキュメントを始めてください。XMLやYAMLからの変換ツールもあります。
ASD (Application State Diagram)
アプリケーション状態
アプリケーション状態とは、クライアントとサーバーのやりとりでクライアントがどこに位置しているかという状態です。例えばECサイトでは商品を見ているのか、注文して支払いにしているのか、といったURLとして反映されるクライアントのリクエスト位置の情報です。サーバーから与えられるリンクによってアプリケーション状態が遷移するのがRESTです。12 13
ダイアグラム
asdツールはALPSドキュメントからアプリケーション状態遷移図を描画します。ダイアグラムはSVGでレンダリングされ、四角で表されたのがアプリケーションステート、矢印で表されているのがその遷移です。クリックしてその詳細を見る事ができます。
皆さんはどのようなツールを使ってWebサイトやWebサービスの情報設計を行なっていますか? どのようにアプリケーションが扱うコンテンツの名前を決めたり、意味を定義したり、用語を統一していますか? コンテンツの内包関係や関係性はどうでしょうか。
ALPS + ASD
ALPS + ASDはサイトからUIやデザイン要素を除いた状態でアプリケーションの情報スケルトンだけを取り出し視覚化したものです。単純な図ですが、全てのアプリケーションセマンティクスとプロトコルセマンティクスが含まれています。
遷移を含む全ての情報要素にIDが振られたこの図を使い、non-techの人も含めてサイトの情報設計を共有することができます。定義された語句はプロダクトオーナー、サーバーサイドエンジニア、クライアントサイドエンジニア、デザイナーが理解共有するのに役立ちますし、それぞれの言語で共通の語句を利用することができます14。
GUIツールと違い、図もJSONから描画するのでgit管理して履歴や差分を残すことができます。誰がどの語句や繊維をいつ追加したか記録することができます。
ALPSは特定のメディアタイプに囚われない、RESTアプリケーション設計のための問題を記述する言語です。HTTPやOpenAPIといった実装の上位に位置します。この段階ではURLやHTTPステータスコード、スキーマによる制約といった実装のための制約はまだ出現していません。
ドキュメントサイトのデモを試してみてください。
ALPS Unified
設計言語を実装の詳細にブリッジするのがALPS Unifiedです。
ALPS UnifiedはALPSドキュメントを各種IDL (Interface definition language)に変換します。現在サポートしているのはOpenAPI, SDL, Proto3, AsyncAPI, WSDLです。
Amazon CDKをサポートするCDK Alps Spec Rest Apiも開発が続けられています。
弁護士ドットコムでの取り組み
現在、弁護士ドットコムでBUSINESS LAWYERS(ビジネスロイヤーズ)というサービスでALPSを使った情報設計に取り組んでいます。得られたフィードバックは後述するAOOHでALPSコミュニティに伝えALPSプロジェクトにも役立っています。
弁護士ドットコムは継続してきたビジネスとそのソフトウエア基盤がありますが、週に一度のTech Focus Day (TFD)では既存コードのリファクタリングや実験的な事でも可能な新しい取り組みを行なっています。ALPSもTFDで取り組み始めました。
ALPS Open Office Hours (AOOH)
今年の10月からAOOHという1h程度のオンラインミーティングが週一で開催されています。
参加は少人数ですが、主催の@mamundさんは多くの登壇経験や著作のある世界でも最高のAPIコンサルタントの一人です。そういった一流の方とアイデアを出し合い、議論し、プロジェクトを前に進めていくことはエキサイティングです。
私の英語はBad Englishですが、オープンソースにはもっとBad Englishが必要です。 プロジェクトにコントリビューターとして関わりたいと考え、AOOHに参加を続けています。
http://mamund.site44.com/alps/
RWABook
RESTful Web APIs は2013年に発売された本ですが、今日でも本格的なREST API (Hypermedia API)を設計するのに必要な読む価値のある良書です。リソース表現やハイパーメディアなどのWebの基礎技術を改めて紹介した後に、ドメイン固有設計や、コレクションパターン、ハイパーメディア設計を学び、REST APIの設計手法を学びます。付録のAPI Designer's Guide to the Fielding Dissertation (API設計者のためのREST論文)も読み応えがあります。
まずは目次をご覧になってください。
http://restfulwebapis.com/chapters.html
RWABook読書会について
改めて読書会をしようとしたモチベーションになったのが RESTlessnessに打ち勝つ という記事です。"ソフトウェアエンジニア産業は,成熟したRESTエコシステムを基盤として,新たなプロトコルの技術的長所を探求する手段を模索するべき" との意見に共鳴します。
読書会は弁護士ドットコム主催で RESTful WEB APIs読書会として2019年10月から開催しています。当初はオフライン開催で参加者に弁護士ドットコムからお寿司+飲み物を提供していただいていました。現在はオンラインで月1回の開催で、毎回、国内最高のRESTエキスパートの@tkawaさんにご参加いただいています。
本書は英語版しかありませんが、DeepLと@tkawaさんの助けを借り一人で読み進めるよりグッと楽しく進めてるのではないかと思います。
来年もよろしくお願いします
来年最初の1回目はこれまでの総集編を考えています。今までの一年はなんだったのかというくらいきちんとまとめてお話ししたいと考えてますので、ちょっと休んでた方も、初めての方も是非ご参加ください! 予定は運営担当の@TSUCHIYA_Naokiさんや、compassから発表されます。
明日は @happylifetaka さんの記事です。お楽しみに!
参考リンク
-
Content TypeはHTTPヘッダーでのメディアタイプの指定する時に使われます。 ↩
-
MIME TypeはMedia Typeの以前の呼び方 https://www.iana.org/assignments/media-types/media-types.xhtml ↩
-
Internet Assigned Numbers Authority https://www.iana.org ↩
-
ロビン・ベルジョンさん (@robinberjon) W3CでHTML5の仕様策定者。 ↩
-
Webブラウザ、オーサリングツール、サーチエンジン ↩
-
GitHub APIはこれを行っています。https://docs.github.com/en/free-pro-team@latest/rest/overview/api-previews これらのカスタムメディアタイプはIANAに登録されてもいません。 ↩
-
RFC6509 The 'profile' Link Relation Type https://tools.ietf.org/html/rfc6906 ↩
-
アプリケーションで使う語句に意味を明示的に与える事です。 ↩
-
広く誤解されてますが、統一インターフェイス制約はHTTPメソッドとCRUDのマッピングではありません。https://www.infoq.com/jp/articles/subbu-allamaraju-rest/ ↩
-
実際にはtypeのデフォルトはsemanticなのでtype:semanticは省略可能です。 ↩
-
例えばschema.orgではPersonのプロパティにfirstNameではなくgivenNameが使われています。https://schema.org/givenName ↩
-
HTMLのAタグやFORMタグでURLが与えられるHTMLがその典型です。クライアントはURLを組み立てずサーバーから示されたリンクをたどるだけです。 ↩
-
REST制約の中の4つの統一インターフェイス制約の1つ、アプリケーション状態のエンジンとしてのハイパーメディアでもこの用語が使われています。 HATEOAS(Hypermedia as the Engine of Application State)とも呼ばれます。 ↩
-
CSS、API、サーバーサイド言語やJSでの変数、クラス名、メソッド名、DBスキーマなど ↩