10.9K Views
June 18, 23
スライド概要
実装と乖離させないスキーマ駆 動開発フロー / OpenAPI Laravel 編 (非公式)PHP Conference Fukuoka After Hack!! June 25, 2023. v0.0.21 Press Space for next page
自己紹介 katzumiと申します 以下のアカウントで活動しています katzchum k2tzumi katzumi
スキーマ駆動開発のフローってどうやっていますか? 本LTではクライアント(フロントエンド)の実装はさておいて、主にAPI(バックエンド)の実装についてお 話します。
スキーマ駆動開発のフローってどうやっていますか? 本LTではクライアント(フロントエンド)の実装はさておいて、主にAPI(バックエンド)の実装についてお 話します。 ドキュメント(スキーマ定義の仕様書)が先?
スキーマ駆動開発のフローってどうやっていますか? 本LTではクライアント(フロントエンド)の実装はさておいて、主にAPI(バックエンド)の実装についてお 話します。 ドキュメント(スキーマ定義の仕様書)が先? APIの実装(コード)が先?
問題点 スキーマ定義(ドキュメント)と実際の実装(コード)が乖離してしまう
なぜ乖離が発生するのか? ドキュメントが先の場合(コードが先であっても。。)
なぜ乖離が発生するのか? ドキュメントが先の場合(コードが先であっても。。) Open API Spec コード生成 Stub コード 実装 実際のコード
なぜ乖離が発生するのか? ドキュメントが先の場合(コードが先であっても。。) * 変更 コード生成 Open API Spec Stub コード ❌ 変更済みのStubを反映することはできない 実装 実際のコード
なぜ乖離が発生するのか? ドキュメントが先の場合(コードが先であっても。。) コード生成 * 変更 Open API Spec Stub コード 実装 ❌ 変更済みのStubを反映することはできない * ❌ 定義が間違っていても自動反映はされない 変更 実際のコード
なぜ乖離が発生するのか? ドキュメントが先の場合(コードが先であっても。。)
なぜ乖離が発生するのか? ドキュメントが先の場合(コードが先であっても。。)
なぜ乖離が発生するのか? ドキュメントが先の場合(コードが先であっても。。)
つらい、、
なぜ?
スキーマとコードとの距離が離れてしまっている 独立したものになっていて、乖離が発生したことを見落としがち コード生成 Open API Spec Stub コード ココ!! 実装 実際のコード
どうすれば距離が縮まるか?
スキーマ定義をコードに埋め込むという方法
swagger-php のAttributeを使ってスキーマを定義する
Controller
Request
<?php
<?php
use OpenApi\Attributes as OA;
use OpenApi\Attributes as OA;
use Illuminate\Foundation\Http\FormRequest;
#[OA\Info(title: "My First API", version: "0.1")]
class OpenApi {}
class MyController {
}
#[OA\Get(path: '/api/data.json')]
#[OA\Response(response: '200', description: 'The data')]
public function getResource() {
// ...
}
ユーザー生成のリクエ
#[OA\Schema(schema: 'CreateUserRequest', title: '
class CreateUserRequest extends FromRequest
{
use BaseRequestTrait;
ユーザー名
#[OA\Property('username', description: '
',
type: 'string', maxLength: 100,
pattern: '^[a-zA-Z\d]{4,100}', example: 'scott',
nullable: false)]
public string $username;
メールアドレス
#[OA\Property('email', description: '
',
type: 'string', maxLength: 320,
pattern: '^[a-zA-Z0-9_.+-]+@([a-zA-Z0-9][a-zA-Z0-9-]*[a-zAexample: '[email protected]',nullable: false)]
public string $email;
レビューしやすい 視点移動が少なくて済む
絶対スキーマから乖離させないマン Attributeや実際に出力されたスキーマファイルを活用してスキーマとコードを乖離させない仕組み
Attributeの力を引き出してみる!
Arttibuteはコードの一部! ReflectionClassを使ってArttibuteを読み出してゴニョゴニョする
Arttibuteはコードの一部! ReflectionClassを使ってArttibuteを読み出してゴニョゴニョする スキーマファイル 生成 実際のコード Controllerクラス クラス Request Attribute 定義 Attribute クラス Response Attribute 定義 定義
Arttibuteはコードの一部! ReflectionClassを使ってArttibuteを読み出してゴニョゴニョする スキーマファイル 生成 ズレが発生しない 実際のコード Controllerクラス Attribute 定義 自動生成 クラス Request 実行時評価 Validation ルール Attribute 定義 クラス Response Attribute 定義 ファイル Route
Arttibuteはコードの一部! ReflectionClassを使ってArttibuteを読み出してゴニョゴニョする スキーマファイル 生成 ズレが発生しない 実際のコード Controllerクラス Attribute 定義 自動生成 クラス Request 実行時評価 Validation ルール Attribute 定義 クラス Response Attribute 定義 ファイル Route
スキーマ自体も静的解析すべし! OpenAPI Spec Redoc 整形 スキーマファイル swagge-ui 静的解析 生成 表示 spectral swagger-php(L5-Swagger) require 実際のコード Controllerクラス Attribute 定義 自動生成 クラス Request 実行時評価 Validation ルール Attribute 定義 クラス Response Attribute 定義 ファイル Route
リクエスト・レスポンスの正確性を保証させる Controllerテストで laravel-openapi-validator を利用してリクエストとレスポンスを検証 スキーマファイル 生成 自動生成 Controller クラス 実際のコード Routeファイル クラス Request 実行時評価 Validation ルール クラス Response テスト実行 コード テスト(PHPUnit) Test Controller Use laravel-openapi-validator 参照(リクエスト・レスポンスValidation)
より確実にE2Eで検証 APIシナリオテスト( runn )でユースケースを網羅的に検証 スキーマファイル 生成 自動生成 Controller クラス 実際のコード Routeファイル クラス Request 実行時評価 Validation ルール クラス Response テスト実行 API Testコード シナリオテスト(runn) 参照(リクエスト・レスポンスValidation)
まとめ
スキーマ≠ドキュメント スキーマはコードの一部。ドキュメンテーションツールからSpecを自動生成
スキーマをいつ書くか? コードを書いたら勝手にスキーマ定義がいい感じに出力されている状態
スキーマ自体もテストが必要 静的解析して最低限の品質を確保 テストでの検証にも利用してスキーマを含んだAPI自体の品質も向上させる
参考URL 実装と乖離させないスキーマ駆動開発フロー / OpenAPI Laravel編 https://zenn.dev/katzumi/articles/schema-driven-development-flow swagger-php https://github.com/zircote/swagger-php spectral https://github.com/stoplightio/spectral laravel-openapi-validator https://github.com/kirschbaum-development/laravel-openapi-validator runn https://github.com/k1LoW/runn
ご清聴ありがとうございます