Feature Toggleについて調べてみた
前から何回か興味を持ってるんだけど、ちょっとまとめて調べながら思ったことをザクザク吐き出しておくよ。
今のところ考えるちょうどいい使い方
いろんな使い方ができると思うんだけど、リリースサイクルの都合ではなく
- どんな機能が現在のプロダクトで切り替え対象となっているのかの可視化 ( admin panel )
- サーキットブレイカー
の意味で使うのを前提にしつつ、
- カナリアリリース
- A/Bテスト
にも導入していく、くらいの感じだとよさそう。
大げさな感じがするかもしれないけど、ちゃんと考えて入れないとややこしくなるだけだなと感じているので。
雑な言い方すると feature toggle って global な状態分けの if ブロックなわけで、実際、特別な記法なんかなくたって環境変数と if だけで実現可能なわけですよ。でもそれって実装側からもプロダクトオーナー側からも実態が見えにくくなるだけでいいことないので、なぜそれが有用なのか?を説明できる状態、機能を実現してなきゃダメだよな、と思うわけです。
基本的には避けられるものなら避けるべき
全体的に feature toggle でリリース管理していくのは危険な感じがする。クライアントサイドやアプリでは、時限リリースなど、マーケットが挟まることで uncontrollable になってしまう部分には使わざるを得ない場合があると思うけど。
普通は 追加するより消す方が怖い ので、消されないで放置されるフラグが増え続けることは容易に想像できる。リリースサイクルのコントロールよりも duration や user segmentation などのメリットを重視してやった方がよさそう。
また、サーキットブレイカーのような、消したらダメな機能もある。そういう違いが admin panel 上で可視化できるとよさそう。
※ 小さいプロダクトの立ち上げ期で次々 feature toggle で出し入れしなきゃいけない状況はあり得るっちゃああり得るけど、それは技術的に解決するものではなく WHY に立ち向かっていない状況のように見える。実装は同時並行で行なって短時間で検証をくり返す、言葉で言うとかっこいいけど、聞いただけで事故る可能性が高い(同時並行のくだりのあたり)し、本当にスモールな時って、そもそも多人数で同時並行開発できないので、feature toggle とか考えようがなくね?という気もする。まぁ、もしかしたら自分の知らない魔法の世界があるのかもしれない。
SaaS
https://launchdarkly.com/pricing/
75 USD/mo
ちょっと高いかなー。でも機能がすごい。これ全部実装するのは確かに大変。user の segmentation も webhook もみんなある。ユーザーベースの拡大がビジネスチャンスの拡大に繋がるプロダクトにはよさそう。
Admin Panelとスピードと履歴が重要
Admin Panel はかなり重要な要素になると思うんだけど、真面目に作るとそこそこ重たいので、複数のサービスをまたいで使えるとよさそう。というかイマドキはまたげないときつそう。サービスをまたいで feature toggle を実現するには CDN でスピードを稼ぎやすい仕組みが重要な気がする。例えばサーバが JP にあったり US にあったりするはず。1
そして admin panel 上の操作は履歴を残すことが重要。なんなら同時に通知を飛ばすなどがあってもよいかもしれない。(PubSub でいいか?)
feature の追加、削除はどこで?
- admin panel で追加、削除すると実態(実装)と乖離する可能性がある
- 各サービス(アプリ)側で追加、削除の order が出せるのが理想的?
- 追加、削除の履歴はコードの VCS 側に残る形か
調べてみた
http://featureflags.io/ より。先の LaunchDarkly 提供。
気になっているのは、
- backend storage はどうするのか?
- admin panel はどうするのか?
- frontend ではどうしているのか?
frontend で feature toggle はー、いるんだろうか? Node.js でバックエンドならまだしも。JSアプリケーションを初期化する cell をバックエンドで rendering するかしないかで切り替える方が素直な気がするなぁ。
flip gem
参考になる。
Admin Panel までコミで、ちょうどいい感じがする。
feature gem
DSL 部分の実装がよさげ。
https://github.com/mgsnova/feature
- separeted repository
- in-memory or redis or static YAML or ActiveRecord
- cache されるし force refresh! もできる
Repository が分離しているのは非常によい。refresh! もできるので、例えば Central Repository を分離しておいて Central Repository に Admin Panel を設置、Central Repository から必要な情報を取得して Repository に保存しつつ、Central Repository が更新されたら PubSub で Repository を更新する、といったことが可能なはず。
Unleash npm
こりゃすごい。
- Admin Panel ( Server ) と Client SDK を持つ
- Java / Node.js / Go / Ruby / Python / .NET
- Heroku-ready
- storage は PostgreSQL 固定?
- userId とカナリアリリースっぽいものに対応
これすごいな。 LaunchDarkly の OSS 版ぽい感じ。ただ、都度アクセスが必要になりそうなので、cache がないとサーバの位置によってはちょっとつらそう。
bandiera gem
監視体制が参考になる。
https://github.com/springernature/bandiera
- サーバサイドは Ruby
- Client SDK は Ruby / PHP / Node.js / Scala
これ自体が中央のサーバになるので監視ものがいろいろ最初から考慮されている。
chanko
https://github.com/cookpad/chanko
Rails アプリの中で toggle する機能に関するコードの置き場所を安全に分離する DSL. user segmentation 対応。
確かにねぇ、View 以外も分けたいとなった時にコードの置き場所に困るのは事実。
rollout gem
https://github.com/FetLife/rollout
- DSL の部分はあまりイケてる感じがしない
- Redis固定
- Service あり ( https://github.com/fiverr/rollout_service )
- dashboard アリ ( https://github.com/fiverr/rollout_dashboard/ )
API サーバも Dashboard も作ってあって真面目にやってる感じがする反面、DSL や Redis 固定の部分はイマイチかなぁ。
flagship gem
https://github.com/yuya-takeyama/flagship
- dependency free
- flagset を DSL で定義できる
- この中でもさらに条件分岐できる
- ちょっと難し過ぎる気がする
- no storage
admin panel を別立てにできなさそうに見える。
少なくとも DSL での定義を通過する必要があるので、deploy / restart は必要な気がする。環境変数を参照する部分は反映し直しやすいけど、それでも restart は必要? でもそれだと目的を達成できないような気がするので何かを見落としているかも。
feature-toggles gem
https://github.com/LouisSayers/feature-toggles
YAML storage 固定
まぁ YAML dump する script があれば admin panel を別立てにすることもできるけど、YAML storage ってことは deploy し直さないといけないので、そこはイマイチ。feature gem でいいかな。
参考
- システム障害のおわびとまなび - freee Developers Blog
- 「新機能作成時に開発ブランチに細かくmergeしていく戦略」について社内勉強会で発表しました - Hatena Developer Blog
- フューチャブランチの発展は継続的インテグレーションの衰退である
- 第3回 ブランチvs.フラグ:Comparators—比べてみればわかること|gihyo.jp … 技術評論社
- 開発中の機能を小分けにして本番環境にどんどん出すためには - hitode909の日記
主に Heroku の利用が視野に入っているため。 ↩