はじめに
BASE でプロダクト開発をしている @rry です。
さいきん BASE では 予約販売 App にて「長期の予約商品」を設定できるようになりました!
- 🗓️予約販売期間が1年先まで延長可能
- 🧵製作や入荷に時間がかかる商品も取り扱いやすく
- 🎄季節の限定商品を事前に販売開始も◎
今までの予約販売 App では最長で8週間までしか予約設定することができず、オーナーさんからのフィードバックでも「8週間先も設定できるようにしてほしい」という要望が多かったため、このたび予約販売長期化 PJ として機能改修を行いました。
この PJ の裏側を開発目線からご紹介していこうと思います。
PJ 概要
- PJ キックオフから10/19リリースまでの期間:約8ヶ月
- PJ メンバー:開発エンジニア 2-6人、QA エンジニア 1人、PM 1人、デザイナー 1人
- アジャイル・スクラムで開発
- 1スプリント:1週間
- デイリースクラム:毎日15分
- スプリントレビュー・レトロスペクティブ・スプリントプランニング・バックログリファインメント:まとめて毎週火曜日
自分はこの PJ では PjM と主にフロントエンドの開発という役割で PJ をリードしていきました。
どんなことをやったのか
長期の予約注文は内部的には、決済時に一度取得したオーソリ(与信)をキャンセルし、時が来たら再度オーソリを取り直す、という方法で長期化を実現しています。 また、長期の予約注文が発送開始予定日を迎えるまでは注文を発送させないようにしなくてはいけません。そのため以下のような開発が必要でした。
- バッチの作成
- 注文時のオーソリをキャンセルするバッチ
- オーソリを再取得するバッチ
- このときにオーソリが取れずキャンセルしなければならない注文はキャンセル処理もする
- オーソリ取得に成功して時が来たら注文の配送ステータスを「対応開始前」から「未対応」に変える
- 注文管理画面から長期の予約注文が確認できるようにする・配送ステータス「対応開始前」のときは発送できないようにする
- オーソリを取り直す必要があるため、長期の予約商品では Pay ID ログインが必須。そのためカートを改修する
- 注文の配送ステータスに今回新しく「対応開始前」が追加されたため、配送ステータスが影響している箇所すべてを改修する
- 予約販売 App 画面と商品登録画面から長期の予約商品が設定できるようにする
- 商品詳細画面で長期の予約商品は発送時期が上旬・中旬・下旬表記に変わり、注意文言が増える
なんかいっぱいありますね!
ザックリ時系列の流れ
- 2-4月: DB・アーキテクチャ設計、影響範囲調査、概算見積もり
- 設計についてはいろいろありましたが4月あたりから開発着手できるところから開発着手していきました
- 5-9月: 開発
- カート -> バッチ -> 予約販売 App -> 注文管理 -> 商品管理 -> その他... みたいな流れで進めていきました
- 10月: リリース前 QA -> リリース
このように開発が進んでいきました。
PJ を通して大変だったこと
半年以上の PJ をやってみて、いくつか反省点や大変だったことがありました。
インシデントはトータル5件
ユーザーに影響がないような小さいインシデントからユーザーに影響があるインシデントまで、この8ヶ月間でトータル5件起こりました。
ユーザーに影響があるインシデントが起こった箇所としては「商品管理画面」「ショップの商品詳細画面」で起こり、同じような不具合を起こさないように対策&周知してこれからも気をつけて開発していきたいと思います。
PJ 初期の段階でポイント見積もりに時間をかけすぎてしまった感がある
スクラムをしていく上で、開発がいつ頃に終わるのか予測を立てるために、開発前に概算のポイント見積もりをしていました。
が、全体の仕様が決まりきる前に全体のポイント見積もりをしてしまったり、開発していくとポイントの重みが初期の重みから変わってしまったりしてしまいました。こうなってしまうと初期につけたポイント見積もりはあまり意味のないポイントになってしまい、見積もりにそこまで時間をかけるよりも開発に時間をかけたい、となってしまいます。
この反省を生かして、次から全体のポイント見積もりを行うタイミングは、
- どこまで開発するかの要件や仕様と設計が定まってから
- 数回スプリントを回してみてポイントに対する肌感が開発エンジニアの中で揃ってきたときに
するのが良いのではないかと思いました。 次回の PJ では、開発初期は「ここまでにこれを開発していたい」というざっくりとしたマイルストーンを置くくらいに留めて、全体の概算見積もりは仕様と設計が固まってからにしたいです。
色々あった結果既存コードが多く残っているリポジトリでの開発で DDD を採用しないことにした
こちらについては長くなるのですが、誤解されてしまうのを恐れずにあえてザックリめに書きたいと思います。
BASE では現在、既存コードが多く残っていて昔からあるリポジトリから、DDD + クリーンアーキテクチャで作られた新しいリポジトリにリアーキテクチャをしていっている最中です。カートのバックエンドなどは新しいリポジトリにコードがあります。いずれはバックエンドのコードはこの新しいリポジトリにコードを移していく予定です。
ですが今回は既存の注文まわりのコードが新しいリポジトリにないため、昔からあるリポジトリ上でメインの開発をすることにしました。 では、昔からあるリポジトリで今回の開発をする場合は、どういう設計にするのが適切でしょうか?
昔からあるリポジトリでも一部コードはドメインモデリングがされていて DDD のアーキテクチャが採用されていたり、はたまた軽量 DDD のような設計で構成されている状態ではありますが、まだまだ大部分のコードは MVC + S のアーキテクチャです。
当初予約 PJ では、
新しく書くコードの設計は DDD でいこう、いやでも昔からあるリポジトリでは DI や DB トランザクションまわりの基盤機能が十分ではないしな...
それなら軽量 DDD にするか...?いやでもドメインモデリングがしきれないのに DDD のアーキテクチャパターンを少しだけ囓ったような設計ははたして「軽量 DDD」と呼べるのか... 否、呼べないな...
そして社内でチーム内外含めて議論する日々...
と、このようなことが起こりました。
そこで話し合った結果、以下の内容でチーム内外含めて全体での合意がとれました。
- 境界づけられたコンテキストで明確に分けられることが分かっているドメインであること
- ドメインモデリングをしており、尚且つそのドメインモデリングを保守・運用していくこと
- DDD による設計が生きてくる程度にはある程度複雑性のあるドメインであること
この3つが満たされる場合のみ、昔からあるリポジトリでも DDD で開発することができます、満たせない場合は DDD で開発するのはやめましょう。
そして予約 PJ の場合は注文に関係するドメインと密接に関わっていて、「境界づけられたコンテキストで明確に分けられることが分かっているドメイン」ではなかったため、昔からあるリポジトリでのメインの開発にて DDD は採用しないことにしました。
ではどんな設計にしたのか?
基本は MVC + S のアーキテクチャに則っています。ただし、開発するボリュームを考えるに Service が肥大化するのが目に見えています。 そこで、以下のような設計を行いました。
- Entity ... Model 層が実質2層に分かれている
- フレームワークの Model の責務はデータアクセス(DB クエリビルダー)
- 連想配列ではなく、ORM 的なオブジェクトとビジネスロジックは Lib/Entity へ(ValueObject のようなもの)
- Shared Service ... Service 層を2層に分ける
- Service ... Controller(もしくは shell)から1処理あたりに call できる Service は原則1つ、いわゆる MVC + S の S
- Shared Service ... Controller(もしくは shell)などから直接 call してはいけない、Service 層もしくは Facade 層から call する
- Facade ... いわゆる Facade パターン。外から Entity や Shared Service を呼ぶときは Facade を使う
ここまで大変だったことを長々と書きましたが、PJ を通して良かったこともありました。
PJ を通して良かったこと
当初の設計から大幅な仕様変更や、影響範囲の考慮漏れなどがなく PJ を終わらせることができた
前回自分が担当した PJ では、開発終盤で影響範囲の考慮漏れがみつかり阿鼻叫喚、みたいなことがありましたが、今回はその反省を生かしてあらかじめ影響範囲調査をしっかりとやったので今のところ考慮漏れバグみたいなものはみつかっていないです。
バックエンドのテストカバレッジ結果が良かった
これはバックエンドエンジニアの方がメインでテストを手厚く書いていったことによる功績ですが、今回新規追加したバックエンドコードのテストカバレッジ結果が他コードと比較してとても良かったです。
リリースしてから大きな不具合なく済んでいることに影響していると考えます。
フィーチャートグルを使ってビッグバンリリースにせず小出しにリリースできた
半年以上かかる規模の PJ だったので、初期からフィーチャートグルの仕組みを使ってスプリント中に開発したものをメインのブランチにマージしていきながら開発できたのは開発体験が良かったです。そしてリリース当日はフィーチャートグルを全ショップ公開にするだけでリリースすることができました。
QA エンジニアに PJ 開始時から入ってもらえた
今回の PJ では、PJ 当初から QA エンジニアの方に Join してもらうことができ、スプリント中に機能ができあがり次第随時機能単位での QA をしてもらうことができました。
また手厚い QA 項目があったおかげで、リリース前の複雑なバッチの QA なども手分けして行うことができました。
おかげで安心して開発を前に進めることができ、クリティカルな不具合がなく済んでいることに影響しています。
以上、これらをやることによって開発エンジニアとしては PJ を前向きな気持ちで進めることができました。
おわりに
長くなりましたが、以上が予約販売長期化 PJ の開発の裏側になります。
今回は開発にフォーカスしましたが、PdM やデザイナーの方など優秀な人たちの力を借りてようやくリリースできた PJ だと思っています。 これからも BASE のプロダクトをより良いものにしていくような開発を心がけてやっていきたいです! 🚀