Adways Advent Calendar 2020 15 日目の記事です。
こんにちは、まっちゃんです。
非常に寒い日が続いてますが、非常に熱々な Adways Advent Calendar は最終週を迎えました。
14 日目の記事は ECS の記事でしたね。自分もインフラの方に協力をしてもらいプロダクト新規開発部分で導入しました。(導入後の展開、運用が動けてないですが、現在担当しているプロダクト効率化のプロジェクトでどうにかリプレイスを狙ってます チラッ)ぜひ ECS を導入したい方は見てみてください!
明日 16 日目の記事は SLI/SLO 関連の記事です!SLI/SLO に関しては全く触れていないので内容が楽しみです!
本日 15 日目はタイトルとサムネイルから分かる通り、最近チームに対して OpenAPI を用いたスキーマ駆動開発の導入を行い、開発を進めています。
導入に至る背景や実施したこと、チームの反応などを書いていきます。
ぜひ API 開発がうまくいってないなーって思う方に読んで欲しいです!
先にまとめ
久々のブログということで新規書き起こし & アドベントカレンダーという事で気合が入ってしまい、想定の 2 倍は長くなってしまいましたmm
やったこと、結果を先に載せます。
もっと詳しく読みたい方はぜひ続きを読んでください。
背景: なぜ導入をしたかったのか?
プロダクト開発の課題や、組織の状況がうまくリンクしました。
対応すれば効果があるのではないか?と思いました。
■ プロダクト開発の課題
自身が担当しているサービスでは Scala による Web API 開発と Vue.js によるフロント開発がここ 3~4 年で多くなりました。
現在担当しているプロダクト効率化のプロジェクトもほぼ同じ構成です。
最初の設計はドキュメントツール( Confluence )でリクエストやレスポンスなどの設計を行い、ドキュメントレビューを実施してました。
図: ドキュメントツールで行った Web API の設計(再現)
レビューが通り開発を進めることができます。
ですが以下のような問題が多く発生していました。
- フロントエンド開発時にモック用の API サーバを作成、テストデータなども人力で頑張って作っていた
- JSON ファイルを作って、サーバを起動して確認
- 開発を進める中で API の仕様変更があった場合、変更に対応できない
- バックエンドの命名が変更されたが、バックエンドの担当者のみしか把握をしていない
- バックエンドとフロントエンドを連携させる際に必ず問題が発生
- API の仕様が異なる
- リクエストを受け付けない
- レスポンスの値が無く、出力できない
- キー名が異なる
- キャメルケースやスネークケース
- typo
- API の仕様が異なる
- 問題を解消するためのコミュニケーションコストが高い
- 問題点には挙がるが結局改善までは至ってない、次の開発でも問題が発生
... API 開発あるあるじゃないでしょうか?
どうにかして改善を行いたいものです。
■ 組織の状況
事前に下記の記事を読んでおくと、より内容が理解できます。
言葉の定義 のチーフ(テックリード)やリードチーム、時系列は 2020/05~2020/08 DivOKR、PJOKR の箇所になります。
● チーフ(テックリード)のリードチームの方針
2020 年 3 月頃の自社広告配信サービスを開発・運用する部署の状況です。
マネージャーが組織に対しての DX Criteria のアセスメントを実施しました。
今回の記事にも関連する [システム 05] API駆動開発 ですが、組織として弱いので改善の見込みがあります。
図: 2020/03 時点 DX Criteria [システム 05] API駆動開発 の結果
アセスメントの結果を元に、改善したい箇所をピックアップしてチーフ意見交換会でチーフの方針を確定しました。
アーキテクチャの勉強、大規模案件の振り返り、開発文化の統一などの開発文化やシステム全体に対しての議論を活発に行い、チーフに依存していた改善に大きな影響を与えることを目的としてます。
図:2020/05 ~ 2020/08 チーフの方針(ピックアップして掲載)
はい、ありますね、スキーマ駆動開発が。
図:チーフ意見交換会でスキーマ駆動の勉強を実施
チーフ意見交換会ですが以下の記事に取り組み始めた背景や内容は以下の記事に書いてます。
チーフ同士の意見交換会 の項目です。
● アーキテクチャの勉強
実際に 2020 年 8 月上旬にスキーマ駆動を題材とした勉強と意見交換会を実施しました。
勉強内容はWEB+DB PRESS Vol.108の [効率急上昇!]スキーマ駆動Web API開発 OpenAPI/GraphQLで仕様からコードもテストも作成 の特集です。
特集1
[効率急上昇!]スキーマ駆動Web API開発
OpenAPI/GraphQLで仕様からコードもテストも作成
スキーマを基点にしたWeb API開発の方法を解説する特集です。WebAPIのスキーマは,エンドポイントへのリクエスト方法やそのレスポンスの構造を記述したものです。これを最初に記述することで,ドキュメント/テスト/実装などの作成を効率化できます。第1~2章でスキーマの必要性とREST Web APIのスキーマを記述するOpenAPIの基本を解説し,第3章ではOpenAPIによるスキーマ駆動開発の様子をお見せします。第4章ではGraphQLによるスキーマ駆動開発について説明し,RESTとGraphQLでアーキテクチャスタイルが異なってもスキーマ駆動開発の本質は変わらないことを示します。
WEB+DB PRESS Vol.108
決定事項として 組織でスキーマ駆動開発をやってみる、プロダクト効率化のチームで調査して、組み込めるか判断する事 になりました。
以下、当時の議事録から抜粋して載せます。
(長くなったので詳細が気になる方はクリック・タップして読んでください)
読んだ感想:
フロントとサーバでタスクを分けるからスキーマ駆動開発がマッチしそうだな。 想像以上に色々なオブジェクトがあった。俺の知っているSwaggerではなかった。やばい。 最初の検証は時間がかかりそうだけど、それぞれで理にかなっているな。 定義したスキーマを実装でも利用することで、ドキュメントと実装の乖離問題が解消しそう。 定義したスキーマをテストに活かすことができて良い。 現状XXXシステムでは事前にスキーマ決めてるけど、ツール使って継続的な管理がやれてない感じ。 サーバサイドのOpenAPIの実装はあんまりぴんと来てなかったけど(バリデーションできるっていったってバックエンドでのバリデーション実装するやんけ的な) 読み進めていく中でそこのバリデーション文言が一致するよねとかを差分確認できるみたいなところが旨味(?)っぽかったので あくまでスキーマと比較して正しいことを証明するのがいいみたいなかんじだと認識した 設定ファイルを見た感じエンジニアであればある程度のスキーマ設計についてわかると思った 事前に命名規則やComponentの分割ルールとかは決めて置いた方が良さそう フロント、バックで結合するまでに必ずスキーマを元にチェックしたりするので結合はとても楽そう フロント、バックの各工程でチェックしたりするのでそれをスクラムの完了の定義に使えそう 案外HTTPなリクエスト・レスポンスは考えているようで問題が発生してて、あんまアプローチはできていない そのアプローチとしてのスキーマ駆動開発で構造の定義を行い、開発するのは良さそう いままでコンフルで頑張ってきたり、Paradoxで頑張ってきた、その延長線としてありなのかな? いきなりGraphQLは無い、スキーマ駆動開発の実績が出てきてからだと思う
議論したいこと:
- 1、スキーマ駆動の導入 - スキーマの定義、○○プロダクトだとコンフルで頑張っている、□□プロダクトはParadoxを使っている、メリットを引き出すためにどうスキーマ駆動開発を導入していくか - 開発組織におけるスキーマ駆動の導入メリット。 現状の課題を考慮した上でどんなメリットがありそうか? - 2、GraphQLの活用 - GraphQLは使いたい?使うべき状況(価値がある状況に直面しているか)だと思うか? - GraphQLどこに活用できそう? - 3、ドキュメント - いろんなドキュメントがあると思うけどどこまで必要?何で判断する? (テストコードがドキュメント、paradoxとかでロジックの流れみたいなところを説明する、OpenAPI使ってドキュメント兼実際に動かせるなどなど) - スキーマとドキュメントの扱いはどうしたらいいのか
議論内容(投票が多かった導入について):
1、スキーマ駆動の導入 スキーマ駆動ならば、フロントとバックで別れているものは問題ないかな。 プロダクト新規開発プロジェクトの現状 フロント(express:JSONを作成)とバック(paradox:ドキュメントとしてJSONを書いている)で書く プロダクト効率化プロジェクトもConfluenceにスキーマがある。 Swaggerはどのリポジトリに置くのか。 フロント、バックエンドどっちに置くか?外出しして管理する方が良いだろう。 スキーマ決めるときはペアプロとかで決めて実施する相性はいいかも。 スキーマ駆動をやるとドメインの精度まで担保できるのか? 担保できない。機能Aと機能Bが違うから別物扱いになっちゃう。 理想としては別物扱いではない。 スキーマの定義はリクエストとレスポンスだから、インフラ層でしかない。 現状の課題 - APIの仕様変更をキャッチ出来ない - 開発途中での変更や過去の変更が把握できないこと - 結合テストで変な漏れがある - ドキュメントでの限界 - 実際のAPI化した時のパラメーターや異常値の考慮漏れまではドキュメントでは再現できずに漏れてしまう メリット - スキーマがコード化されることでのAPIの変更を検知 - Swaggerを元にフロントやバックエンドでCIや開発で利用されるため検知が可能 - ドキュメントが更新し忘れたなどが発生しない - API変更をコードとして残せる - CIや開発時に利用しなければメンテナンスできない可能性がある(本番システムで活用されるわけではないので) - テストコードでSwaggerのファイルを利用する - フロントエンドでテスト用APIとして利用する 開発が活発なもので試してみる。 プロダクト効率化プロジェクトでやる。
調査: 実際に導入ができるのか?作ってみることは可能か?
担当していた開発や運用タスクが落ち着いた 2020 年 11 月頃から実際に導入するための調査や提案などに着手しました。
■ どうやって取り組むか
プロダクト効率化プロジェクトの開発チームは技術的な取り組みとして、週に 1 度 "改善棚卸し" を実施しています。
改善リソースもプロジェクトリーダーが PdM やディレクターと合意形成を取り、確実に取れる状態でした。
前々からやりたいです!時間ください!と言い続けていたのですんなりと調査のタスクをスプリントバックログに入れる事ができました。感謝です。
■ どんな事を行ったのか
時間が経っていたので、改めて WEB+DB PRESS Vol.108 を読んだり、チーフ意見交換会の内容を読み返したりしました。
公式 Document や関連する情報を見てた時に Swagger Editor を見つけました。
アクセスするとサンプルが既に記載されているのでイメージもしやすいですね。
図: Swagger Editor
じっくり考えたりするのも良いですが、やっぱり動くものを見せた方がイメージも湧きやすいので実際に作ってみることにしました。
(ちゃんとした作業ログのドキュメントが残っていなかったので、勢いで進めてしまったなと個人的には反省してます)
当時プロダクト効率化のプロジェクトは今まで同様 Confluence にまとめてあったので、それを OpenAPI 仕様で書きました。
ユーザ情報を全て取得する API を想定してサンプルを置いておきます。
./docs/api/openapi.yml
openapi: "3.0.3" info: title: "user" version: "1.0.0" paths: "/api/users": get: responses: "200": description: "ユーザ情報を全て取得する API" content: application/json: schema: type: object items: $ref: "#/components/schemas/Users" example: result: - user_id: 1 user_name: "サンプル1" age: 21 - user_id: 2 user_name: "サンプル2" age: 22 "500": description: "サーバエラー" content: application/json: schema: example: messgae: "サーバーに問題が発生しました。" code: 500 errors: "" components: schemas: Users: type: object required: - user_id - user_name - age properties: user_id: type: integer format: int32 user_name: type: string age: type: integer format: int32
別軸でプロダクト効率化プロジェクトの開発チームに最近ジョインしてくださったシニアエンジニアの方が次の開発のための設計準備を JSON スキーマ仕様でサクッと用意してました。(感謝)
JSON スキーマ仕様のサンプルもあることでよりイメージや説明しやすくなりそうだと感じ、いよいよ開発チームへの提案に臨みます。
提案: プロジェクトチームのエンジニアへの提案
プロダクト効率化プロジェクトの開発チームのもう 1 つの技術的な取り組みとして "技術共有会" と言うものを 2~3 週間に 1 回のペースで行っています。
開発チームのエンジニアやスクラムマスターが発表したい内容や聞きたい内容を 30~60min で発表する場になります。
「提案するならこの場が良い!」 とずっと思っていたので、なんとか順番を後ろの方にしてもらってました。(感謝)
(ちなみにこの "技術共有会" は前所属していたプロダクト新規開発チームの後輩エンジニアがやりたいです!と声を上げて定期的に実施を行っていました。後に自分と新卒エンジニアが今所属しているプロダクト効率化チームへ異動しましたが、新卒エンジニアが後輩エンジニアの想いを引き継いでやりたいです!と声を上げてくれて今のチームでも実施をしています。そんな新卒エンジニアもアドベントカレンダー書いてあるのでひ見てください。なにこれすげーな行動してます。)
(そしてふとチーム内の勉強会を運営していたなーという事も思い出しました。約 2 年前。懐かしい。)
■ 提案した内容
この記事にも書いてある背景やサンプルの内容を中心に説明をしていきました。
やること・やらないこと、どういう風なフェーズを経て導入していきたいかを書いておきます。
やること・やらないこと
## 導入について ### やること - OpenAPIを用いたスキーマ駆動開発 ### やらないこと - GraphQLを用いたスキーマ駆動開発 - 複雑なものを1回で済ませるのみ良さそう、シンプルなAPIではOpenAPIで良さそうと判断
フェーズ分け
## 導入フェーズ分けの案 いきなり全部はやりません、MVP開発同様、小さな単位で行っていきます ### 1. 次の MVP 開発の設計で入れてみる - 設計をOpenAPIの仕様でやりとりできればOK - コミュニケーションコストが下がるのかを確認 ### 2. 開発で活用する - モックの活用 - 変更時のミスが減るか ### 3.(未定だが組み合わせたり) - テストコードでの活用 - CIでの活用
■ 開発チームの反応
チームの反応はぜひやってみよう!との事でした。
とにかくやってみる、チャレンジして学びを得る。
失敗を受容できる組織は強いです。
アジャイルコーチやスクラムマスターたちが地道に作ってきた文化だと思います。
「失敗」がポジティブになれる記事はこちらです。
Q&A
## Q&A ### (新卒エンジニア)スキーマ駆動とOpenAPIの関係 スキーマ駆動を実現させるための手段 スキーマ駆動開発(概念)、OpenAPI(手段) 様々なレイヤーで呼ばれる スキーマとして共通の言語 統一されたフォーマットで、ymlで機械に読みやすい、組み合わせができる 「スキーマ」を駆使して開発する ### (新卒エンジニア)スキーマとは? もともと図や図式や計画のことを指す言葉 開発では DB の定義などで使われている ### (プロジェクトリーダー)サンプルあるが、実際に導入できる道筋は? 2020/05~2020/09 で開発した機能の設計でやりたい Confluence の設計を OpenAPI として書いても良いかも yml でかければOK **マスターデータであることを合意を取って開発や修正を進める(これが大事!)** コードだけ変えちゃだめよ ### (プロジェクトリーダー)リポジトリ専用で作る? バックエンドのリポジトリに入れてやってみましょう
決定事項
## 決定事項 下記で進めていく 動き出しはできそうなので、下記タスクをバックログに追加して開発を進める - 2020/05~2020/09 の MVP 開発した機能の API 設計(過去のドキュメント)を OpenAPI で作成 - 2020/12~2020/01 で MVP 開発を行う機能を API 設計(今後作るもの)を OpenAPI で作成 活用方法はもう少し考える
導入: 実際にやってみる
チームとして OpenAPI を用いたスキーマ駆動開発に着手することになりました。
■ プロジェクトリーダーと新卒エンジニアが作る
過去のドキュメントをプロジェクトリーダーが、今後作るものはシンプルそうだねという話も有り新卒エンジニアが担当することになりました。
知見のあるシニアエンジニアがレビューに入りました。
(自分は属人的なタスクをしていたので少しだけレビューしました)
コードレビューのやり取り(一部)
実際にやってみないとわからないことも多くあったなと思います。
シニアエンジニアの方から多くの事を学べました。(感謝)
## 過去のドキュメント [must] ここに限りませんが、scalaの `Int` は32bit符号付き整数なのでint32です [imo] ステータスは独立したvalueobjectなので別タイプとして定義し、enumにして取りうる値をリストアップ+descriptionで説明追加とかしてもいいかも。 https://swagger.io/docs/specification/data-models/enums/ [good] descriptionもすごくわかりやすくて良いと思います! 次のフェーズとしてOpenAPIのlint導入ですね 😁 ## 今後作るもの [ask] 一度、サンプルのレスポンスをJSON(YAML)でちゃんと考えてみたほうがいいかも? [must] ここに限らず、 enum 全てについて、ちゃんと type: を指定してください。 allOfを継承みたいに使って、ちょっとだけcomponentsの中身整理してみた。 `修正案の記述`
スプリントふりかえりで上がった内容(一部)
ふりかえりでも話題に上がったのでチームへの良い影響を与えているなと思います。
## GOOD ゴリゴリyml書いてた レビューを通して誤った知識のアップデートに繋がった 導入できた 🎉🎉🎉 OpenAPIのドキュメント作成のレビューありがとうございました ## Problem 進め方気になった 新しく作る時は内部設計・インタフェース設計として軽くJSONとしてのレスポンスのアウトプットまとめて一度レビュー入れた方が良い? 新卒エンジニアとペアプロを実施すればうまく行ったのかな 自分が導入提案したがみなさまに甘えてしまった 自分で作成や改善がしたい!!!
直近のスプリントでも変更点は欠かさずコミットされ、全体に共有されてるので良い感じです。
今後: どのようなフェーズを経て拡大していくのか
導入から 1~2 スプリントを回してみました。
自分が過去に思っていた問題点や、チーフの意見交換会で出てきた課題は今のところは解消できそうな見込みです。
但し過去には "導入する事がゴールとなり、うまく改善を回せず、運用することができなかった" という良くない失敗を多くしてきてます。
銀の弾丸は無いと周りからよく言われるので、チーフ(テックリード)としてチームにとって何がベストなのかを考え、開発文化の構築や改善を行っていきたいです。
昨年のアドベントカレンダーでは技術の取り組みを MVP として考える記事を書きました。
プロダクト開発以外にもこの考えは通ずると思ってます。
(マネージャーが大事にしている価値観でもあるのかなと思ってます)
その考えを継続して取り組みます。
図: 仮説と MVP のイメージ
また、次の個人目標(個人 OKR )では OpenAPI を用いたの開発文化を維持する意思表明を出しておきました。
図: 次の個人目標
まとめ
下記の流れで OpenAPI を用いたスキーマ駆動開発を導入し、運用をし始めました。
- 背景
- Web APIの開発を行っていたが、様々な問題点があった
- 組織としてもAPI駆動開発に課題があった
- やったこと
- チーフの意見交換会でスキーマ駆動開発を題材とした勉強と議論
- OpenAPIを調べ、過去のドキュメントを元に〇〇を作り、チームへ提案
- 結果
- 現在はチームの全エンジニアがOpenAPIを触っている状態
- 所感 -ここまできたのは組織改善の結果やチームの協力あってのこと
- 今後
- 文化を維持するために改善を行っていく
皆様の API 開発に幸あれ。
参考記事
チームのWeb API開発を最適化するSchema Driven Developmentの解説&実装例 - Qiita
スキーマ駆動開発のススメ - Studyplus Engineering Blog
本当に使ってよかったOpenAPI (Swagger) ツール | フューチャー技術 ブログ
次はほったさんの記事です。