diff --git a/feature-toggle/README.md b/feature-toggle/README.md index 982108bc7..496e2439f 100644 --- a/feature-toggle/README.md +++ b/feature-toggle/README.md @@ -3,38 +3,39 @@ title: Feature Toggle category: Behavioral language: en tag: - - Extensibility + - Decoupling + - Extensibility + - Feature management + - Scalability --- ## Also known as -Feature Flag + +* Feature Flag +* Feature Switch ## Intent -A technique used in software development to control and manage the rollout of specific features or functionality in a -program without changing the code. It can act as an on/off switch for features depending on the status or properties of -other values in the program. This is similar to A/B testing, where features are rolled out based on properties such as -location or device. Implementing this design pattern can increase code complexity, and it is important to remember to -remove redundant code if this design pattern is being used to phase out a system or feature. + +A technique used in software development to control and manage the rollout of specific features or functionality in a program without changing the code. It can act as an on/off switch for features depending on the status or properties of other values in the program. This is similar to A/B testing, where features are rolled out based on properties such as location or device. Implementing this design pattern can increase code complexity, and it is important to remember to remove redundant code if this design pattern is being used to phase out a system or feature. ## Explanation + Real-world Example -> This design pattern works really well in any sort of development, in particular mobile development. Say you want to -> introduce a feature such as dark mode, but you want to ensure that the feature works correctly and don't want to roll -> out the feature to everyone immediately. You write in the code, and have it switched off as default. From here, it is -> easy to turn on the code for specific users based on selection criteria, or randomly. This will also allow the feature -> to be turned off easily without any drastic changes to the code, or any need for redeployment or updates. + +> This design pattern works really well in any sort of development, in particular mobile development. Say you want to introduce a feature such as dark mode, but you want to ensure that the feature works correctly and don't want to roll out the feature to everyone immediately. You write in the code, and have it switched off as default. From here, it is easy to turn on the code for specific users based on selection criteria, or randomly. This will also allow the feature to be turned off easily without any drastic changes to the code, or any need for redeployment or updates. In plain words + > Feature Toggle is a way to introduce new features gradually instead of deployment all at once. Wikipedia says -> A feature toggle in software development provides an alternative to maintaining multiple feature branches in source -> code. A condition within the code enables or disables a feature during runtime. In agile settings the toggle is -> used in production, to switch on the feature on demand, for some or all the users. + +> A feature toggle in software development provides an alternative to maintaining multiple feature branches in source code. A condition within the code enables or disables a feature during runtime. In agile settings the toggle is used in production, to switch on the feature on demand, for some or all the users. ## Programmatic Example -This example shows Java code that allows a feature to show when it is enabled by the developer, and when a user is a -Premium member of the application. This is useful for subscription locked features. + +This example shows Java code that allows a feature to show when it is enabled by the developer, and when a user is a Premium member of the application. This is useful for subscription locked features. + ```java public class FeatureToggleExample { // Bool for feature enabled or disabled @@ -55,16 +56,18 @@ public class FeatureToggleExample { } } ``` -The code shows how simple it is to implement this design pattern, and the criteria can be further refined or broadened -should the developers choose to do so. + +The code shows how simple it is to implement this design pattern, and the criteria can be further refined or broadened should the developers choose to do so. ## Class diagram -![alt text](./etc/feature-toggle.png "Feature Toggle") + +![Feature Toggle](./etc/feature-toggle.png "Feature Toggle") ## Applicability + Use the Feature Toggle pattern when -* Giving different features to different users. +* Conditional feature access to different users and groups. * Rolling out a new feature incrementally. * Switching between development and production environments. * Quickly disable problematic features @@ -72,15 +75,33 @@ Use the Feature Toggle pattern when * Ability to maintain multiple version releases of a feature * 'Hidden' deployment, releasing a feature in code for designated testing but not publicly making it available -## Consequences -Consequences involved with using the Feature Toggle pattern +## Known Uses -* Code complexity is increased -* Testing of multiple states is harder and more time-consuming -* Confusion between friends on why features are missing -* Keeping documentation up to date with all features can be difficult +* Web development platforms use feature toggles to gradually roll out new features to users to ensure stability. +* Enterprise applications use feature toggles to enable or disable features during runtime to cater to different market needs. + +## Consequences + +Benefits: + +* Facilitates A/B testing and canary releases. +* Allows for quicker rollback and minimal risk deployments. +* Enables conditional feature execution without redeploying the application. + +Trade-offs: + +* Code complexity is increased. +* Testing of multiple states is harder and more time-consuming. +* Potential for technical debt if toggles remain in the code longer than necessary. +* Risk of toggle misconfiguration leading to unexpected behavior. + +## Related Patterns + +* [Strategy](https://java-design-patterns.com/patterns/strategy/): Both patterns allow changing the behavior of software at runtime. The Feature Toggle changes features dynamically, while the Strategy allows switching algorithms or strategies. +* [Observer](https://java-design-patterns.com/patterns/observer/): Useful for implementing feature toggles by notifying components of feature state changes, which allows dynamic feature modification without restarts. ## Credits -* [Martin Fowler 29 October 2010 (2010-10-29).](http://martinfowler.com/bliki/FeatureToggle.html) -* [Feature Toggle - Java Design Patterns](https://java-design-patterns.com/patterns/feature-toggle/) +* [Feature Toggle - Martin Fowler](http://martinfowler.com/bliki/FeatureToggle.html) +* [Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation](https://amzn.to/4488ESM) +* [Release It! Design and Deploy Production-Ready Software](https://amzn.to/3UoeJY4) diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersion.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersion.java index ce7886a10..b3484cec2 100644 --- a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersion.java +++ b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersion.java @@ -77,12 +77,12 @@ public class PropertiesFeatureToggleVersion implements Service { /** * Generate a welcome message based on the user being passed and the status of the feature toggle. * If the enhanced version is enabled, then the message will be personalised with the name of the - * passed {@link User}. However if disabled then a generic version fo the message is returned. + * passed {@link User}. However, if disabled then a generic version fo the message is returned. * * @param user the {@link User} to be displayed in the message if the enhanced version is enabled * see {@link PropertiesFeatureToggleVersion#isEnhanced()}. If the enhanced version is * enabled, then the message will be personalised with the name of the passed {@link - * User}. However if disabled then a generic version fo the message is returned. + * User}. However, if disabled then a generic version fo the message is returned. * @return Resulting welcome message. * @see User */ diff --git a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersion.java b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersion.java index 74eb44340..420783485 100644 --- a/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersion.java +++ b/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersion.java @@ -30,10 +30,10 @@ import com.iluwatar.featuretoggle.user.UserGroup; /** * This example of the Feature Toggle pattern shows how it could be implemented based on a {@link - * User}. Therefore showing its use within a tiered application where the paying users get access to + * User}. Therefore, showing its use within a tiered application where the paying users get access to * different content or better versions of features. So in this instance a {@link User} is passed in * and if they are found to be on the {@link UserGroup#isPaid(User)} they are welcomed with a - * personalised message. While the other is more generic. However this pattern is limited to simple + * personalised message. While the other is more generic. However, this pattern is limited to simple * examples such as the one below. * * @see Service @@ -66,7 +66,7 @@ public class TieredFeatureToggleVersion implements Service { /** * Method that checks if the welcome message to be returned is the enhanced version. For this - * instance as the logic is driven by the user group. This method is a little redundant. However + * instance as the logic is driven by the user group. This method is a little redundant. However, * can be used to show that there is an enhanced version available. * * @return Boolean value {@code true} if enhanced. diff --git a/feature-toggle/src/test/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersionTest.java b/feature-toggle/src/test/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersionTest.java index c8abdedcd..f659134fb 100644 --- a/feature-toggle/src/test/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersionTest.java +++ b/feature-toggle/src/test/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersionTest.java @@ -40,9 +40,7 @@ class PropertiesFeatureToggleVersionTest { @Test void testNullPropertiesPassed() { - assertThrows(IllegalArgumentException.class, () -> { - new PropertiesFeatureToggleVersion(null); - }); + assertThrows(IllegalArgumentException.class, () -> new PropertiesFeatureToggleVersion(null)); } @Test diff --git a/feature-toggle/src/test/java/com/iluwatar/featuretoggle/user/UserGroupTest.java b/feature-toggle/src/test/java/com/iluwatar/featuretoggle/user/UserGroupTest.java index b605cec5f..07d0bc88f 100644 --- a/feature-toggle/src/test/java/com/iluwatar/featuretoggle/user/UserGroupTest.java +++ b/feature-toggle/src/test/java/com/iluwatar/featuretoggle/user/UserGroupTest.java @@ -53,17 +53,13 @@ class UserGroupTest { void testAddUserToPaidWhenOnFree() { var user = new User("Paid User"); UserGroup.addUserToFreeGroup(user); - assertThrows(IllegalArgumentException.class, () -> { - UserGroup.addUserToPaidGroup(user); - }); + assertThrows(IllegalArgumentException.class, () -> UserGroup.addUserToPaidGroup(user)); } @Test void testAddUserToFreeWhenOnPaid() { var user = new User("Free User"); UserGroup.addUserToPaidGroup(user); - assertThrows(IllegalArgumentException.class, () -> { - UserGroup.addUserToFreeGroup(user); - }); + assertThrows(IllegalArgumentException.class, () -> UserGroup.addUserToFreeGroup(user)); } }