スキーマ駆動開発、はじめました

f:id:kuracux:20210830125237p:plain

目次

  • はじめに
  • スキーマ駆動開発とは
  • 導入背景
    • 課題
    • 実現したい状態
  • スキーマ定義
  • ドキュメントの閲覧
  • バックエンド
    • APIのテストに利用
  • フロントエンド
    • モックサーバとしての利用
  • 導入してどのように変わったか?
  • おわりに

はじめに

スタメンでエンジニアをしている田中です。今回は新規プロジェクトにて導入したスキーマ駆動開発について、その背景や実際にどのように開発に組み込んでいるかをご紹介いたします。

※ 前提: スタメンではバックエンドにRuby on Rails, フロントエンドにTypeScript, Reactを利用しています。

スキーマ駆動開発とは

スキーマ駆動開発とは、「APIのスキーマを最初に定義し、その定義をもとにバックエンド(API)とフロントエンド(画面)の開発を進めること」を指します。

バックエンド・フロントエンドのそれぞれの開発は定義したスキーマをベースに進めていきます。APIのスキーマを最初に定義することによって、両者の間でAPIの仕様のズレを防ぐことができます。また、仕様に変更がある場合はスキーマの定義を修正し、それぞれの開発に反映させていきます。

導入背景

課題

バックエンドとフロントエンドの開発者が別々の場合、APIのリクエストやレスポンスがどのような形式であるかについて、共通の認識を持つ必要があります。スタメンでは初めは社内wikiにて共有をしていましたが、機能が増えてきたことによってドキュメントの数も増えて管理が難しくなったり、 フォーマットが明確ではなかったので書く人によってばらつきがあるという問題がありました。

当初、まずはAPIドキュメントの自動生成およびそれに伴うフォーマットの統一から始めるために、RSpecのRequest SpecからAPIドキュメントを生成する「rspec-openapi」の導入を行いました。

導入記事: RSpec から API ドキュメントを生成する「rspec-openapi」を試してみた

しかし、この方法ではRequest Specを作成しないとドキュメントが生成されないので、バックエンドが先行してRequest Specを記述する必要がありました。そのため、フロントエンド開発者に対しては

  • タスクの着手時期を調整する(Request Spec記述後に着手してもらうようにする)
  • 別途社内wikiにてドキュメントを作って共有する

のどちらかをしなければなりませんでした。

実現したい状態

大きく分けると以下の3つがありました。

  1. 何らかの定義をすることで自動でドキュメントが生成される(手作業でドキュメントを作成しない)
  2. ドキュメントと実装の一致
  3. バックエンドとフロントエンドの開発を並行で進められる

1はRequest Specとrspec-openapiにより実現できていましたが、2はバックエンドのみ、3は実現できておりません。

そこで、今回はこれらの状態の実現するために、スキーマ駆動開発を導入してみました。 以下に、実現するにあたり導入したフォーマットやツール、ライブラリを紹介します。

スキーマ定義

利用するフォーマットとしてはOpenAPI Specification(以降、OpenAPI)となります。OpenAPIはRESTful APIのインターフェースを定義することができ、また、APIを表示するためのドキュメント生成ツール、様々なプログラミング言語でサーバやクライアントを生成するコード生成ツール、テストツールなど、様々なケースで使用することができます。

以下、記述例です。

paths:
  /users:
    post:
      summary: Adds a new user
      requestBody:
        content:
          application/json:
            schema:      # Request body contents
              type: object
              properties:
                id:
                  type: integer
                name:
                  type: string
              example:   # Sample object
                id: 10
                name: Jessica Smith
      responses:
        '200':
          description: OK

OpenAPIはYAML形式で記述できるのですが、上記のような形式を直接編集して定義することはなかなか大変です。そこで、Stoplight StudioというOpenAPIをGUI上で編集することが出来るエディタを利用しています。

f:id:kuracux:20210830125903p:plain

また、ここで定義したスキーマはjsonファイルやyamlファイルとしてエクスポート出来るので、後述するAPIのテストやモックサーバに利用します。

ドキュメントの閲覧

上記に記述したStoplight Studioを利用しています。現状、開発メンバーは利用できるので、編集と閲覧をStoplight Studio上で完結させています。

f:id:kuracux:20210830125950p:plain

バックエンド

APIのテストに利用

committeecommittee-railsというgem、定義したスキーマを利用して、APIのリクエストおよびレスポンスの検証を行うことが出来ます。

設定ファイルに下記を加えます。

include Committee::Rails::Test::Methods

def committee_options
  @committee_options ||= {
    schema_path: Rails.root.join('doc', 'openapi.yaml').to_s,
  }
end

そして、検証したいリクエストまたはレスポンスに対して、assert_request_schema_confirmassert_response_schema_confirm(200)にてチェックすることが出来ます。

describe 'GET /' do
  it 'conform yaml schema' do
    get '/'
    assert_request_schema_confirm # リクエストのチェック
     assert_response_schema_confirm(200) # レスポンスのチェック
   end
end

仮にエラーが発生すると例としてこのようなメッセージが返ってきます。例では型チェックを行なっていますが、他にも必須チェックなど、OpenAPIに定義した内容に沿って確認してくれます。

Committee::InvalidResponse:
#/components/responses/products-list/content/application~1json/schema/properties/data/items/properties/attributes/properties/status expected string, but received Integer: 1

フロントエンド

モックサーバの利用

Stoplight Prismと定義したスキーマを利用し、モックサーバを立てることが出来ます。Stoplight PrismはOpenAPIのスキーマをベースにしたモックサーバを立てるためのパッケージです。スキーマに定義されているリクエストボディのバリデーションやサンプルデータのレスポンスを行うことが出来ます。

Docker Imageも存在するので、Docker環境で立ち上げることも出来ます。 以下、docker-compose.ymlの記述例です。

mock-server:
  image: stoplight/prism:4
  container_name: 'mock-server'
  ports:
    - '3000:10083'
  command: mock -h 0.0.0.0 -p 10083 /doc/openapi.yaml
  volumes:
    - ./doc/openapi.yaml:/doc/openapi.yaml

これによって、APIの開発を待つことなくフロントエンドの開発を進めることが出来るようになります。

導入してどのように変わったか?

冒頭にあげた実現したい状態について、どのように変わったかを説明します。

何らかの定義をすることで自動でドキュメントが生成される(手作業でドキュメントを作成しない)

Stoplight StudioでOpenAPIを定義すると自動的にドキュメントとしても利用ができるようになりました。

ドキュメントと実装の一致

定義したスキーマを利用することでバックエンドではAPIのテストによるチェック、フロントエンドではStoplight Prismのバリデーションやレスポンスによってチェックができています。

バックエンドとフロントエンドの開発を並行で進められる

フロントエンドについてはStoplight Prismのモックサーバを用いた開発により、これまでのバックエンド先行の開発ではなく、並行して開発が進められるようになりました。

スキーマ駆動開発を導入することで実現したい状態をそれぞれ満たすことが出来るようになりました!

しかし、まだ活用できていないこともあります。たとえば、

  • OpenAPI generatorを用いたTypeScriptの型定義
  • Stoplight PrismとCypressを利用したE2Eテストの実現

など、この辺りもまずは試してみて良ければ導入しようと思います。

おわりに

スキーマ駆動開発をはじめるにあたり、その背景や導入したツール・ライブラリを紹介しました。導入して1ヶ月半ほどになりますが、全体の開発効率が良くなった実感があります。

また、実際の導入にあたり、プロジェクト開始前にスキーマ駆動開発の社内向けのドキュメントを作ったり、勉強会を開催したりすることで、プロジェクトに参加するエンジニアにスキーマ駆動開発の進め方やそのメリットを理解してもらい、プロジェクト内で利用するイメージを持ってもらいました。今の所は上手く運用できていますが、メンバーが増えるタイミング等でも参加メンバーが共通の認識が持てるように、今後も運用していきたいと思います。

スタメンでは一緒にプロダクト開発を進めてくれる仲間を募集しています! 興味を持っていただいた方は、是非下記の募集ページをご覧ください。

TUNAG

FANTS