Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
スキーマ駆動開発による品質とスピードの両立 - 私達は何故、スキーマを書くのか
Search
武田 憲太郎
April 17, 2024
Programming
1.5k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
スキーマ駆動開発による品質とスピードの両立 - 私達は何故、スキーマを書くのか
Postman API Night Tokyo 2024 Spring
https://postman.connpass.com/event/309418/
#APINight
武田 憲太郎
April 17, 2024
More Decks by 武田 憲太郎
See All by 武田 憲太郎
LL言語やWebフレームワークのPostgreSQL対応 〜DBの機能がユーザーに届くまで〜
kentaroutakeda
1
150
Laravel Boostに学ぶ、AIにPHPを書かせる技術 〜OSSの実装から蒸留するエージェント制御の王道〜
kentaroutakeda
3
1k
Why Laravel apps break—Mastering the fundamentals to keep them maintainable
kentaroutakeda
1
500
「接続」—パフォーマンスチューニングの最後の一手 〜点と点を結ぶ、その一瞬のために〜
kentaroutakeda
6
3.1k
PHP 8.4の新機能「プロパティフック」から学ぶオブジェクト指向設計とリスコフの置換原則
kentaroutakeda
2
2.2k
php-src is waitingfor your contribution or: How to Level Up Your PHP Skills with php-src
kentaroutakeda
0
110
REST API設計の実践 – ベストプラクティスとその落とし穴
kentaroutakeda
4
2.2k
Inertia.jsのサーバサイド実装から学ぶ依存逆転原則の応用
kentaroutakeda
1
250
私の愛したLaravel 〜レールを超えたその先へ〜
kentaroutakeda
13
6.6k
Other Decks in Programming
See All in Programming
テストを司るデーモンに会いに行く 〜隔離した仮想マシンでテストを通すまで〜
h1d3mun3
1
440
iOSDC2026登壇資料.pdf
riofujimon
0
170
速く作れる。その次は、速く確かめられる開発へ 〜AIネイティブ開発を支える、Shift Down〜 / Can build fast. Next, moving to development where we can verify fast.
rkaga
5
3.2k
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
130
技術的負債の返済は、AI時代の複利で効く投資 — 経営としての意思決定とその遂行
curekoshimizu
0
1.5k
Jetpack Compose メカニズム
skydoves
0
440
C#の現在地 進化の歴史と、AI時代の.NET Everywhere
neuecc
4
2.2k
フロントエンドUIフレームワークのこれまでとこれから
ssssota
5
2.8k
手動確認はもう限界 〜XCUITestでCustom URL Schemeの遷移を起動種別ごとに自動テストする〜 / Testing Custom URL Schemes with XCUITest
otouto
0
300
From 6 People Classroom Meetup to 100 People Regional Conference / FOSS4G Hiroshima 2026
furukawayasuto
0
210
iOSDC Japan 2026 - Swiftで作って学ぼう!データベース自作入門
kaseken
2
170
市販E-Readerを乗っ取れ 〜Embedded Swiftで電子ペーパーガジェットを制御する〜
trickart
0
190
Featured
See All Featured
So, you think you're a good person
axbom
PRO
2
2.2k
The Mindset for Success: Future Career Progression
greggifford
PRO
0
500
How to Ace a Technical Interview
jacobian
281
24k
Music & Morning Musume
bryan
48
7.4k
Designing for Performance
lara
611
70k
Six Lessons from altMBA
skipperchong
29
4.5k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
63
46k
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.4k
How STYLIGHT went responsive
nonsquared
100
6.3k
For a Future-Friendly Web
brad_frost
183
10k
A Modern Web Designer's Workflow
chriscoyier
699
190k
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
3
1.2k
Transcript
スキーマ駆動開発による 品質とスピードの両⽴ 私達は何故、スキーマを書くのか 2024/4/18 #APINight
⾃⼰紹介 2024/4/18 #APINight @KentarouTakeda / 武⽥ 憲太郎 Webアプリケーションエンジニア • サーバサイド:
PHP - 2002年頃〜 • 型の扱いが⽐較的緩かった⾔語 • フロントエンド: TypeScript - 2013年頃〜 • 発表当初より厳密な型システムを持っていた⾔語 APIへの型付けや仕様と実装の乖離に、 課題感を持ち続けている。 スキーマ駆動開発による品質とスピードの両⽴ 1
アジェンダ 2024/4/18 #APINight •APIファーストが 解決した課題ともたらした困難 •スキーマ駆動開発による 品質とスピードの両⽴ スキーマ駆動開発による品質とスピードの両⽴ 2
APIファーストが解決した課題ともたらした困難 2024/4/18 #APINight • 仕様書の無い開発 • 仕様書のある開発 • 「仕様書」は依存に値するか? •
仕様書の冗⻑化に過ぎない実装 • 隠蔽されない知識 スキーマ駆動開発による品質とスピードの両⽴ 3
仕様書の無い開発 2024/4/18 #APINight • サーバサイドが出⼒するプロパティ名と フロントエンドのそれとが連動 • フロントエンドのコンポーネントが サーバサイドの実装に依存 //
サーバサイド: UserController.php public function show(User $user): array { return response()->json([ 'name' => $user->name, 'email' => $user->email, 'birthdate' => $user->birthdate ->toIso8601String(), ]); } // フロントエンド: UserComponent.tsx useEffect(() => { axios.get("/api/users/" + id) .then(response => setUser({ name: response.data.name, email: response.data.email, birthdate: new Date(response.data.birthdate), }) }); スキーマ駆動開発による品質とスピードの両⽴ 4
仕様書の無い開発 2024/4/18 #APINight 依存関係 • インターネットを跨いで依存している。 • 担当者を跨いで依存している。 • リポジトリを跨いで依存している。
スキーマ駆動開発による品質とスピードの両⽴ 5
仕様書のある開発 2024/4/18 #APINight SOLID原則: 依存関係逆転の原則 上位のモジュールは下位のモジュールに依存してはならない。どちらの モジュールも「抽象」に依存すべきである。 抽象(仕様書)への依存により詳細(インターネット)を隠蔽 APIファーストはここが出発点 スキーマ駆動開発による品質とスピードの両⽴
6
「仕様書」は依存に値するか? 2024/4/18 #APINight • ⾃然⾔語 • 表現⼒の限界 • 解釈の余地 •
管理 • リビジョン • ブランチ • マージ • 強制⼒ • 仕様と実装の乖離 スキーマ駆動開発による品質とスピードの両⽴ 7
仕様書の冗⻑化に過ぎない実装 2024/4/18 #APINight <label for="email">メールアドレス</label> <input type="email" name="email" id="email" maxlength="128">
<label for="password">パスワード</label> <input type="password" name="password" id="password" maxlength="32"> <label for="name">名前</label> <input type="text" name="name" id="name" maxlength="20"> <label for="birthdate">生年月日</label> <input type="date" name="birthdate" id="birthdate"> <!-- 省略 --> スキーマ駆動開発による品質とスピードの両⽴ 8
仕様書の冗⻑化に過ぎない実装 2024/4/18 #APINight スキーマ駆動開発による品質とスピードの両⽴ 9 axios.post("/api/users", { email: form.email, password:
form.password, name: form.name, birthdate: form.birthdate, // 省略 }).then(response => { // 省略: レスポンスを描画 });
仕様書の冗⻑化に過ぎない実装 2024/4/18 #APINight class CreateUserRequest extends FormRequest { public function
rules(): array { return [ 'email' => [ 'required', 'email', 'max:128' ], 'password' => [ 'required', 'string', 'max:32' ], 'name' => [ 'required', 'string', 'max:20' ], 'birthdate' => [ 'nullable', 'date' ], 'organizations' => [ 'required', 'array' ], 'organizations.*' => [ 'string' ], ]; } } スキーマ駆動開発による品質とスピードの両⽴ 10
仕様書の冗⻑化に過ぎない実装 2024/4/18 #APINight 仕様書と全く同じ内容を 別の書き⽅に書き直しているに過ぎない • ⾔語もコードベースも異なるため、再利⽤が効かない。 • ⼿作業にによるコードのため、ミスのリスクが付きまとう。 単純作業に割かれる多くの時間
スキーマ駆動開発による品質とスピードの両⽴ 11
隠蔽されない知識 2024/4/18 #APINight API仕様書に準拠した実装 • ⽬的: IDを指定しユーザー情 報を取得する。 • ⼿段:
仕様通りに URLを組み ⽴てGETリクエストを送る。 ネットワークの知識が フロントに漏れ出している。 抽象化された実装 • ⽬的: IDを指定しユーザー情 報を取得する。 • ⼿段: IDを指定しユーザー情 報を取得する。 適切な隠蔽が ⽬的と⼿段を⼀致させる。 // GET /api/users/{id} const users = await axios .get('/api/users/' + id); // UserApiクラスのメソッド呼び出し const user = await userApi .getUserById(id); スキーマ駆動開発による品質とスピードの両⽴ 12
スキーマ駆動開発による品質とスピードの両⽴ 2024/4/18 #APINight • ⾼品質で安定したものに依存する • フロントエンド開発 • サーバサイドでのスキーマ管理と統合 •
TDDとスキーマ駆動開発 • スキーマの破壊的変更 • エラー原因の提供 • リリース後の品質向上 スキーマ駆動開発による品質とスピードの両⽴ 13
⾼品質で安定したものに依存する 2024/4/18 #APINight プリミティブな値は Json Schemaで表現可能 • 数値 { "type":
"number" } • 整数 { "type": "integer" } • ⾃然数 { "type": "integer", "minimum": 1 } • non-empty-array<string> { "type": "array": "items": { "type": "string" }, minItems: 1 } プリミティブなドメインは OpenAPI Specificationで表現可能 • ⽂字列・UI上はマスクを推奨・8⽂字以上 { "type": "string", "format": "password", "minLength": 8 } • ⽇時・ISO8601形式の⽂字列 { "type": "string", "format": "date-time" } • URL⽂字列 { "type": "string", "format": "uri" } 「解釈の余地」が問題を招く → インターフェース記述⾔語による厳密化 スキーマ駆動開発による品質とスピードの両⽴ 14
⾼品質で安定したものに依存する 2024/4/18 #APINight インターフェース記述⾔語の導⼊により: • 間違いが機械的に指摘される。 • 補完(エディタ・IDE) • Lint
/ 静的解析 • Spectral • IBM OpenAPI Validator • 実⾏時検査 • 履歴が残る。 • Git ⼈間の判断は間違える → マシンリーダブルな⾔語で判断を⾃動化 スキーマ駆動開発による品質とスピードの両⽴ 15
⾼品質で安定したものに依存する 2024/4/18 #APINight 安定したインターフェース記述⾔語へ依存することで、 秩序を強制し、品質を向上させる、開発⼿法 •強制が、メリットでありデメリット。 •強制のコントロールが、開発の成否を決める。 スキーマ駆動開発による品質とスピードの両⽴ 16 「スキーマ駆動開発」とは
⾼品質で安定したものに依存する 2024/4/18 #APINight OpenAPIドキュメントそれ⾃体に強制⼒は無い。 実⽤的に使うには、これと同じ強制が必要。 class User implements Authenticatable {
} // Fatal error: // Class UserModel contains 6 abstract methods and must therefore be declared ... スキーマ駆動開発による品質とスピードの両⽴ 17
⾼品質で安定したものに依存する 2024/4/18 #APINight • コード⾃動⽣成: OpenAPI Generator • 仕様に準拠(=正しく依存)したライブラリが⾃動⽣成される •
「ビルドが通れば問題なし」と判断できる • バリデーション⾃動化 - OpenAPI PSR-7 Message Validator • ドキュメント: Redocly • ⼿動テスト: Swagger UI • APIテスト: runn • プラットフォーム: Integrate Postman with OpenAPI • ドキュメント /⼿動テスト / APIテスト / バリデーション⾃動化 • デリバリー / 監視 スキーマ駆動開発による品質とスピードの両⽴ 18
⾼品質で安定したものに依存する 2024/4/18 #APINight OpenAPIによるスキーマ駆動開発 多くの⽤途への正しい転⽤がポイント スキーマ駆動開発による品質とスピードの両⽴ 19
フロントエンド開発 2024/4/18 #APINight スキーマ駆動開発による品質とスピードの両⽴ 20 OpenAPI Generatorによる⾃動⽣成ライブラリは: • tagがクライアントライブラリのクラスに変換される。 •
operationIdが各クラスのメソッドに変換される。 • schemaが各⾔語の型定義やクラスに変換される。 • enumが各⾔語のenumや定数に変換される。 • リクエストレスポンスへの型付けが⾏われる。 • descriptionやsummaryが各⾔語のDocBlockに反映される。 • deprecatedなどのメタデータもDocBlockに反映される。 • date-timeが各⾔語の⽇時型と透過的に変換される。 以上の機能を持つ。
フロントエンド開発 2024/4/18 #APINight スキーマ駆動開発による品質とスピードの両⽴ 21 • 型安全 • エディタ補完・ホバーヒント •
静的解析・コンパイルチェック • 抽象化 • URLやHTTPメソッドを隠蔽したAPIクライアント // UserApiクラスのメソッド呼び出し const user = await userApi .getUserById(id); // メソッド補完
サーバサイドでのスキーマ管理と統合 2024/4/18 #APINight • デメリット • サーバサイド(APIサーバ)のコードに責務が集中する • メリット •
API仕様はサーバサイドの担当者が書くことが多い • URL(ルーティング)はサーバサイドに実装される • 型(バリデーション)はサーバサイドに実装される • 仕様と実装とを⼀致させやすい • 他の⽅法にいつでも移⾏できる スキーマ駆動開発による品質とスピードの両⽴ 22
サーバサイドでのスキーマ管理と統合 2024/4/18 #APINight • 仕様をアノテーションで宣⾔。すぐ下に実装。 • レスポンスの型定義(仕様)と⽣成(実装)とを紐づけ。 ここでの定義はOpenAPIドキュメントとしていつでも出⼒可能 #[OA¥Schema( title:
'User', properties: [ new OA¥Property(property: 'name', type: 'string'), new OA¥Property(property: 'email', type: 'string', format: 'email'), new OA¥Property(property: 'birthdate', type: 'string', format: 'date-time'), ], required: ['name', 'email', 'birthdate'], )] class UserResource extends JsonResource { public function toArray(Request $request): array { return [ 'name' => $this->resource->name, 'email' => $this->resource->email, 'birthdate' => $this->resource->birthdate->toIso8601String(), ]; } } スキーマ駆動開発による品質とスピードの両⽴ 23 仕様 実装
サーバサイドでのスキーマ管理と統合 2024/4/18 #APINight スキーマ駆動開発による品質とスピードの両⽴ 24 • 全てのリクエストレスポ ンスに強制的に介⼊ • OpenAPIドキュメントに
基づきバリデーション • 400 Bad Request • 500 Internal Server Error • 成功時のみ200 OK • 200 OK時の仕様準拠を 保証
TDDとスキーマ駆動開発 2024/4/18 #APINight スキーマ駆動開発による品質とスピードの両⽴ 25 • Red: • 失敗するテストを書く •
テストは失敗する • Green: • テストに通るコードを書く • テストは成功する • Refactor: • テスト成功を維持しつつリファクタ リング • Schema: • スキーマを先に書く • リクエストは失敗する • Code: • 仕様準拠したコードを書く • リクエストは成功する • Refactor: • リクエスト成功を維持しつつリファ クタリング リクエストレスポンスのテストを1本書けば Red / Green / Refactor が回る。
TDDとスキーマ駆動開発 2024/4/18 #APINight スキーマ駆動開発による品質とスピードの両⽴ 26 コードファースト • 迅速なプロトタイピング • 柔軟性
APIファースト • 設計品質 • DX向上 スキーマ駆動 • イテレーティブ • 仕様と実装の同期
スキーマの破壊的変更 2024/4/18 #APINight スキーマ駆動開発による品質とスピードの両⽴ 27 破壊的変更の発⽣条件 • リクエストの型を狭める • レスポンスの型を広げる
• 型を変更する SOLID原則: リスコフの置換原則への違反 • 事前条件を、派⽣型で強めることはできない。 • 事後条件を、派⽣型で弱めることはできない。 破壊的変更の条件を予め知っておくことで 発⽣の際の対応も容易に
エラー原因の提供 2024/4/18 #APINight •400 Bad Request フロントエンドに不⾜なく理由を 知らせる(レスポンス) •500 Internal
Server Error サーバ再度が容易に理由を知れる ようにする(ログ・レスポンス) { "title": "Response Validation Failed", "status": 500, // エラー位置 "pointer": [ "data", "status" ], // エラー理由 "detail": "Value cannot be null", // オリジナルのレスポンス "originalResponse": { "data": { "id": 42, "status": null, "name": "yokawasa", "content": "APINight" } } } スキーマ駆動開発による品質とスピードの両⽴ 28
エラー原因の提供 2024/4/18 #APINight スキーマ駆動開発による品質とスピードの両⽴ 29 本番リリース後も仕様外レスポンスを追跡 • クラッシュさせずログに残しアラートと連携 • リリース直後など⼗分に安定していないサービス
• 既存サービスへ後からスキーマ駆動開発を導⼊するケース • 開発時と同じようにエラーとする • 堅牢性よりも正当性を優先しなければならないサービス • バリデーションそのものを外す • ⻑期の運⽤を経て⼗分に安定したサービス • スループットが重要なサービス
私達は何故、スキーマを書くのか 30
⽯をどのように積むのかは、君次第だ。 31 © 2023 Hayao Miyazaki/Studio Ghibli
だけど、残念ながら世界には まだまだ良いAPIが少ないんだ THE API-FIRST WORLD Abhinav Asthana / © POSTMAN,
INC.
積みやすい⽯を作るのが、私達の仕事だ。 #APINight