本記事は、10月29日〜30日にかけて開催した「CyberAgent Developer Conference 2024」において発表した「WINTICKETアプリで可用性を向上させたFeatureFlagの運用戦略とその方法」に対して、社内の生成AI議事録ツール「コエログ」を活用して書き起こし、登壇者本人が監修役として加筆修正しました。
中鉢 かける (株式会社WinTicket Flutterエンジニア)
2021年サイバーエージェントに新卒入社して株式会社WinTicketに配属。 WINTICKETアプリのFlutterリプレイスプロジェクトに参画して、運用に携わる。
「WINTICKETアプリで可用性を向上させたFeatureFlagの運用戦略とその方法」について発表させていただきます。中鉢かけると申します。2021年に新卒で入社して以来、株式会社WinTicketでモバイルアプリエンジニアとして従事しています。
まず初めに、WINTICKETについて簡単にご説明します。WINTICKETは、競輪とオートレースに投票できるサービスです。このアプリでは、レース映像のライブ視聴や、AI予想、EXデータなどの豊富なデータ提供を行っています。また、ABEMA番組とも連動しており、ミッドナイト競輪などの番組をWINTICKETアプリ上で視聴することが可能です。
サイバーエージェントの決算資料によると、WINTICKETはリリースからわずか約2年で競輪投票サービスNo.1へと急成長を遂げました。さらに、芸能人を起用したCMやマーケティング活動にも積極的に取り組み、現在では競輪業界を牽引する存在となっています。
WINTICKETの紹介を終えたところで、ここから本題に入らせていただきます。本セッションでは、これからお話しする内容の流れを順を追ってご説明していきたいと思います。
まずは、Flutterリプレイス後のFeatureFlag運用についてお話しします。その後、従来のFeatureFlagを使用した開発について説明し、そこから発生していた不具合の分析と整理についてお話しします。不具合の分析を通じて得られた課題をどのように捉え、可用性向上のための運用戦略とその具体的な方法を考えたのかをご説明します。そして最後に、対応した結果と今後の展望についてお話しする流れで進めさせていただきます。
1. Flutterリプレイス後のFeatureFlag運用と課題
まず、Flutterリプレイス後のFeatureFlag運用と課題についてお話しします。WINTICKETのアプリは、以前はiOSとAndroidがそれぞれ異なる技術で開発されていました。この分離された開発環境により、メンテナンス性や機能追加の効率性に課題がありました。そこで、2021年3月に技術戦略の一環として、アプリをFlutterでリプレイスすることが決定されました。この決定を受け、Flutterを用いたアプリのリプレイスプロジェクトが正式にスタートしました。
約1年後の2022年4月に、まずAndroidアプリのFlutterリプレイスに成功しました。さらに翌年の2023年3月には、iOSアプリのリプレイスも完了し、現在ではFlutterを用いてiOSとAndroidアプリの開発および運用を続けています。このFlutterリプレイスプロジェクトの開始当初から、WINTICKETのアプリではトランクベース開発を採用しており、現在までに3年以上の運用実績があります。
Flutterリプレイス時の詳しい開発体制や取り組みについては、昨年のCADCセッションで詳しくお話ししていますので、ぜひそちらもご覧ください。
最初に、本セッションで出てくる用語の説明をさせていただきます。トランクベース開発とは、機能追加や改修といった大きな変更を小さな単位に分割し、それを順次メインブランチにマージしていくバージョン管理手法を指します。
機能が完成しているかどうかに関わらず、常に修正がメインにマージされてリリースされます。従来のFeatureBranchで開発するGitFlowと異なり、機能修正のマージのリードタイムを短縮し、メインブランチへのマージ時のコンフリクトを起きにくくすることができます。
次にFeatureFlagについてです。FeatureFlagは、静的または動的に機能のオンとオフを切り替えることができる手法のことです。トランクベース開発では、未完成の機能をリリースに含めますが、実行されないように処理を隠すためにFeatureFlagを使用します。
概念を伝えるためにサンプルコードを記載していますが、基本的には、Boolのような真偽値を使用して、if文で分岐を制御するコードを書くことが可能です。
この2つを組み合わせることで、WINTICKETアプリではFeatureFlagを活用したトランクベース開発を運用しています。
例えば、ブランチAで未完成の機能を実装し、それをリリース1.0としてストアに公開します。この際、FeatureFlagをオフにしているため、ユーザーにはその機能が見えないように制御します。その後、ブランチBでさらに差分を加えて機能を完成させ、リリース1.1でストアに公開するときにFeatureFlagをオンに切り替え、初めてユーザーにその機能を提供できるように制御します。
この先の戦略にもつながるため、前提知識としてアプリチームのこれまでの開発状況についてご紹介します。
まず、1つ目に、WINTICKETではFeatureFlagを使用したトランクベース開発を3年以上運用してきました。2つ目に、それによって新機能を追加する際には、FeatureFlagを活用して開発中の機能を閉じた状態で、アプリを毎週という頻度でリリースしていました。3つ目に、新機能の開発やリファクタリングが活発で、常時20個弱のFeatureFlagがプロジェクトコードに埋め込まれている状況で、新規の2つから3つの機能を同時に並行開発していました。4つ目に、近年では新卒メンバーを積極的に配属しており、既存コードへの理解が浅いメンバーが急増しているという状況がありました。
また、本セッションでは、WINTICKETのアプリ開発について理解を深めていただくための事前知識として、アプリのレイヤー構成を簡単にご紹介いたします。
WINTICKETのアプリは、クリーンアーキテクチャをベースに、Data、Domain、State、UIの4つのレイヤーで構成されています。これらのレイヤーをまたぐ依存性の注入(DI)やステートの管理には、リポジトリパターンを採用しています。
詳しいレイヤー構成や設計については、過去にDevelopers Blogでまとめていますので、興味のある方はぜひそちらをご参照ください。
それでは、Flutterリプレイス後のFeatureFlag運用について具体的にお話ししていきます。本セッションでは、FeatureFlagの使用用途、FeatureFlagの実装方法、そしてFeatureFlagの導入原則について順に説明します。
まず最初に、FeatureFlagの使用用途についてお話しします。
WINTICKETアプリにおけるFeatureFlagの使用用途についてですが、先ほど少し触れたように、主に開発中の機能を細かいプルリクエストに分割してメインブランチにマージすることで、プルリクエストのリードタイムを短縮し、コンフリクトが発生しにくくするために使用しています。
また、新機能の開発や大規模なリファクタリングを行う際には、リリース時に不具合が発生した場合に機能を切り戻せるようにする目的でもFeatureFlagを活用しています。
さらに、機能の効果を検証する際には、FeatureFlagを使用してA/Bテストを実施することも可能です。このように、FeatureFlagは開発効率の向上だけでなく、機能の安全なリリースや運用の改善にも役立っています。
次に、FeatureFlagの実装についてお話しします。具体的には、FlutterでFeatureFlagを活用するために、WINTICKETでは内製のFeatureFlagクライアントを実装し、それを使用しています。
WINTICKETでは、FeatureFlagを2つのタイプで実装しています。1つ目は「Work In Progress」というタイプです。このタイプの実装では、SharedPreferencesを使用してフラグの状態をローカルストレージに保存しています。これにより、手元でいつでもフラグの状態を切り替えることが可能です。このタイプは主に開発中に使用するフラグです。
もう1つは「OPS」というタイプのフラグです。このタイプの実装では、Firebaseのリモートコンフィグと連携しており、リリースを行わなくてもFeatureFlagを切り替えることが可能です。これは主に機能が完成してリリースするときに使用するタイプです。
次に、WINTICKETで具体的にどのようなFeatureFlagの制御を実装しているかについて説明します。
まずは、先ほどお話ししたFeatureFlagクライアントのインスタンスから直接getメソッドを使用し、ブール値を取得してif文で条件分岐を行う実装方法です。この方法は最もシンプルに利用できる実装です。
このタイプの実装は、UseCaseやState管理におけるロジックの分岐に活用されています。
次に、UIレイヤーでのFeatureFlagの制御方法についてお話しします。WINTICKETでは、useFlagというCustom Hooksを利用してFeatureFlagを制御できるようにしています。
このCustom Hooksは、主にUIのビルド関数内で使用されます。具体的には、ボタンが押されたときの処理や、Hooks内でのロジックをFeatureFlagによって分岐させる場合に活用されています。この方法により、UI層での柔軟な制御が可能になっています。
useFlagの実装は、FeatureFlagクライアントのgetメソッドをuseFutureで実行し、その結果をブール値として返却する仕組みになっています。この方法により、非同期で取得したフラグの値を簡単に利用できるようになっています。
もう一つの方法として、UIではFlagBuilderという専用のビルダーウィジェットを用意しています。これはロジックを伴わないシンプルなウィジェットの表示の出し分けを制御するために使用しています。FlagBuilderのビルダーメソッド内では、引数として渡されるフラグを使ってウィジェットの表示を分岐させることができます。
FlagBuilderの実装では、FeatureFlagクライアントの非同期なgetメソッドをFutureBuilderを使用して実行しています。この非同期で取得したFeatureFlagの値をビルダーの引数として渡すことで、呼び出し元でif-elseを用いた分岐制御が可能になります。この仕組みにより、UIの出し分けが簡単に行えるようになっています。
画面遷移時のフラグ制御方法についてです。WINTICKETのアプリでは、画面遷移にAutoRouteというパッケージを使用しています。
そのAutoRouteにあるRoute Guardsという機能を使用して独自のFlagGuardというGuardを実装して、指定のフラグのブールに応じて画面遷移を許可したり、遷移できないようにしたり、開発途中の画面にディープリンク経由で遷移できないようにも制御を入れています。
3つ目に、FeatureFlagの導入原則について話します。
各レイヤーにおける具体的なFeatureFlagの制御実装についてご紹介しましたが、WINTICKETのアプリでは「できるだけデータフローの根源に立つ」という導入原則に基づいて、どのレイヤーで分岐の制御を行うかを決定しています。この原則により、フラグの制御が一貫性を持ち、適切な場所での分岐が可能となるよう運用しています。
例えば、サーバーのAPIをV1からV2に変更したい場合、データフローの根源に近い部分でフラグ制御を行います。具体的には、サーバーリクエストの結果を受け取るドメインレイヤーでif分岐を使用し、V1とV2のAPIエンドポイントを切り替えるイメージです。このように、データフローが始まる場所で分岐を制御することで、制御が明確になり、管理が容易になります。
一方で、ボタンの色を赤から青に変更するようなUIのみの変更の場合は、色の変更をデータフローの根源と捉えて、UIレイヤーでフラグ制御を行います。このように、制御する内容に応じて適切なレイヤーを選択することで、効率的な運用を実現しています。
2. 従来のFeatureFlagを使用した開発
次に、従来のFeatureFlagを使用した開発についてお話しします。従来の開発フローを大まかにまとめると、以下のような流れになっていました。
まず、機能開発の実装を進める前に、設計フェーズとして実装方針レビューを行っていました。このレビューでは、機能の設計や実装方針について議論し、開発がスムーズに進むよう事前に課題や不明点を洗い出していました。
実装概要や具体的な実装手順を記載し、過去に発生した不具合をもとに考慮項目をチェックするためのドキュメントを作成していました。このドキュメントをもとに、約30分間チームメンバーを集めてレビュー会を実施していました。
レビュー会では、他のチームメンバーから考慮漏れの指摘や疑問点の解消を図り、可能な限り実装時に不具合や手戻りが発生しないように運用していました。このプロセスを経た後、具体的な実装フェーズに入っていきます。
まず、Work In ProgressタイプでFeatureFlagの定義を追加し、UIの改修やドメインの改修など、実装要件に沿ってFeatureFlagクライアントを使用して実装を進めます。
WINTICKETのアプリチームではE2Eテストが豊富に作成されており、これを利用してデグレードの検知を行っています。E2Eテストでは、基本的にFeatureFlagをオフにした状態でテストを実行し、CI環境で定期的にテストを実行する運用を行っています。
開発がある程度進んだタイミングで、チーム全体で動作確認を実施します。この際には、手元の開発用画面に用意されているFeatureFlagエディターを使用し、FeatureFlagをオンに切り替えて動作確認を行います。
動作確認が問題ないことを確認したら、QCチームへ手動テストの依頼をします。
ONに切り替える必要があるFeatureFlag名と、そのフラグの切り替え方法は、事前にチームメンバーに共有しておきます。QC(品質確認)で問題がないことが確認できたら、FeatureFlagのタイプをWork In ProgressからOPSに変更し、アプリを申請します。
申請が承認され次第、ビジネスメンバーとリリースタイミングを調整して機能をリリースします。FeatureFlagをオンにする際は、Remote Configを使用してフラグを操作し、機能をリリースします。
機能がリリースされた後は、Slackを使ってアプリチームに「開発見直しリマインダー」という棚卸しの通知を設定しています。リリースからおおよそ1ヶ月が経過し、機能が安定したと判断された場合、このタイミングでFeatureFlagを削除する運用を行っています。
WINTICKETでよく行っていた実装要件について整理していきたいと思います。
まず、UIに関する要件では、新しい画面を追加するなどの新規機能の追加と、既存のトップ画面を新しいデザインにリニューアルするといった既存機能の改修が挙げられます。例えば、投票履歴機能を新たに作成し、それに伴う新しい画面を追加するケースや、現在のトップ画面をより使いやすくデザインを変更するケースがありました。
ドメインに関しても同様に、新しい機能の開発に必要なサーバーAPIへリクエストを送る新規機能の追加と、既存機能を改善するために、例えばAPIをV1からV2へ変更するような既存機能の改修が行われていました。これらの要件をもとに、FeatureFlagを活用して柔軟に運用していました。
3.発生した不具合の分析と整理
次に、WINTICKETのアプリにおけるFeatureFlag周りで発生していた不具合の分析と整理についてお話しします。
WINTICKETでは、過去に機能の改修や追加を行う中で発生した不具合のケースをまとめ、それらの発生頻度を分析しました。不具合の頻度を可視化した結果、表のように具体的な発生状況が明らかになりました。このデータを基に、問題の傾向や改善ポイントを整理し、運用の見直しを進めています。
不具合が発生しやすかったのは、DomainとUIの改修を同時に行ったパターンです。まず、発生頻度が最も多かったDomainとUIレイヤーの既存改修を同時に行った場合について、具体的にどのような不具合が発生したかを説明します。
既存の実装では、UIがDomainからのイベントを購読し、Domainからイベントが届いたら、Domainを呼び出すフローになっていました。新規の実装では、このデータフローを変更し、①既存のDomainからイベントが届いた際に、新規で実装した別のDomainを呼び出し、その結果のイベントが届いたら、既存のDomainを呼び出すように改修しました。
この時、既存のデータフローは削除しましたが、新規実装のデータフローに制御を入れることで、実質的には同じ挙動になるようにし、ユーザーの見た目には影響が出ないように実装していました。
しかし、新規のデータフローにおけるイベント購読の実装にミスがあり、UIに正常にイベントが届かなくなる問題が発生しました。その結果、既存で実装されていたDomainが正しく実行されなくなりました。この不具合によって、既存の動作が正常に動作しなくなり、ユーザーから見た挙動も変更されてしまい、不具合につながりました。
不具合が発生したときも、既存のデータフローは削除して新規のデータフローで実施しつつ、既存と同じ挙動になるように実装していたため、既存のフローに切り戻すことが不可能な不具合になってしまいました。
理想は、新規のデータフローを実装しながら、既存のデータフローには手を触れずに残しておくことでした。そうすれば、FeatureFlagを使用して、新規のデータフローに不具合があった場合でも、既存のデータフローに切り戻すことが可能でした。
次に、Domainに新規実装を追加した場合と、UIを既存改修した場合に実際に発生した不具合について説明します。まず、UI改修時のみで発生した不具合のケースです。この場合、HooksやProviderのリッスンのコールバック内でロジックを分岐制御していました。
しかし、分岐漏れが発生していたり、FlagBuilderのbuilder内で、if文の制御外でWidget構築のためのロジックで分岐漏れが発生したケースがありました。
他にもUI関連では、Route周りでの不具合が発生したケースもありました。これはAutoRouteのGuard機能のインターフェースに関連しているのですが、FlagGuardで画面遷移を制御する際に、metaというプロパティにフラグを設定することが必須でした。しかし、この必須の設定をインターフェースで適切に実装できておらず、metaの設定を忘れることで、FlagGuardが指定されているにもかかわらず、実際には画面遷移の制御ができない事態が発生しました。
次に、Domainの新規追加時に発生した不具合についてです。FeatureFlagの制御を入れ忘れたため、既存の画面からアクセスされた際に、開発途中のDomainが実行されてしまうことがありました。これにより、未完成の機能がユーザーに影響を与える可能性があり、適切にFeatureFlagで制御することの重要性が再確認されました。
まとめると、既存回収が複数レイヤーで起こると不具合が発生しやすく、逆に全く新しい画面実装のような新機能の場合は、FeatureFlagで閉じる導線のみを制御すればいいので、不具合の発生頻度が低いことが分かりました。これらの実際に発生した不具合の課題に対するアプローチですが、大きく2つで、既存は触れずに残しておきながら改修できるようにすることと、制御忘れに機械的に気づけるようにすることです。
1つ目については、実際の不具合発生ケースでも話したように、新規のデータフローを追加しても、既存の実装には触れず残しておけば、最悪何かあったときにFeatureFlagで切り戻せることがわかりました。そのため、これに関しては既存の実装には触れずに新規の実装を加え改修できるアプローチを考えたいと思います。
2つ目は制御忘れに機械的に気づけるようにしたいということです。実装者もレビュー者も人間なので、忘れてしまう時はあり、信用しすぎるのは危険なことがわかったためです。できるだけ人間が直接関与して判断したり、意識することを減らすアプローチを考えたいと思います。
コードベース以外の考慮ですが、若手が多いチーム構成だったり、組織拡大期で人の流動性が高く、人の出入りが激しいことや、他の横軸並行タスクが多く、ヒューマンエラーが起こりやすい状況だったので、中堅メンバーの能力に頼らず、いつでも誰でも安全にFeatureFlag制御できるような実装制限をかけるようなアプローチを取りたいと考えました。解決したいことの整理ですが、アプローチは先ほど話した2点で、それらを若手から中堅まで誰でも同じレベルで可用性を向上させられるように実装上で制限をかけることを考えたいと思います。
4. 可用性向上のための運用戦略とその方法
次に、可用性向上のための運用戦略とその方法についてお話しします。運用戦略は、実際の不具合から考える戦略と、開発フローから見る戦略の二軸で話を進めていきたいと思います。
まず、実際の不具合から考える運用戦略についてです。先ほど整理した上位3つの不具合に対しては、シンプルな新規機能の追加制限を禁止し、既存の実装には全く手を加えないという実装制限をかける戦略をとることにしました。この戦略により、安定した状態を保ちつつ、新規の実装を安全に進めることができると考えています。
最後に、人間が忘れてしまう部分を機械に任せるという点についてですが、レビュー時にBotなどを使用して機械的に気づけるようにする戦略をとることにしました。
そのため、実際の不具合から考える運用戦略としては、既存の実装には全く手を加えないように実装制限をかけることと、機械的に気づける仕組みを取り入れるという2つの戦略を採用しました。まず、実装制限について説明します。実装制限をかける戦略ですが、制御レイヤーと分岐制御の制限という2つのアプローチを考えました。
制御レイヤーの制限についてですが、できるだけデータフローの根元であるDomainのみで分岐が完結するようにすることで、UIとDomain間でのデータフローのやり取りでミスが起きにくくなると考えました。例えば、Domain内でのみFeatureFlag制御の分岐を入れ、フラグがオンの場合は文字列を返し、オフの場合は空文字を返すようにします。UIでは、この文字列があるかどうかだけを意識すればよく、FeatureFlagの制御を意識する必要がなく、シンプルなフラグ制御が実現できると考えました。
理想としては、制御レイヤーをDomainに絞り、Domainだけで制御できるように設計することで、デグレードしにくい制御を実現できると考えました。しかし、ボタンの文言の切り替えをA/Bテストしたい場合や、ボタンを押した際の画面遷移先を変更したい場合など、UIのみの改修が必要な場合は、UIでしかFeatureFlagの分岐ができないため、Domainだけに制限することは難しいという現実的な課題もあります。
そこで、制御レイヤーについては、従来通り、基本的にUIとDomainのみに制限することにしました。それ以外の特殊な例外に関しては、一部Stateレイヤーでの制御も許容する方針としました。
次に、分岐制御の宣言についてです。これまでの実際に発生した不具合ケースから学んだこととして、FeatureFlagをブール値で扱うと、自由度が高すぎて簡単に複雑なロジックの制御が可能になってしまうことが分かりました。
例えば、既存のif文にFeatureFlagを組み合わせたり、既存の論理演算子にFeatureFlagを加えたりすることで、複雑な分岐が発生する可能性があります。WINTICKETのアプリでは、ドメインにおいて複雑なFeatureFlagの分岐が発生するケースはこれまであまりなく、特に問題と感じたことはありませんでした。そのため、UIのみに制限をかけるというアプローチを考えました。
具体的にこれまでUIでWidgetの分岐を行う際には、Flag BuilderというWidgetを使用して制御していました。このビルダーは引数としてフラグのブール値を受け取り、実装者がbuilderメソッド内で自らif文を記述して制御する必要がありました。
そこで、シンプルなブールで制御するインターフェースを廃止し、onBuilderとoffBuilderというインターフェースに変更しました。これにより、フラグのif分岐を実装者に委ねることをやめ、より安全かつ簡単に制御できるようにしました。この変更により、既存のWidgetはoffBuilderにコピペして実装を逃がすことができ、新しく実装するWidgetはoffBuilder内に閉じ込められることになります。これによって、既存のUIを触ることなく、安全にUIの制御を行うことができるようになりました。
この時、図のように既存のWidgetはoffBuilderに逃がし、手を触れずにFeatureFlagで切り替えられるようにしています。これにより、既存の機能に影響を与えることなく、新しい機能の実装を進めることができ、より安全にUIを制御できるようになりました。
しかし、回収の仕方によっては、この例のようにFeatureFlagで切り替えたい部分は一部のロジックのみですが、それ以外の変更がない箇所も冗長に記述する必要があり、少し手間が発生することがあります。ただし、今回は安全にFeatureFlagの分岐ができるように、可用性を重視してこのような実装制限をかけることにしました。
最後に、「人間が忘れてしまうところは機械に任せたい」という点についてですが、レビュー時にBotなどを使用して機械的に気づけるようにする戦略をとることにしました。例えば、新規ページ追加時のFlagGuardの設定忘れに関しては、FlagGuardの追加や、FlagGuard追加時のmetaの設定忘れをプルリクエスト作成時にDangerで指摘できるようにしました。この方法により、人的ミスを減らし、より確実な運用が可能になりました。
DangerはCIプロセス中に実行できるツールで、一般的なコードレビュー作業を自動化することができます。これを使用して機械的なレビューを行うコードを実装すると、プルリクエスト作成時にボットが対応したコメントを自動でしてくれるようになります。生成AIほどの知能は必要ない機械的なレビューに関しては、Dangerで十分対応可能な場合が多いため、おすすめです。
また、UseCase追加時にFeatureFlag制御を忘れてしまう場合についても、同様にDangerを使用して、FeatureFlagの制御がなければ機械的にコメントするようにしました。
次に、運用戦略の2つ目、開発フローから見る運用戦略についてです。開発フローで見た場合の戦略ですが、設計時にこれまで通り実装方針レビューを行うようにし、その際に作成するドキュメントにFeatureFlagについてのセクションを追加しました。このセクションでは、どこでどのようにFeatureFlag制御を行うかを明確にし、設計段階から考慮できるようにしました。
また、設計時にはこれまで30分のミーティングを取って実装レビューを行っていましたが、考慮されているかどうかに関わらず、30分が過ぎると実装が始まってしまうことがありました。そこで、実装方針レビューもプルリクエストでレビューする体制に変更しました。これにより、ミーティングなどの時間を取らず、他のコードレビューと同じようにレビューしてもらうようにしています。
実装時には、これまでFeatureFlagがオフのときのみE2EをCIで実行していましたが、E2Eの実行フローを見直し、FeatureFlagがオンのときとオフのときの両方でテストシナリオをCIで実行できるように変更しました。これにより、FeatureFlagの状態にかかわらず、全体のテストカバレッジが向上し、より堅牢な運用が実現できるようになりました。
また、万一の時に備え、実装者が誤ってOpsタイプのFeatureFlagを参照して機能実装を行った場合、すでにそのフラグがオンだと開発中の機能がユーザーに見えてしまい危険です。そのため、誤ってフラグがオンになっている場合に警告を出すように変更しました。
リリース時には、Work In ProgressタイプからOPSタイプにフラグタイプが変更された際に、フラグが使用されている箇所を確認できるGitHubのURLをDangerでコメントし、最終的にどこでどのようにFeatureFlag制御が行われているかを確認できるようにしました。この仕組みにより、リリース前にFeatureFlagの実装全体を確認でき、より便利に活用できるようになっています。
今回は、可用性が低下していた状況で、迅速に可用性向上を目指して戦略と対策を立てました。そのため、検討はしたものの採用しなかった方法もいくつかあります。例えば、Git Flowの開発やより根本的な解決としてプロジェクトコード全体のリファクタリングは、結果が出るまで時間がかかるため、今回は採用しませんでした。また、論理的には他の部分でも同じ課題がある場所もありましたが、不具合が発生していない部分については対応せず、実際に不具合が発生した部分のみを重点的に対応しました。
さらに、可用性向上以外で便利さや理想型を追求する部分については、今回は見送りました。
5. 対応した結果と今後の展望
最後に、対応した結果と今後の展望についてお話しします。今回の対応により、従来のようなFeatureFlagによる制御漏れのミスはゼロになり、現在のところ不具合は発生していません。
実装時のFeatureFlag制御において、良い意味で自由度がなくなり、誰でもFeatureFlag設計を考えられるようになった結果だと思っています。これにより、運用の一貫性が高まり、エラーのリスクが減少しました。
ただし、これまでシンプルにbool値で制御できていたことができなくなったため、実装者がFeatureFlag設計で悩むことが多くなり、どうやって制御するかを議論する場面が増えました。これに関しては、可用性を考慮して、迷わず誰でもスムーズに実装できるようにするための改善余地があると感じています。
今後の展望としては、先ほども触れたように、可用性以外の利便性向上にも対応していきます。現在はリリースタイミングにフラグをWork In ProgressからOpsに変更する作業を手動で行っていますが、これを自動化することが一つの改善点として挙げられます。また、迷いがないFeatureFlagの実装やA/Bテスト設定の自動化、さらに現在Dangerで行っている指摘をもっとシフトレフトで気づけるように、カスタムリントで指摘できるように変更することも考えています。
ご視聴いただき、ありがとうございました。