大規模システムの開発とデリバリーというドキュメントで紹介されている機能トグル(Feature toggles)の実装方法について。
機能トグルとは
上記の「大規模システムの開発とデリバリー」には
機能トグルはアプリケーションベースのリリース手法です。本番コードをデプロイすることなく機能の有効/無効を切り替え、システム動作を変更するための仕組みを備えています。
と書かれています。実現方法としては、以下の通り。
一般的に機能トグルは、アプリケーションロジックやUI要素を条件文でラップして実装し、保存された構成設定に基づいて機能を有効化/無効化します。
これを、OutSystemsで実現する方法について検討してみます。
確認環境
Personal Environment(Version 11.12.0 (Build 30002))
Service Studio (Version 11.11.9)
Reactive Web Appを作って動作確認してみます。
実装中の機能を含めたまま、リリース可能にする
OutSystemsのコード管理にはブランチ機能がなく、環境ごとに1つのTrunkのみがあるような構成です。
つまり、リリース済みのアプリケーションを追加開発中に、バグフィックスなどでリリースを行うとバグフィックスに開発中の機能がついていってしまう。
こういうときには、上位環境で直接修正(=ホットフィックス)し、その後その修正を手前の環境にも反映するという方法があります。
その他に、開発中の機能を有効にするかどうかを判定するフラグを用意し、開発環境でだけオンにすることで対応することもできます。これが機能トグルですね。
フラグはサイトプロパティで管理する
フラグは、環境ごとに1つしかないのでサイトプロパティに保存するのが良さそうです。
Boolean型でIsFeatureEnabledというサイトプロパティを作りました。うっかり本番で有効にならないようにDefault ValueはFalseに設定。
機能トグルを有効にしたときのみ表示するUI
Screen Template「Admin Dashboard」を作って動作確認用画面を用意します。
ここに、機能トグルを使って、特定環境でのみ表示されるUIを作ってみます。
配置する先は、タイトルの横辺り(上のスクリーンショットで黄色に塗った部分)。
サイトプロパティをData Actionで取得する
サイトプロパティはサーバサイドにあるので、Data Actionを定義して画面から触れる場所に持ってきます。
画面を右クリック → Fetch Data from Other Sourceを選択。
以下のように実装します。サイトプロパティをData ActionのOutput Parameterに編集するだけ。
Data Actionの出力変数で表示を切り替えるUI
If Widgetを配置し、そのConditionにData Actionの出力変数(サイトプロパティの値を編集)を設定。これで、サイトプロパティIsFeatureEnabledをTrueにしている環境でだけ、Trueの分岐のUIが表示されます。
開発担当者によるフラグ設定
この場合、開発中の環境でのみサイトプロパティのフラグをオンにします。開発環境なので作業は開発担当者。
開発環境のService Centerでサイトプロパティを定義したモジュールの編集画面を開きます。
Site Propertiesタブを開き、IsFeatureEnabledのリンクをクリックして値をTrueに設定してApplyボタンをクリック。
開発以外の、QAと本番はデフォルトのFalseのままにしておきます。
特定ユーザーにのみ機能を提供する
上記とは別のパターンの機能トグルとして、特定のグループのユーザーにのみ新機能を提供し、問題がないことを確認したら徐々に提供するユーザーを増やしていく(カナリアリリース)場合。
例として、REST APIで提供されているサービスを別のサービスに切り替える事を考えてみます。同じライブラリをそのまま使いつつも、リクエストしたユーザーが特定ユーザーである場合、リクエスト先を別のサービスに切り替える。
アーキテクチャ
こういうケースでは、OutSystemsが推奨するアーキテクチャパターンがあります。
連携パターンです。といっても、外部サービスをConsumeするモジュールを直接アプリケーションから呼び出さず、間に抽象化するモジュールを1つかましておこうという程度の話ですが。
上記図の各項目は以下の通り。
- 旧サービス:移行前の、現状利用中のサービス
- Integration Service1:旧サービスをConsumeするモジュール
- 新サービス:移行後の、新サービス
- Integration Service2:新サービスをConsumeするモジュール(新設)
- Core Service:利用側アプリケーションから直接呼び出すモジュール。このレイヤを、移行要件が出てくる前から噛ませておくことで、今回のような要件が出てきたときも、利用側アプリケーションの実装に影響を与えずに変更を加えられます。
Core Serviceに加える変更
Core Service内のPublic=YesのActionの先頭にIfを配置します。
IfのConditionで問題の特定ユーザーに該当するかどうかを判定し、該当する場合は新サービス側のモジュール(Integration Service2)、それ以外なら旧サービス側のモジュールをこれまで通り実行させる実装にします。
特定ユーザーの判定にはいくつか方法が考えられますね。
- Role:モジュール内に作成したRoleにはCheck Actionで判定できます
- Group:Usersアプリケーションで定義した特定のGroupに所属するかどうかで判定する方法。(System)にあるGroup_User Entityが使える
- 管理用Entity:対象ユーザーを管理する専用のEntityを作成する方法
公式ドキュメント
Feature toggle in OutSystems
2021/7/24時点では、日本語訳がないようです。