一部のユーザーの機能を非表示/無効にする


10

アプリの無料版と有料版があるとしましょう。有料版は、ユーザーが利用できる機能に関する無料版のスーパーセットです。つまり、有料版は無料アプリのすべての機能に加えて追加機能を備えています。

起動時にロードされるフラグ(無料/有料など)に基づいて機能の可用性を切り替えるパターンはありますか?

どこにでも以下のコードブロックを用意するのは好きではありません。

if(isFreeVersion){
    // ...
} else {
    // ...
}

すべてのバージョンのために2つの別々のgitのブランチを持つことは、それは2を維持(またはそれ以上)のコードのソースを意味しますので、オプションではありません、一般的には非現実的と思われる、よりここで議論されています。バージョン管理で同じコードベースから二つの個別のソフトウェアバージョンを維持します

これを行う方法はありますか?それでも、単一のコードベースがあり、無料/有料フラグをチェックする条件ステートメントでコードを散らかしていませんか?

これは以前に何度も議論されたと確信しており、この問題に取り組むためのいくつかのパターンがあると確信していますが、それを見つけることができません。

Android / Javaを使用しています。



@gnat tnx、素敵な発見。しかし、個別のブランチを必要とせず、複数のコードベースを維持する必要のないオプションについて説明したいと思います
TadijaBagarićMay

2
これは、異なる認証レベルを持つことに似ています。機能が特定のユーザー/ロールでのみ利用可能である場合、その問題への一般的な対処方法を調べることができます。
バートヴァンインゲンシェナウ2018年

@BartvanIngenSchenau私はほとんどの場合if、禁止されている機能のコントロールを非表示にするためのチェック、またはユーザーが許可されていないことをしようとしたときにポップアップダイアログを表示するためのチェックであると思います。コードで多くの条件を回避する方法を見つけたいと思っています
TadijaBagarić18年

2
ポリフォリズムを使用します。このifステートメントについてもう一度自問する必要はありません。維持するのがとても簡単になります。
スティーブシャマイラード2018年

回答:


14

条件付きのlike if(isFreeVersion)は、コード内で一度だけ発生する必要があります。これはパターンではありませんが、その名前を知っていると思います。これはDRY原則と呼ばれています。「if(isFreeVersion)」のようなコードがコードの複数の場所にあるということは、この行/そのロジックを繰り返したことを意味します。つまり、繰り返しを避けるためにリファクタリングする必要があります。

if(isFreeVersion)」を使用して、さまざまな機能の内部構成オプションのリストを設定する必要があります。結果のコードは次のようになります。

 if(isFreeVersion)
 {
      feature1Enabled=false;
      feature2Enabled=false;
      maxNoOfItems=5;
      advertisingStrategy=new ShowLotsOfAdvertisementsStrategy();
      // ...
 } 
 else
 {
      feature1Enabled=true;
      feature2Enabled=true;
      maxNoOfItems=int.MaxValue; // virtually unlimited
      advertisingStrategy=new ShowMinimalAdvertisementsStrategy();
 }

これにより、単一の「isFreeVersion」フラグがさまざまな機能にマッピングされます。機能コントロールにさらに複雑なパラメーター化が必要な場合は、個々の機能に個別のブールフラグを使用するか、または他の種類のパラメーター、たとえば共通のインターフェイスを持つ異なる戦略オブジェクトを使用するかをここで決定できます。

これで、無料バージョンと有料バージョンの内容を1か所で制御できるため、このロジックのメンテナンスが非常に簡単になります。if(feature1Enabled)(DRYの原則に従って)多くのステートメントでコードが乱雑にならないように注意する必要がありますが、このチェックのメンテナンスはそれほど難しくありません。たとえば、既存の有料機能を無料にする場合(またはその逆)に変更する必要があるものをより適切に制御できます。

最後に、機能の切り替えに関するFowlerのブログ記事を見てみましょう。ここでは、機能の切り替えポイントについて説明しています。一つの中心的なポイントを引用させてください:

新しい機能コード内のすべてのコードパスをトグルで保護しようとせず、ユーザーをそこに誘導するエントリポイントのみに焦点を当て、それらのエントリポイントをトグルします。

したがって、全体的な戦略として、ユーザーインターフェイスに焦点を合わせ、特定の機能を表示または非表示にするために必要な最小限のポイントにチェックを制限します。これにより、コードベースをクリーンに保ち、不要な混乱を防ぐことができます。


5
基本的に、IsFreeVersionをFeaturexEnabledに置き換えましたが、呼び出し回数を減らしていません。私はそのようなケースを正確には持っていませんが、メニューの作成時にユーザーに表示されないはずのオプションを無効にすることで、常に同じようなことを処理してきました。ほとんどの場合、これはフォームの作成時ですが、ポップアップメニューを準備するときに実行しなければならないことがあります。
Loren Pechtel、2018年

1
@LorenPechtel:私の答えをもう一度注意深く読んでください。実際に条件付きテストの数を減らすために2つのことを述べました。1つはDRYの原則、もう1つはUIのテストに焦点を当てています。さらに重要なのは、のような非特異的なフラグをマッピングisFreeVersionする特定の最もこれらのテストの痛みの特徴パラメータを削除し-彼らは実際に理解するために開始され、任意のより多くのメンテナンスの混乱を生じません。
Doc Brown

9

if/elseブロックが気に入らない場合は、継承を使用するようにそれらをリファクタリングできます(Marin Fowlerのリファクタリングブックの条件付き多態性による置換を参照)。これは:

  • コードについて推論することを少し簡単にします。

  • 1つは無料バージョン用、もう1つは有料バージョン用の2つのクラスを作成できるようにします。これにより、他のクラスに呼び出しがディスパッチされ、無料バージョンと有料バージョンの区別が2つのクラスに制限されます(3つは基本クラス)。

  • 後で、安価なバリアントやプレミアムバージョンなど、他の形式のソフトウェアを簡単に追加できるようにします。別のクラスを追加し、それをコードで1回宣言するだけで、コードベース全体が期待どおりに機能することがわかります。


3
これには実装の継承が必要ないことをもっと明確にしたいと思うかもしれません。もう1つの利点は、無料アプリをプレミアム機能なしで提供できることです。Javaバイトコードを変更してif条件を常にtrueにすることは、それほど難しくありません。
JimmyJames、

6

機能切り替えパターンを適用すると、あなたの質問はかなりうまく解決できるようです。

よくあることですが、Pete Hodgsonはこのパターンを適用する際に直面する可能性のあるすべてのシナリオを1つの記事で説明しました

このパターンをサポートするいくつかのライブラリもあります。私はJava でFF4Jを使用した経験がありましたが、次のように入力したと思います。

feature toggle <whatever language you prefer>

...どの検索エンジンでも、いくつかのソリューションが得られます。


1

これを実現する方法は複数あります。単純明快な方法は、非常に多くの記事で提供されている機能切り替えパターンを使用することです。次のアプローチは、プラグ可能な機能の設計に関係しています。AndroidとIOSの両方にアプリ内決済があります。その支払いに加えて、ダウンロードの可能性があります。

サーブレット、JAMES Mailet、さらにはIDEプラグインを見ると、それらはすべてプラグインアーキテクチャの概念を使用しています。

  • アプリが使用方法を知っているインターフェースを定義します。そのインターフェースは、アプリケーションのナビゲーションやプラグインタッチポイントに他のアプリにそれ自体を注入する方法を提供する必要があります。
  • 起動時にアプリが読み取るパスを設定します(実行時のプラグイン管理ははるかに困難です)。
  • プラグインが存在する場合(Java Jarファイルなど)、アプリはマニフェストを読み取ってプラグインインターフェースの実装を見つけるか、インターフェースを実装するクラスをスキャンします。
  • そのクラスが見つかると、インスタンス化され、適切なメソッドが呼び出されて新しい機能を統合します。

これにより、さまざまなユーザーがさまざまなクラスの機能を利用できるようになります。ユーザーが支払うのは機能だけです。

アプリケーションコードは1つのコードベースとして維持され、プラグインは別のコードベースですが、プラグインに関連する部分のみが含まれます。アプリは、プラグインが存在する場合にプラグインを処理する方法を認識しており、プラグインはインターフェースと対話する方法のみを認識しています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.