Skip to content

Commit 2d7073a

Browse files
Mention TargetingContext and fix wording in Variants section of readme (#330)
* mention itargetingcontextaccessor for variant allocation * update changes * add reference to ITargetingContextAccessor to readme for allocation * update with new discussed changes, rename sections and introduce context sooner * fix wording of default * fix wording to avoid implying variants are assigned per feature * use the term assign when referring to variants returned for a user * use assign term in more places * small changes * Update README.md Co-authored-by: Jimmy Campbell <[email protected]> * update section titles * resolve comments * fix typo * update link to allocating variants section --------- Co-authored-by: Jimmy Campbell <[email protected]>
1 parent 6449974 commit 2d7073a

File tree

1 file changed

+53
-26
lines changed

1 file changed

+53
-26
lines changed

README.md

Lines changed: 53 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -708,7 +708,7 @@ In the above example, the feature will be enabled for users named `Jeff` and `Al
708708

709709
When new features are added to an application, there may come a time when a feature has multiple different proposed design options. A common solution for deciding on a design is some form of A/B testing, which involves providing a different version of the feature to different segments of the user base and choosing a version based on user interaction. In this library, this functionality is enabled by representing different configurations of a feature with variants.
710710

711-
Variants enable a feature flag to become more than a simple on/off flag. A variant represents a value of a feature flag that can be a string, a number, a boolean, or even a configuration object. A feature flag that declares variants should define under what circumstances each variant should be used, which is covered in greater detail in the [Allocating a Variant](./README.md#allocating-a-variant) section.
711+
Variants enable a feature flag to become more than a simple on/off flag. A variant represents a value of a feature flag that can be a string, a number, a boolean, or even a configuration object. A feature flag that declares variants should define under what circumstances each variant should be used, which is covered in greater detail in the [Allocating Variants](./README.md#allocating-variants) section.
712712

713713
``` C#
714714
public class Variant
@@ -725,43 +725,70 @@ public class Variant
725725
}
726726
```
727727

728-
### Getting a Feature's Variant
728+
### Getting Variants
729729

730-
A feature's variant can be retrieved using the `IVariantFeatureManager`'s `GetVariantAsync` method.
730+
For each feature, a variant can be retrieved using the `IVariantFeatureManager`'s `GetVariantAsync` method.
731731

732732
``` C#
733733
734734
IVariantFeatureManager featureManager;
735735
736-
Variant variant = await featureManager.GetVariantAsync(MyFeatureFlags.FeatureU);
736+
Variant variant = await featureManager.GetVariantAsync(MyFeatureFlags.FeatureU, CancellationToken.None);
737737

738738
IConfigurationSection variantConfiguration = variant.Configuration;
739739

740740
// Do something with the resulting variant and its configuration
741741
```
742742

743-
### Setting a Variant's Configuration
743+
Once a variant is retrieved, the configuration of a variant can be used directly as an `IConfigurationSection` from the variant's `Configuration` property. Another option is to bind the configuration to an object using .NET's configuration binding pattern.
744744

745-
For each of the variants in the `Variants` property of a feature, there is a specified configuration. This can be set using either the `ConfigurationReference` or `ConfigurationValue` properties. `ConfigurationReference` is a string path that references a section of the current configuration that contains the feature flag declaration. `ConfigurationValue` is an inline configuration that can be a string, number, boolean, or configuration object. If both are specified, `ConfigurationValue` is used. If neither are specified, the returned variant's `Configuration` property will be null.
745+
``` C#
746+
IConfigurationSection variantConfiguration = variant.Configuration;
746747

748+
MyFeatureSettings settings = new MyFeatureSettings();
749+
750+
variantConfiguration.Bind(settings);
747751
```
748-
"Variants": [
749-
{
750-
"Name": "Big",
751-
"ConfigurationReference": "ShoppingCart:Big"
752-
},
753-
{
754-
"Name": "Small",
755-
"ConfigurationValue": {
756-
"Size": 300
752+
753+
The variant returned is dependent on the user currently being evaluated, and that information is obtained from an instance of `TargetingContext`. This context can either be passed in when calling `GetVariantAsync` or it can be automatically retrieved from an implementation of [`ITargetingContextAccessor`](#itargetingcontextaccessor) if one is registered.
754+
755+
### Defining Variants
756+
757+
Each variant has two properties: a name and a configuration. The name is used to refer to a specific variant, and the configuration is the value of that variant. The configuration can be set using either the `ConfigurationReference` or `ConfigurationValue` properties. `ConfigurationReference` is a string path that references a section of the current configuration that contains the feature flag declaration. `ConfigurationValue` is an inline configuration that can be a string, number, boolean, or configuration object. If both are specified, `ConfigurationValue` is used. If neither are specified, the returned variant's `Configuration` property will be null.
758+
759+
A list of all possible variants is defined for each feature under the `Variants` property.
760+
761+
```
762+
{
763+
"FeatureManagement":
764+
{
765+
"MyFlag":
766+
{
767+
"Variants": [
768+
{
769+
"Name": "Big",
770+
"ConfigurationReference": "ShoppingCart:Big"
771+
},
772+
{
773+
"Name": "Small",
774+
"ConfigurationValue": {
775+
"Size": 300
776+
}
777+
}
778+
],
779+
"EnabledFor": [
780+
{
781+
"Name": "AlwaysOn"
782+
}
783+
]
757784
}
758-
}
759-
]
785+
}
786+
}
760787
```
761788

762-
### Allocating a Variant
789+
### Allocating Variants
763790

764-
The process of allocating a variant to a specific feature is determined by the `Allocation` property of the feature.
791+
The process of allocating a feature's variants is determined by the `Allocation` property of the feature.
765792

766793
```
767794
"Allocation": {
@@ -809,21 +836,21 @@ The `Allocation` setting of a feature flag has the following properties:
809836
| Property | Description |
810837
| ---------------- | ---------------- |
811838
| `DefaultWhenDisabled` | Specifies which variant should be used when a variant is requested while the feature is considered disabled. |
812-
| `DefaultWhenEnabled` | Specifies which variant should be used when a variant is requested while the feature is considered enabled and no variant was allocated to the user. |
813-
| `User` | Specifies a variant and a list of users for which that variant should be used. |
814-
| `Group` | Specifies a variant and a list of groups the current user has to be in for that variant to be used. |
815-
| `Percentile` | Specifies a variant and a percentage range the user's calculated percentage has to fit into for that variant to be used. |
839+
| `DefaultWhenEnabled` | Specifies which variant should be used when a variant is requested while the feature is considered enabled and no other variant was assigned to the user. |
840+
| `User` | Specifies a variant and a list of users to whom that variant should be assigned. |
841+
| `Group` | Specifies a variant and a list of groups the current user has to be in for that variant to be assigned. |
842+
| `Percentile` | Specifies a variant and a percentage range the user's calculated percentage has to fit into for that variant to be assigned. |
816843
| `Seed` | The value which percentage calculations for `Percentile` are based on. The percentage calculation for a specific user will be the same across all features if the same `Seed` value is used. If no `Seed` is specified, then a default seed is created based on the feature name. |
817844

818-
In the above example, if the feature is not enabled, `GetVariantAsync` would return the variant allocated by `DefaultWhenDisabled`, which is `Small` in this case.
845+
In the above example, if the feature is not enabled, the feature manager will assign the variant marked as `DefaultWhenDisabled` to the current user, which is `Small` in this case.
819846

820-
If the feature is enabled, the feature manager will check the `User`, `Group`, and `Percentile` allocations in that order to allocate a variant for this feature. If the user being evaluated is named `Marsha`, in the group named `Ring1`, or the user happens to fall between the 0 and 10th percentile calculated with the given `Seed`, then the specified variant is returned for that allocation. In this case, all of these would return the `Big` variant. If none of these allocations match, the `DefaultWhenEnabled` variant is returned, which is `Small`.
847+
If the feature is enabled, the feature manager will check the `User`, `Group`, and `Percentile` allocations in that order to assign a variant. For this particular example, if the user being evaluated is named `Marsha`, in the group named `Ring1`, or the user happens to fall between the 0 and 10th percentile, then the specified variant is assigned to the user. In this case, all of these would return the `Big` variant. If none of these allocations match, the user is assigned the `DefaultWhenEnabled` variant, which is `Small`.
821848

822849
Allocation logic is similar to the [Microsoft.Targeting](./README.md#MicrosoftTargeting) feature filter, but there are some parameters that are present in targeting that aren't in allocation, and vice versa. The outcomes of targeting and allocation are not related.
823850

824851
### Overriding Enabled State with a Variant
825852

826-
You can use variants to override the enabled state of a feature flag. This gives variants an opportunity to extend the evaluation of a feature flag. If a caller is checking whether a flag that has variants is enabled, then variant allocation will be performed to see if an allocated variant is set up to override the result. This is done using the optional variant property `StatusOverride`. By default, this property is set to `None`, which means the variant doesn't affect whether the flag is considered enabled or disabled. Setting `StatusOverride` to `Enabled` allows the variant, when chosen, to override a flag to be enabled. Setting `StatusOverride` to `Disabled` provides the opposite functionality, therefore disabling the flag when the variant is chosen. A feature with a `Status` of `Disabled` cannot be overridden.
853+
You can use variants to override the enabled state of a feature flag. This gives variants an opportunity to extend the evaluation of a feature flag. If a caller is checking whether a flag that has variants is enabled, the feature manager will check if the variant assigned to the current user is set up to override the result. This is done using the optional variant property `StatusOverride`. By default, this property is set to `None`, which means the variant doesn't affect whether the flag is considered enabled or disabled. Setting `StatusOverride` to `Enabled` allows the variant, when chosen, to override a flag to be enabled. Setting `StatusOverride` to `Disabled` provides the opposite functionality, therefore disabling the flag when the variant is chosen. A feature with a `Status` of `Disabled` cannot be overridden.
827854

828855
If you are using a feature flag with binary variants, the `StatusOverride` property can be very helpful. It allows you to continue using APIs like `IsEnabledAsync` and `FeatureGateAttribute` in your application, all while benefiting from the new features that come with variants, such as percentile allocation and seed.
829856

0 commit comments

Comments
 (0)