スキーマ駆動開発とは
https://www.arsaga.jp/news/dx-technical-glossary/%E3%82%B9%E3%82%AD%E3%83%BC%E3%83%9E%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA/#:~:text=%E3%82%B9%E3%82%AD%E3%83%BC%E3%83%9E%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA%E3%81%A8%E3%81%AF,%E3%81%AA%E3%81%A9%E3%81%8C%E5%AD%98%E5%9C%A8%E3%81%97%E3%81%BE%E3%81%99%E3%80%82
システム開発において複数のシステムを結合する際に共通となる標準的なスキーマを用いてインターフェースを設計し開発を進める手法の一つです。
WebAPIの定義記述においてはOpenAPI、プロトコルとしてGraphQL, gRPCなどが存在します。
ということで、ざっくりお伝えするとWebAPIのパラメータ部分を先に設計して、それに合わせてビジネスロジックを作り込んでいく手法・・・と、中の人は理解しています。
今回はGo + Echo + OpenAPIを利用してスキーマ駆動開発を実践しようと思います。
エディタのセットアップ
OpenAPIに準拠した仕様書をYAMLで記述するためにVS Codeに拡張機能をインストールします。
今回は「OpenAPI (Swagger) Editor」を利用しました。
これで、VS Code上でプレビューしつつ仕様書を書くことが出来ます。
(下画像赤枠でプレビューが表示できます)
スキーマ定義書の作成
エディタの設定が終わったので、実際に定義を作成します。
今回はシンプルに名前とE-Mailを受け取るだけのWebAPIとしました。
openapi: 3.0.0
info:
version: 1.0.0
title: RIDE-Content
description: >-
ユーザー名とE-Mailを受け取り、受け取った値をそのまま返却します。
servers:
- url: 'http://localhost:1232'
description: ローカル環境
paths:
/user:
post:
description: >
ユーザー名とE-Mailを受け取り、その値を返却する
operationId: user
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/UserSampleRequest"
responses:
'200':
description: "登録成功"
content:
application/json:
schema:
$ref: '#/components/schemas/UserSampleResponse'
'400':
description: "リクエストのバリデーションエラー"
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: "内部エラー"
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
schemas:
UserSampleRequest:
type: "object"
required:
- "name"
- "email"
properties:
name:
type: "string"
x-go-type: string
example: "test_name"
description: "ユーザー名"
email:
type: "string"
x-go-type: string
example: "test@mail.com"
description: "パスワード"
UserSampleResponse:
type: "boolean"
x-go-type: bool
example: true
description: "true:処理成功、false:処理失敗"
Error:
type: "object"
properties:
error:
type: "string"
example: "ここにエラーメッセージが設定されます"
description: "エラーメッセージ"
externalDocs:
description: "Find out more about Swagger"
url: "http://swagger.io"
Go + Echoのセットアップ
先程作成したOpenAPIの定義書を元に、WebAPIを作成します。
まずはGO + Echoのプロジェクトを作成します。
プロジェクトのディレクトリに移動し、以下のコマンドでセットアップを行います。
go mod init sdd
go get github.com/labstack/echo/v4
これでEchoのプロジェクトが作成されました。
OpenAPIの定義書からGoのソースを作成する
今回は「oapi-codegen」を利用しました。
Go用のソースコードジェネレータはいくつかありますが、oapi-codegenは「生成するソースが1つのみ」ということで、一番シンプルに扱えそうだったため、今回使用することにしました。
下記コマンドでインストールします。
go install github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen@latest
インストールが終わったら、以下のコマンドでyamlファイルからGoソースを生成します。
先程作成したOpenAPIの定義ファイル(ymlファイル)、パッケージ名、出力されるファイル名を指定します。
oapi-codegen -package sdd openapi.yaml > sdd.gen.go
go mod tidy
oapi-codegenはmain関数は生成しないので、自分で定義する必要があります。
実際にmain関数を作成し、動作を確認してみます。
main関数を作成する
main関数を作成します。
普通のGoプログラムのため、Echoのサンプルに基づいて作成します。
(Echoのサンプルを元に作ったので、ファイル名はserver.goという名前にしました)
package main
import (
"net/http"
"sdd/sdd"
"github.com/labstack/echo/v4"
)
type webapi struct{}
func (w webapi) User(ctx echo.Context) error {
var reqBody sdd.UserSampleRequest
ctx.Bind(&reqBody)
return ctx.JSON(http.StatusOK, reqBody)
}
func main() {
e := echo.New()
api := webapi{}
sdd.RegisterHandlers(e, api)
e.Logger.Fatal(e.Start(":1323"))
}
この時点で、ディレクトリ構成は以下のようになっています。
動作を確認してみる
server.goをVS Codeのデバッグモードで実行し、動作を確認してみます。
WebAPIのエントリポイントと、渡すべきデータはOpenAPIの定義書で定義済みとなりますので、その値を利用します。
POSTMANを利用して、リクエストを実行しました。
送信した値がそのままレスポンスとして帰ってきましたので、動作は大丈夫そうです。
以上です
ということで、ざっくりですがGo + Echoを利用したスキーマ駆動開発の紹介を行いました。
OpenAPIの仕様に基づいた定義を行うことで、設計書とAPIの実装がズレてしまう、ということも防げるかと思います。
自分は今まで個人開発を行うときに設計書は書いていなかったのですが、今後はOpenAPIの定義書をちゃんと作って開発を行っていきたいと思いました。
(API一覧が確認できたり、APIの仕様がまとまっている資料というのは、後々助かる資料になるので)