Feature Flags 正在毀了你的 Codebase
覺得我們的內容實用嗎? MyApollo 電子報讀者募集中!歡迎訂閱電子報!
Feature Flags 是上線新功能時很常使用的 1 項技巧,它的作用是可以讓我們迅速地開關特定功能,例如下列 Python 程式碼範例,可以透過設定檔切換新舊的付款服務:
USE_NEW_PAYMENT_SERVICE = config.get('NEW_PAYMENT_SERVICE') is True
if USE_NEW_PAYMENT_SERVICE:
...(the new logic)
else:
...(the old logic)
Feature Flags 雖然方便,不過卻也帶來不少問題,這些問題你我都應該知道或親身體驗過,只是我們多數不像 “Feature flags are ruining your codebase” 1 文的作者那樣將 Feature Flags 的利與弊整理得如此清楚,推薦可以花點時間將該篇文章閱讀一遍,不僅會有很多既視感浮現,還能知道未來怎麼做的更好。
我自己總結如下:
- Feature Flags 很好用沒錯,但要視為最後手段。如果一項功能該上線/下架就勇敢上線/下線,不要做 Feature Flags 讓 PMs 有隨時開關的機會,因為 PMs 很可能會一次食髓知味,之後把各種實驗性的想法都推到 production 環境,甚至讓功能的發想、研究、驗證等過程變得草率,這一切就是因為對 PMs 來說功能的上線/下線變成成本很低廉的事,進而忽略其他人需要付出的成本,這些成本包括,開發者需要將 Feature Flags 的邏輯放入程式碼之中,簡單的話,可能就 x 2 的程式邏輯,不簡單的話就可能是 x N 的程式邏輯,更可怕的是 Feature Flags 之間產生交互作用的情況,例如 A, B Flags 各有 2 種情況,那麼它就會產生 4 (2x2) 種程式邏輯,這些額外產生的邏輯對測試人員也是 1 種成本,因為要測試的案例變多了。
- Feature Flags 會對 Codebase 的後續維護造成困擾。個人的經驗告訴我,這些 Feature Flags 上線之後,也很少人會去關心它打開/關掉的後續問題,所以程式碼就會一直存在這些 Flags, 隨著存在時間變長,它存在的原因也就逐漸被淡忘,一旦遇到需要維護、升級的情況,就會有倒霉鬼需要扮演程式碼考古學家,需要找到當初開發的文件、 PM 、開發者釐清原因,進而決定後續處理步驟,但多數情況不會如此順利,甚至可能沒人想大冒險,因而決定繼續留下 Feature Flags, 直到下一個倒霉鬼又出現。
至於可能的解決辦法則是:
- 為系統可同時容納的 Feature Flags 設定上限,如果 Feature Flags 超過一定數量,就讓測試直接失敗,強迫有人重視這個問題(但是需要團隊有此共識)。
- 為每個 Feature flags 設定合理的失效時間,如果 Feature Flags 達到失效時間也讓測試直接失敗,強迫團隊移除不必要的 Feature Flags 。
- 每個創造 Feature Flag 的開發者或 PM, 應該都要為該 Feature Flag 負責,後續都應該要有 ticket 進行追蹤,才能讓大家意識到 Feature Flag 有其成本,並謹慎使用 Feature Flags 。
總之,每次要用 Feature Flag 時,都應該要捫心自問「必要嗎?」