お客様に価値を提供し続けるために2022年に挑戦したこと、来年に向けて

この記事はVoicy Advent Calendar 2022の25日目の記事です。 qiita.com

Voicy Androidエンジニア、Personalityチームの@numaMykです。

今年、実は色々な挑戦と失敗を経験した年で、個人的に人生を大きく揺るがすイベントがいくつも発生しました。

失敗から学び挑戦を始めた2022年

Androidアプリでポストモーテムが発生したことをきっかけに、flakyな設計部分や顧客の信頼をゆるがす要因となりうる課題を探し、小さく細分化して、リファクタリングや修正を行いました。 ポストモーテムをきっかけにVoicyの開発組織*1にQualityチーム*2という、不具合対応の優先順位づけやUrgentレベルとなる課題に向きあう専属チームが誕生しました。 このチームが誕生してから、自チームの機能開発以外の問い合わせ対応に向けられていたところを担ってくれることとなりました。 また、問い合わせ対応を担うCSのメンバーも入社してくれたりと今年はさらにいろんな人に支えていただいて開発できていることを実感した年でした。

もちろん、サービス品質をあげることは全エンジニアの課題で、ユーザー報告を受けるSlackの監視や普段使いしていますが、 Voicyの顧客にとって何が優先すべきなのか判断し、組織全体を俯瞰して即時に行動を起こしてもらえるチームがいることで、より自分が担っている機能開発にマインドシェアを向けることができました。

私の内省というと、瞬時な意思決定や他メンバーを巻き込んで課題に向き合うことを遂行する力に未熟さを感じていました。

私が属するPersonalityチームはパーソナリティ向けに大きな機能開発リリースを控えていました。 サービス品質を維持しながらユーザーの信頼を損なうことなく、それでいて保守的にならず価値を提供し続けていくための策としてFeature Flagを用いることを目標に置きました。

この記事ではVoicyでのモバイルアプリでFeature Flagを導入していく中で得た知見と課題を紹介できたらと思います。

Feature Flagとは?

Feature Flag を知ったのは2019 GDG DevFestでLINE Android開発チームの玉木 英嗣さんのセッションでした。 www.youtube.com

Feature Flagは、新機能のリリースを行う際、コードに修正を入れずに分岐を使って有効化または無効化する開発のことです。 分岐処理を用いることでユーザーに新機能を見せない状態で開発を進めることが可能です。 また、フィーチャーフラグは、必要に応じてコードをロールバックする際にも有効です。

プログラムを書かない人にも伝えたく、ねじ曲げて伝わらないか心配ですが、比喩表現を使わせてください。

if もしもというドラマをご存知でしょうか。

wikipediaより引用)if もしも…人が皆、孤独な旅人であるとしたら、貴方はやがてある二股の分かれ道に突き当たるのです。 右に行くべきか左に行くべきか貴方は大いに迷う。或いはうっかり気づかなくて通り過ぎてしまう。 かくして現在の貴方があるわけですが、ひょっとして別の道を選んでいたほうが幸せになれたかもしれないのです。 もしも、こっちを選んでいたら…if もしも…

このドラマは一話ごとにとある人物のライフステージの中で分岐点が存在し、そこから枝分かれした2通りのストーリーがそれぞれ描かれています。

ソースコードの中でもさまざま条件分岐が随所で存在します。 Feature Flagでも条件分岐を使用して、機能が有効なら〇〇する、無効ならXXするというふうに処理を分けることで、ユーザーに新機能を隠しながら段階的に機能を展開していきます。 また、Feature Flagは、必要に応じて機能を無効にすることも可能なので、ロールバックする際にも有効です。

Feature Flagに求める要件

Feature Flagに求める要件を松竹梅の形で区分けし、今回のPersonalityチームで機能開発にFeature Flagを用いるために必要最低限のスコープを定めて、今回は梅に定義している要件が満たせることを目指しました。

  • ダークリリースフラグ
  • 本番にリリースされているけど、一部のユーザにしか使えないようになっている
  • 特定の人や特定属性に対して機能有効・無効を切り替える
  • 不具合が出た場合、コード修正やリリースを行うことなくロールバックしたい
  • トランクベース開発
  • レビューが楽になる:変更箇所は最小限に抑えることで、プルリクエストのレビューのストレスが軽減される
  • バグが減る:変更箇所のスコープが狭くなることにより、バグが入り込むリスクを減らす
  • コンフリクトが起きなくなる:短期間でマージすることにより、マージする際のコンフリクトを減らす

  • ABテストフラグ
  • コンバージョン率を測る

  • パーセンテージで機能を有効にするユーザーを決める
  • 管理画面にて機能のオンオフ

Firebase Remote Config および内製のPros, Cons

Firebase Remote Configには決定的な欠点がありました。それはFirebase SDKに依存するためリアルタイム性の担保ができないことです。 例えばとあるuserがremoteConfigのfetchをした後にremoteConfigの値に影響される機能がリリースされると最大12時間はfetchされない可能性があり、remoteConfigの値が反映されないということは起こりえました。

Voicyバックエンドで内製する場合、既にアプリでリクエストするAPIのレスポンスとして返すことができれば、即効性があることは明らかでした。 他の機能でも恒久的にFeature Flagを使用していくとなれば、機能表出に時間的制約があっても気にしないくていいようリアルタイム性はほしいところです。

ですが、今回の機能開発は、期間限定のキャンペーンのようなものではないため時間的制約はありませんでした。

ひとまずFeature Flag自体恒久的に使用するかどうかの判断しうるための経験がないこともあり、比較的にミニマムにFirebase Remote Configを使う判断をしました。

Feature Flagを使用する中で見えたメリットと課題

カナリヤリリースしない限り、本番リリースに伴う不確実性は解消されない

Feature Flagの大きなメリットでカナリヤリリースがあります。はじめから全てのユーザーに公開するのではなく対象のユーザーを絞り、本番環境で実証実験的に公開しテストすることで、検証環境で出ることがないような障害が発生した場合にもユーザーへの影響を最小限におさえることができます。

今回の機能開発では本番環境でユーザーに見えるのは機能を全体公開するときであるため、機能公開日に不確実性と向き合うことには変わりないです。

とはいえ、社員に解放し早く本番環境でテストできる(早く失敗できるとも言える)ことで得るものは大きいと考えています。

トランクベース開発で開発者体験が向上

もしFeature Flagを用いず段階的にリリースしない場合、日に日に肥大していくFeatureブランチに他チームのリリース内容を都度取り込みコンフリクト解消にリソースをかけることになります。

Feature Flagを使えば、小さなPRをマージすることができ、ブランチの生存期間が短くコンフリクトの発生を少なくすることができます。 短いサイクルで施策改善していく他チームと協働開発する上で、一番メリットに思えたことでした。

機能表出のリスクを伴う

当たり前なことですが、まだ未完成な機能をユーザーに見せてしまう危険性と隣り合わせです。 Feature Flagのオフの状態のテストケースを精緻に行っていても、エッジケースなどの考慮漏れがあると一発で露見してしまいます。

コンフリクトにかけるマインドシェアが省けた一方で、モブプロでiOSAndroidの設計を精緻に合わせることに時間をかけました。

低凝集なソースコードにFeature Flagが入るとカオス

既に条件分岐や状態遷移の激しい箇所にさらにFeature Flagをいれると単純な処理でも頭を悩ませることになります。 if文がネストしたり、And条件がいくつもあることになってしまいます。

できれば、そういったケースでは処理をカプセル化したりBuilderなどのデザインパターンを用いて条件分岐を丸っと内包させることで可読性もあがり、Feature Flagを除去する際にも容易になると思います。

来年に向けて

今年はFeature Flagを用いてユーザーに価値を届けることを挑戦してきました。 来年はリリースに近づいていくにつれて違った気づきが得られそうです。 来年も感謝と挑戦する気持ちを忘れないようにしたいと思います。

参考文献

https://martinfowler.com/articles/feature-toggles.html https://firebase.google.com/docs/remote-config?hl=ja