OpenAPI Specificationを読んでみた

# はじめましての自分語り
はじめまして、U1(仮)です。私は20代から40代にかけて、光ディスクドライブ制御という極めてニッチな組み込みソフトウェアに全仕事エネルギーを注ぎ込んできました。

今から見ればとても非力なDSPで、毎秒20万のタイマ割り込みによるフィルタ演算を行います。当然のごとくアセンブラ言語直書きで、命令のサイクル数を数えながらDSP性能を文字通り限界まで使って職人芸のような実装していました。とっても楽しかったです。

ご想像の通り、次のキャリアに技術ドメイン知識はほぼ役に立ちませんでした。焦りもありましたが、会社のニーズと自分のやりたいことを棚卸した結果、今はソフトウェア品質に管理職として関わらせていただいております。

# OpenAPIとの関わり
私が現役エンジニアだったころから時代は進み、クラウドでのサービス開発に品質面で関わるようになりました。社内の開発チームでどんな仕様書書いているか共有してもらった際、「SwaggerでAPI仕様書書いています」みたいな話があり、「なるほど、Swaggerね、ふむふむ」などとコメントしたものの、ベースの知識が全くなく、こりゃ勉強しなきゃならんと調べ始めたというところです。
そんなわけで、若干加齢臭が隠し切れない記事になると思いますが、優しい気持ちをお持ちの方はお付き合いください。

# この記事の方針
1次情報をしっかり読む。とことん読む。そのうえで分からないところは2次情報（ブログとか）に頼る。
この記事は全訳ではなく、自分が理解したことをなるべく自分の言葉で書いたもの。勉強の過程を残すことが目的です。（誤解があれば優しい人からFBもらえるかも、という期待もあります。）

# 今回の敵
OpenAPI Specification Version 3.0.3
https://swagger.io/specification/

## 全体構成

#### Introduction
 OpenAPIの定義が書いてある。まず最初に理解すべき内容。
#### Definitions
 出てくる用語の定義。
#### Specification
 本文。めっちゃ長い（個人の感想）
#### RevisionHistory
 全部読んだ後に歴史を紐解くのに使いたい。


## OpenAPIとは (Introduction)
 
OpenAPI specification(OAS)は、RESTfulなAPIへの標準的で言語に依存しないinterfaceを、人間にもコンピュータにもわかるように定義します。

OASで定義したinterfaceを見れば、ソースコードや他の文書をみたり、ましてやnework trafficの分析なんかしなくてもサービスのcapability（機能・性能）がわかります。
OASに沿って適切に定義されたサービスに対し、利用者は最小限のロジック実装で連携できます。

OpenAPIで定義した内容は、文書作成ツールでAPIを表示したり、コード生成ツールで様々な言語によってサーバ・クライアントを構築したり、テストツールを使ったり、いろんなユースケースに活用できます。

## 定義 (definition)

#### Open API document
APIを定義もしくは説明する文書。定義はOpenAPI Specificationに準ずる。

#### Path Templating
テンプレートの表現方法。URL pathのうち、パラメータで交換可能な部分を中括弧{}で表す。

テンプレート表現はPath Itemに含まれるパスパラメータそのものと/またはPath ItemのOperationsに含まれるパスパラメータに対応しなくてはならない(Must)。
(Path ItemとOperationsがわからないが、先に読み進む）

#### Media Types
Media typeの定義はいろいろなリソースにあるが、[RFC6838](https://tools.ietf.org/html/rfc6838)に沿ってなされるべき(should)

Media typeの例として、text/plan とか　jsonとか、githubで定義されているものとかが挙げられている。

#### HTTP Status Codes

[RFC7231](https://tools.ietf.org/html/rfc7231#section-6)に定義されている。また、[IANA Status Code Registry](https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml)で登録されたstatus codeが調べられる。

## Specification

### Versions

OPEN API Specificationそのもののバージョン番号のつけ方は、[Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html) (semver)を使う。
major.minorはOASの機能セットを示す。.patchは誤記修正で、ツール群は.patchの違いを区別するべきではない(SHOULD NOT)。

Minorバージョンを上げる際は、後方互換性の確保がMust。例えば、有効なOpenAPI 3.0.2ドキュメントはopenapiプロパティを3.1.0に変更するだけで有効なOpenAPI 3.1.0ドキュメントとなり、同じ意味になるべきです。
(マイナーバージョンで省略可能な仕様が追加されることはOKだが、Mustな仕様が追加されたり、変更されたりする場合はメジャーバージョンを上げる必要があるのだな）

### Format

OpenAPI Specificationに準ずるOpenAPI documentはJSONオブジェクトで、JSONもしくはYAMLフォーマットで表現される。
すべてのField名は指定がない場合case sensitive(大文字小文字の区別あり）。

スキーマはFixed fields(宣言した名前がついている）とPatterned fields（field名に対して正規表現パターンが宣言されてる）の2種類のfieldを公開する。

Patterned filedはそれがもつオブジェクト内に固有の名前を持たなければならない（MUST)
（Patterned filedに含まれるオブジェクトは固有名が必要、という意味として理解。すなわち、Patterned filedに含まれるオブジェクトがpatterned fieldで定義された名前を持つことは不可、ということと思った。）

### Document Structure

OPEN API documentは一つのドキュメントで完結してもよいが、複数のドキュメントに分けることもできる。後者の場合、$ref fieldsを使って参照先を示すことは必須。

ルートの文書は openapi.jsonかopenapi.yamlという名前にするのを推奨。

### Data Types

Primitive data tipes は[JSON Schema Specification Wright Draft 00](https://tools.ietf.org/html/draft-wright-json-schema-00#section-4.2)に従う。
integerとかnubmer,stringとか。
format propetyには任意の文字列を書いてよい。ツールはformatに書かれた文字列を理解できなかった場合、指定されなかった時と同じ動きをするかもしれない。

### Rich Text Formatting

description fieldは　CommonMarkdownFormattingをサポートする。OpenAPIのツールは最低でも [CommonMark 0.27](https://spec.commonmark.org/0.27/)をサポートしなくてはいけない。セキュリティ対応のため、ツールはCommonMarkdownの機能をいくつか無視することがあるかもしれない。

### Relative References in URLs

特に指定がない場合、URLは相対参照。[RFC3986](https://tools.ietf.org/html/rfc3986#section-4.2)の定義に従う。
Sever objectをBase URIとして、相対参照は解決される（絶対参照にできる）。

### Schema
ここからスキーマの定義。計30個のobjectが定義されている。
REQUIRED,MUST,SHALLの記載がない場合、optionalとする。

#### OpenAPI object

Open API documentのroot document object。
openapiのバージョン、APIのmetadata、BaseURIとなるservers, APIで利用可能なpathとoperation、components(API定義の再利用な能なスキーマを持つオブジェクト）、security, tags, externalDocs。

#### Info Object
APIのメタデータを表現するのに使う。

#### Contact Object
 Contact先情報
#### License Object
 ライセンス情報
#### Server Object
 サーバ情報。APIのBaseURI。
 (複数記載できる。例にdevelopment server, Staging server, Production Serverなど書かれているが、descriptionを見て、利用者側で判断するということか。)
#### variables
 servers URLテンプレート内のサーバ変数を表すオブジェクト。default値は必須。

#### Components Object

再利用可能なオブジェクト定義。ここで定義しただけではAPIに影響しない。compoments objectの外から明示的に参照されてはじめて、APIに反映される。

#### Paths Object

endpointとoperationに対する相対パスを持つ。Server ObjectからURLを加えてfull URLとなる。

#### Path Item Object
単独パスで実行可能なoparationを表す。
get/put/post/delete/options/head/patchなどのOperation Objectとパラメータを持つ代替えサーバなどの要素を持つ。
固定フィールド。

#### Operation Object
API operationを表す。
#### External Documentation Object
外部リソースへのリンク
#### Parameter Object
一つのoperationのパラメータを記述する。
nameとlocationの2つの情報から特定される。

#### Request Body Object
Request bodyを記述する。

(ここで力尽きたので中略）

## Appendix A: Revision History

Version 1.0 はSwagger specificationとして2011/8/10にリリースされた。
Version 2.0で、OpenAPI Initiativeに寄付された。2015/12/31。

## 理解できたこと、思ったこと。

- JSON formatに沿っている。定義されたobject内のfieldのtypeで指定されたobjectがspecification内でさらに定義されるという構造になっている。
- Specificationだけあって、網羅的に書かれているが、内容を理解するには当然httpやRESTful API、JSONの知識などが前提。
- ツール群の要求仕様としてもworkするspecificationにするため、ツール側がどう動くべきかに言及している部分があり、興味深い。
- サービスの機能呼び出しと応答に関する情報がすべてJSON/YAMLで定義されているので、確かにOAS documentのみからテストが作れるはず。そうしたツール群についても調査してみたい。
- オールドスクールな私からすると、仕様書は人間言語のあいまいさを必ず含むものだが、OpenAPIでサービスの網羅的な定義をした場合、ツール群が直接理解できる程度にあいまいさを排除する必要があり、実装も一部含んでいるような印象を受けた。（実際には、私の慣れ親しんだ開発フローにおいて、設計フェーズで決めなくてはいけないことを決め切らずに実装フェーズで決めるようなやり方をしていただけのような気もする。）
- ユーザだけでなく、開発側が自分たちの開発やテストツールに直接使える形式でAPI仕様を記載することにより、開発者がメリットをダイレクトに感じられ、しっかりアップデートしていくモチベーションが開発側に生まれやすいのではないかと感じた。
- Semantic versionsなど、関連知識の勉強にもなった。
- Specificationしっかり読まずにいきなり文書作成ツールを使うエンジニアもいそうだが、仕組み自体をしっかり理解しないと、きっとすぐ壁にぶち当たるのではないか。

## 理解できなかったこと、限界を感じたこと。

- HTTPの知識不足により、正直に言ってobjectの詳細が理解できていない。おそらく実際に動かしながら学ぶもの。
- エンジニアとして実装経験踏まないと、これ以上理解するのは効率よくできないかも。