Darklaunch（ダークローンチ）を導入してチーム開発を進めやすくした

[GLOBIS Advent Calendar 2023](https://qiita.com/advent-calendar/2023/globis) 14日目の記事です。

こんにちは！GLOPLA LMS開発メンバーの太田です。

開発をしていると「大きな機能の開発」をすることがあると思います。

私たちはスクラムを導入していますが、プロダクトの開発メンバーは比較的多いため、スクラムチームとして3〜4人くらいのチーム構成になるよう分かれて開発をしています。

その中で、特定のチームが「大きな機能の開発」を担当することもあります。
そのケースでは機能全体の開発の進行がスプリントを跨ぐことはしばしばです。

しかしながら、開発途中の機能をそのままメインブランチに混ぜると、実装途中の機能が顧客に見えてしまいます。
かといって、それを避ける全体のリリースを止めてしまうと、他チームが開発した機能のリリースの妨げになってしまいます。[^1]

この記事では、この困りごとを解消するためにDarklaunchを導入した話について書きます。

## Darklaunch（ダークローンチ）とはなにか
ユーザーに気づかれないよう機能をリリースし、内部でパフォーマンスの測定をしたり、動作確認を行ったりできる手法のことです。
これはいわゆるFeature Toggles（Feature Flagsとも呼ばれる）と呼ばれる機構であり、「ON」にすると機能を有効にし、「OFF」にすると無効にするような手法です。

これによって、開発した機能を本番へリリースすると全て全体に公開されていたものが、この機構によって公開するかどうかを選択することができるようになります。

参考: [『ダーク ローンチとは何か : CRE が現場で学んだこと』](https://cloud.google.com/blog/ja/products/gcp/cre-life-lessons-what-is-a-dark-launch-and-what-does-it-do-for-me)

## フィーチャーブランチという選択肢
例えば、大きめな実装になるのであれば、ダークローンチを用いらなくともブランチ戦略としてフィーチャーブランチを採用することがあると思います。

フィーチャーブランチで開発する場合、メインブランチから別のブランチを派生させ（これがフィーチャーブランチ）、そのブランチからまた派生をして開発し、フィーチャーブランチへとマージします。
開発したいものが全てフィーチャーブランチへとマージされると、それをメインブランチへとマージします。

フィーチャーブランチのメリットは、メインブランチへ影響を及ぼさない形で複数人で大きめの開発を行えるところです。
これであれば、メインブランチに入っているもの = 完成しているもの = リリースできるもの　となるため、リリースフローにも影響しません。

一方でデメリットとしては、メインブランチとのコンフリクトが発生しやすくなる点です。
先述のように複数チームで同じプロダクトを触っているため、少し追従できなくなると簡単にコンフリクトが発生します。
このデメリットはそれなりに大変で、たとえば毎週最新のメインブランチを取り込んでいたとすると、その度にコンフリクトの解消に30分かかることがよくあります。

つらいです。

## 達成したい目的
最も達成したい目的は "できるだけフィーチャーブランチを使わずメインブランチにマージしながら開発を進めたい" ことです。

フィーチャーブランチではブランチの環境保全に労力がかかるので、できれば他の手段が欲しい状態でした。

そのため、できるだけメインブランチにマージしつつ、大きめな実装を続けていく仕組みを入れたい、という流れの中で「Feature Toggles」が候補に上がりました。

この目先の目標を達成するには必ずしも本番環境で機能を有効にしなくてもOKですが、STG環境や検証環境では有効にしたいケースもあるので、機能を有効にしたいケースも満たしたいです。

それならと、以前運用を体験したことがある「Darklaunch」を導入しましょうと提案し、実際に運用に向けて導入していくことになりました。

## 導入に向けて
Darklaunchを導入するに向けて、世に出ているサービスを導入するか、独自で実装するかの検討をしました。

例えば[LaunchDarkly](https://launchdarkly.com/)というサービスがありますが、（当然ですが）少なからずお金がかかります。

仮に独自で実装したとしても、Darklaunchの機能としては非常にシンプルなので独自で実装しちゃってもいいのではないかと判断して、独自で実装を進めることとなりました。

当時プロトタイプを1時間ほどで作成して、実際に動くところをチームにお披露目した覚えがあります。

この仕組みを機能として落とし込むために、仕様、運用方針、設計を決めていきました。

### 仕様
- 顧客企業単位で設定ON/OFFを切り替える
- 設定ON/OFFはシステム管理者だけが切り替えることができ、ユーザーは切り替えられない

### 運用方針
- 機能を顧客に公開する際は、Darklaunchを使用しない
  - 今後は使用するケースがあるかもしれないが、初期段階としては使用しない
  - あくまで顧客へ機能を隠すために使用する
  - DarklaunchをONにする場合は、顧客に見えない環境で実行し、内部の確認用にとどめる
- ひとつのDarklaunchはできるだけ短命にする
  - 公開できるラインまで開発が完了したらDarklaunchを削除し、全体公開へ切り替える
  - 本来は1、2週間で削除するらしいが、ここでは対象機能の開発がマイルストーンを迎えるまでとする

### 設計

私たちのアプリケーションでは以下の技術構成を使用しています。

バックエンド: Ruby on Rails
フロントエンド: React
APIのやりとり: GraphQL

主にユーザー側の画面はReactで実装されており、システムの管理画面はRailsで実装されています。

設計方針としては以下のイメージです

![スクリーンショット 2023-12-01 18.58.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3592026/c532bf26-e6c5-20ea-e53d-9edca0c76b16.png)

実際にはバックエンド側でもDarklaunchの設定によって処理を分けることもある想定です。

ざっくりいうと以下のような仕組みです：
- システム管理側でDarklaunchを設定する
  - Darklaunch設定用の画面を用意する
  - この画面で以下を設定してDBに保存
    - Darklaunch名
    - 説明文（任意）
    - 対象企業ID
- アプリケーションのバックエンド側でDBからDarklaunch設定を取得する
  - DBから取得した値をAPIを通してフロントエンド側に返却します
- フロントエンド側で表示を切り替える
  - ログインしているユーザーのテナントのDarklaunch設定を確認する
  - ONになっていたらUIを解放する

## 導入してよかったこと
### フィーチャーブランチの導入頻度が減った
Darklaunchによる開発のおかげでフィーチャーブランチに最新のメインブランチを取り込んだり、コンフリクト解消をしたりといった作業が不要になりました。

### 常に最新のメインブランチとの影響を確認できる
例えばフィーチャーブランチで開発していると、最新のメインブランチの状態を反映させないと他チームが開発している新機能との影響を確認することができません。
さらに、確認できるのはフィーチャーブランチで開発しているメンバーだけなので、他チームとの影響に気づくのは広い視野が必要です。

一方でDarklaunchの場合は常にメインブランチに混ざっているため影響が確認しやすく、またより多くの人が影響に気づくことができます。

### フィードバックを受けやすくなった
フィーチャーブランチに開発物を溜めているうちはどの環境にも反映されていないので、開発者自身の開発環境でしか様子が伺えません。

しかし、Darklaunchを使用すると任意のタイミングで機能をONにすることができるため、開発途中の機能を検証環境やSTG環境で見ることができます。

途中の状態をエンジニア以外のマネージャーやデザイナー、QAの方やビジネス側の方が確認できることによって早めのフィードバックがもらえるため、改善点やリスクを発見しやすくなりました。

一方で、開発が途中過ぎる状態で操作をすると中途半端なデータが出来る可能性があるため、いつでも自由に触れるわけではない点には注意しなければなりません。

## 導入して困っていること
### コミュニケーションの難しさ
今までエンジニア側とビジネス側で「リリース」という言葉の定義が微妙にずれていました。

エンジニアが行うリリースフローの中にデプロイ作業も入っているため、エンジニア側は実質リリースとデプロイが同じ状態になっていました。
リリース作業というとコードデプロイを指しているため、Darklaunchによって隠している機能も含まれます。

一方ビジネス側ではあくまで機能の顧客公開を指しているため、Darklaunchによって隠している機能は含まれません。

Darklaunchによって隠している機能に対して「この機能は次のリリースに含めますか？」と聞かれた時に、コードが反映されていることなのか、機能が顧客に公開されていることなのか、どっちなんだい！という混乱が生まれていました。

今まではメインブランチに反映したものは全て顧客に公開されていたので特にこれまで問題はなかったのですが、Darklaunchの登場によって少しややこしくなりました。

そこから「Darklaunchという仕組みによって機能を隠しているので、コードは反映させるけど顧客へ公開はしない」という説明を重ねる中でDarklaunchそのものの理解が広まり、今では「この機能はDarklaunchです」と言うだけでビジネス側の方々にも伝わるようになりました。

感謝...!

### DBの変更が伴う開発にDarklaunchが使えない
ここで導入したDarklaunchはコードレベルでの話なので、DBの変更には対応できません。
テーブルを追加したりカラムを追加したりなどのDBの変更が既存に影響しないのであればメインブランチにそのまま入れますが、そうでない場合はメインブランチに入れることができないため、Darklaunchを使用することができません。
そういった場合は、歯を食いしばりながらフィーチャーブランチでの開発をしております。

ここにも対応できるようにしたい、というのが今後の展望です。

## おわりに
今回導入したDarklaunchはあくまで本番では公開設定する運用を予定していない前提なので、とても簡易的なものです。
隠すためであれば他の手段も取れると思いますが、本番環境の検証環境やSTG環境でチラ見できると先手でフィードバックがもらえるので、導入してよかったなと思っています。

ちなみに、Darklaunchを導入した直後に早速大きめの開発をすることになったのでDarklaunchを使用したのですが、Darklaunch名を設定する際に「この開発は1ヶ月くらいで終わるしな」と思い、開発する機能とは全く関係がない`the_feels`という命名から運用が始まりました（私が当時Twiceにハマっていた）。

そこからしばらく`enable_XXX(機能名)`という真面目な命名が続いた後、また私に命名チャンスが回ってきたので`DH_17`（ユーザーを指名できる機能に関連した開発だったので、それにちなんで指名打者大谷翔平を連想しました）というまた関係のない命名をしたところ、今度はしっかりレビューで弾かれました。

Darklanch名はわかりやすい命名にしましょう。

## 一緒に働く仲間を募集しています！
株式会社グロービスでは、エンジニア含めて各職種方面で仲間を募集しています。
興味がある方はぜひご連絡ください！

https://recruiting-tech-globis.wraptas.site/

[^1]: メインブランチから各開発メンバーが開発ブランチを切り、メインブランチへマージするフローで開発しています。GitHub Flowに近い。