dely Tech Blog

クラシル・TRILLを運営するdely株式会社の開発ブログです

攻めと守りのトレードオンを目指した開発ルールの見直し

こんにちは。delyでクラシルリワードのサーバーサイドの開発をおこなっている高松です。

はじめに

今私が開発を担当している「クラシルリワード」は、日々我々が行う購買行動をよりお得に行なってもらうことを目的に作られたサービスです。

dely.jp

私は2023年10月からクラシルからこのクラシルリワードの開発担当として異動してきました。

クラシルリワードにおいては、プロダクトの急成長段階にあり、KPIを伸ばす上で何が適切なのかの解像度が低い状況にあります。

そのため、仮説検証をなるべく早く繰り返すことで、解像度を上げて施策の効果を最大化したい思いがあります。

この記事はそんな中で、開発ルールは現状のもので良いのかを改めて考えてみた経緯です。

トレードオンとは

弊社にはトレードオフと対比する言葉としてトレードオンというどちらのメリットも享受できる方法を考えようという文化があります。 今回はその文化のもと、開発における攻めと守りの両方を意識してみたというお話です。

1. 究極の理想状態を考える

スタートはいろんな制約を考えず、どういった状態であったら最高なのかを考えるようにしています。

仮説検証をなるべく早く繰り返したいプロダクトの状態においてサーバーサイドの開発に関しては、「リリースしたい機能を誰でもすぐにリリースできる状態」かなと考えました。

この状態は技術的に実現できるか否かでいうとどうでしょうか。

実現できなくはなさそうですが、同時に下記のような問題が発生することが想像できます。

  • 個人で気が付かない不具合が含まれている可能性がある
  • 開発者以外要件と目的がわからなくなる

どうして不具合が発生してはいけないのか

システムの不具合 = プロダクトが意図通り動いていない状態 = 利用者に想定の価値を提供できていない

つまり

  • 利用者の目線で言えば、「プロダクトを使っている目的を果たせなくなる」
  • 我々サービス提供者目線で言えば、「達成したい目標を達成できない」

と、当然ながら誰も幸せにならない状態になってしまうため、不具合は基本的には発生させてはいけません。

どうして開発者以外要件がわからなければいけないのか

こちらはどうでしょう。

  • チームで継続して開発をする上で既存の要件を制約として満たさなければいけないため

さらに深ぼると

  • 既存の要件を無視して開発を継続することで不具合が発生する可能性があるため

つまり、こちらも結局は不具合の発生の温床になるためという結論になりました。

現実的な理想をまとめる

結論我々の理想は「リリースしたい機能を "全ての機能が不具合なく動くことを担保した上で" 誰でもすぐにリリースできる状態」という制約付きのものであるという考えに至りました。

2. 現実的な理想を実現する方法について考える

ひとまず現実的な理想が

  • リリースしたい機能を誰でもすぐにリリースできる状態であること
  • 全ての機能が不具合なく動くこと

であることとしたので、それぞれどうすれば実現できそうかを考えます。前者に関しては冒頭で考えたので、後者に関して考えてみます。

「全ての機能が不具合なく動くことを担保する」ためには

そもそも開発者全員不具合を出さないように開発をしているはずなのに、個人で気が付かない不具合が含まれてしまうのはなぜでしょうか。

  • 正常動作の確認は簡単であるが、異常動作の全てを確認することが容易でないため。
  • 開発箇所の影響範囲が不明確なため、開発者の意図しない箇所の挙動が変わる可能性があるため。
  • 本番のトラフィック量やデータ量など環境依存で発生する要因の確認が難しいため。

まだまだあるかと思いますが、この辺りを要因として挙げました。

それぞれの要因に対して防ぐ方法はどんなことが考えられるでしょうか。

  • 正常動作の確認は簡単であるが、異常動作の全てを確認することが容易でないため。
    • 各開発者のノウハウの共有 = 技術力の底上げ?
  • 開発箇所の影響範囲が不明確なため、開発者の意図しない箇所の挙動が変わる可能性があるため。
    • 全ての機能において網羅的なテストケースの作成?
  • 本番のトラフィック量やデータ量など環境依存で発生する要因の確認が難しいため。
    • リリース前の負荷テストの実行?

深ぼってみると、開発者個人の頑張りよりは仕組みや状況で解決する方がよさそうでした。

どのような仕組みや状況用意することでを「全ての機能が不具合なく動くことを担保する」ことができるでしょう

  • 厳密なQA体制ができていること?
  • 強固なシステムテストがつくれていること?
  • 実装ガイドラインが細かくできていること?
  • PRレビューのapproveガイドラインが細かくできていること?
  • 完全なドキュメントが整備されていること?
  • 本番環境相当の検証環境が用意されていること?

と、俯瞰してみてみると 不具合の発生確率開発速度 においてトレードオフが発生してしまいそうです。

つまり、現実的な理想である「全ての機能が不具合なく動くことを担保する」ことと、「リリースしたい機能を誰でもすぐにリリースできる状態にする」ことはトレードオフの関係であることが改めてわかりました。

3. トレードオン状態になるポイントをチームで探る

ここからは認識をそろえるために、クラシルリワードのサーバーサイドチームメンバーや適宜プロダクト開発の意思決定者も交えて話し合いをしていきました。

プロダクトとして絶対に担保しないといけないところはどこか

  • コインやガチャチケットなど売り上げに直結する情報が正しく更新・表示されること
    • = 利用者が受け取れるはずの報酬をちゃんと配布できること
    • = 不正利用によって報酬が配布されないようにすること
  • 利用者がクラシルリワードに来た目的を安全に果たせること
    • = アプリのどのページもいつでも開けること
    • = 個人情報などセキュアな情報がちゃんと取り扱えていること

担保しなければいけない点はたくさんありますが、プロダクトの特性上大まかに「金銭に関わること」「個人情報に関わること」「アクセスできない状態を避けること」のポイントに絞られました。

それぞれ担保するために必要になりそうなことは何か

結論としては、「用意するテストケース」「監視体制」「レビュー観点」という原始的な部分の再認識となりました。

この段階では開発ルールの変更は何もされていないものの、チーム内で「守るべきこと」「攻めていい箇所」の感覚が擦り合って来たと思います。 

また、開発ルール変更とは別軸ですが、弊社のエンジニアjoeさんが用意してくれた、SLIによってまだ攻められるか、攻めすぎかを定量的に見えるような工夫もできました。

tech.dely.jp

4. 現実的な理想と現状の差分を可視化する

当時クラシルリワードでは、先輩プロダクトであるクラシルでの知見や反省を活かすために、開発ルールも基本踏襲した形をとっていました。

delyの開発体制とクラシルの開発ルール

delyではプロダクトを開発する際、プロダクトの主要KPIから作られるKPIツリーにおいて、注力するべきKPI毎にプロダクト開発チームを作り自走して開発ができるようにしています。

そんなプロダクト開発チームにおいて、サーバーサイドのエンジニアはこんなフローで開発をしています。

  • プロダクト開発チームが解決するべき課題と仮説をもとに次にリリースする施策を決定する
  • プロダクト開発チームで、施策の実現方法を検討する
  • 施策実現のために必要なサーバーサイドの開発内容を設計書としてまとめる
  • 他のサーバーサイドメンバーが設計書をレビューする(3名ランダムアサイン。2名のapprove必須)
  • 設計書のレビューが完了したら、設計書に則った形で実装をする
  • 他のサーバーサイドメンバーが実装をレビューする(1名ランダムアサイン。approve必須)
  • 実装のレビューが完了したら、リリースする

特色としては、実装前に仕様書・設計書という名目でドキュメントを作成し展開することで、

  • この設計で目的を達成できるか、問題になるところはないか

が議論でき、「別のプロダクト開発チームに属するサーバーサイドエンジニア」「将来ジョインするサーバーサイドエンジニア」「将来の自分」に向けて、

  • 開発をする目的は何か
  • この開発をするに至った経緯

が残せることがメリットとして大きくあります。

実装時のレビューにおいても、コーディングにフォーカスできるため、実装レビューの負担を少なくすることができています。

クラシルの開発ルールのメリットをまとめると下記です

  • 各箇所の開発の意図や目的がドキュメントとして残る
  • 実装前にレビューが入るので、実装の手戻りが発生しにくい

クラシルリワードにおいて今の開発ルールは適切か

ここは個人的な感覚として、クラシルリワードにおいてクラシルの開発ルールを踏襲するのは、下記の理由からオーバーキルであると感じました。

  • 設計と実装で2回のレビューが入ることは開発者もレビューする側もかかる時間が大きい
  • かかる時間に対して、チームで取り決めた「守るべきこと」を担保できる効果が薄い
  • 全メンバーが設計に目を通すわけではないので、設計の段階では一部のメンバーにしか開発経緯や目的が伝わらない

5. 開発ルールを変更する

上記の理由から、下記の通り開発ルールを変更しました。

  • 実装前のドキュメント作成の義務は撤廃
    • 理由は上記の通り、これにかかる時間に対して「守るべきこと」を担保できる効果が薄いため
    • 開発量が膨大だったり、事前に伝えておきたいと開発者が感じた場合はドキュメントの作成・レビュー依頼共にOK
  • 実装レビュー依頼時のランダムアサインを撤廃
    • 開発者以外で経緯を把握しているメンバーや過去に同じ領域を開発していたメンバーによってレビューされた方が「守るべきこと」は担保されやすいため
  • ドキュメントは仕様書という役割で、実装後に「どんな経緯で」「何を目的に」実装されているかをまとめるようにする
    • 将来の自分達のために価値のあるドキュメントを残しておくことの重要性は、クラシルの経験から引き続き踏襲したいため

変更による効果

「1日のデプロイ頻度の向上」「変更障害率の低下」が数値としてはみられています。

定性的には、ひとまず施策リリースのために#FIXMEとして残しておいた部分を後から改修しやすくなったため、デプロイに対するハードルが下がり施策リリースサイクルは上がっていると感じます。

6. まとめ

今回は開発効率の改善をテーマに考えたこと、行ったアクションをまとめてみました。

一概に開発効率の改善といっても、こんな開発ルールにすれば必ず効率が上がります!という所謂銀の弾丸と呼ばれるものは無いのかなと思った一方で、 フレームワーク的な見方として、組織の文化や今のプロジェクトにおける開発で重要視される点を具体的にしていくと、現状に対して何を改善する必要があるのかは見えてきたりするのかなという学びがありました。

また、個人的に今回の件に限らず抽象度の高い問題に対しては

  • 究極的な理想を考える
  • 究極的な理想に対して、発生してしまう制約を洗い出して現実的な理想を定義する
  • 現実的な理想と現状の差分を可視化する
  • 差分を埋める方法を考える
  • やってみる
  • 効果を見る

こんな感じのステップで考えるようにしています。

また、他の人も巻き込みながら何かを進める際は下記のことが大事かなと思っています。

  • 当たり前と思われることも言語化する
  • 原理原則から認識をそろえる

この考え方が必ずいいというわけではないと思いますが、どなたかの参考になれば嬉しいです。