API contract とは? サービス間の約束
API contract とは、インターフェースの合意された形と振る舞い、すなわち呼び出し側が依存する endpoint、フィールド、型、エラーケースのことです。
あるサービスやクライアントが別のものを呼び出すとき、呼び出される側のインターフェースが特定の形で振る舞うことに依存します。その期待の集合が API contract です。OpenAPI spec として形式的に書かれることもあれば、利用によって暗黙的になることもありますが、いずれにせよそれを壊すと呼び出し側が壊れます。契約をファーストクラスでテスト可能な artifact として扱うことが、独立したデプロイを安全にします。
契約が対象とするもの
request と response の形、フィールド名と型、必須か任意か、status code、エラー形式、そして idempotency のような振る舞いの保証。consumer が依存するものは、ドキュメント化されているか否かにかかわらず、すべて契約の一部です。
明示的か暗黙的か
明示的な契約は、それに対して検証できる machine-readable な spec です。暗黙的な契約は、たまたま consumer が依存しているものにすぎません。明示的な契約は CI で強制できますが、暗黙的なものは何もチェックしないため偶然に壊れます。
なぜデプロイにとって重要か
- 契約が保たれていれば、consumer と provider は独立してデプロイできる。
- 契約への breaking change は、制御できない呼び出し側を壊しうる。
- 安定した契約こそが、マイクロサービスを本当に独立させる。
- 契約により、チームは合意に対して並行して作業できる。
CI での contract testing
contract test は、provider が consumer の期待を今も満たしていること、そして consumer が実際の契約に対してコードを書いていることを検証します。パイプラインで実行すれば、consumer の本番インシデントではなく、出荷前に breaking change を捕捉します。
breaking change の検出
明示的な spec があれば、CI は提案された契約を現在のものと diff し、breaking change、フィールドの削除や型の厳格化があればビルドを失敗させられます。こうして backward compatibility は、望みを託した code review ではなく自動化された gate になります。
高速な契約の gate
契約の検証と consumer テストは、共有 API へのあらゆる変更ごとに実行されます。高速な runner(Latchkey など)は、これらの絶え間ないチェックがインターフェースに依存するチームを遅らせないようにします。
重要なポイント
- API contract とは、呼び出し側がインターフェースについて依存するすべてである。
- 明示的で machine-readable な契約は CI で強制できるが、暗黙的なものはできない。
- contract testing こそが、provider と consumer が独立してデプロイできるようにする。