Python Feature Flag Management System
Feature flags, also known as feature toggles, are a powerful software development technique that allows teams to enable or disable specific functionalities in their applications without deploying new code. This enables safer rollouts, A/B testing, and the ability to quickly disable problematic features. Your task is to build a basic feature flag management system in Python.
Problem Description
You need to implement a Python class that can manage a set of feature flags. This system should allow you to:
- Define and initialize a collection of feature flags, each with a name and an initial state (enabled or disabled).
- Check the status of a specific feature flag.
- Enable or disable a feature flag dynamically.
- Retrieve all defined feature flags and their current states.
The system should be designed to be easily integrated into an existing Python application.
Key Requirements:
- A
FeatureFlagManagerclass is required. - The manager should store flags internally, likely in a dictionary or similar structure.
- Each flag should have a unique string name.
- Flags can be either
True(enabled) orFalse(disabled).
Expected Behavior:
- When a flag is created, it should have a specified initial state.
- Checking a non-existent flag should indicate it's not present or return a default value (e.g.,
False). - Enabling a disabled flag should change its state to enabled.
- Disabling an enabled flag should change its state to disabled.
- The system should provide a way to iterate through all managed flags.
Edge Cases to Consider:
- Attempting to enable/disable a flag that doesn't exist.
- Handling duplicate flag names during initialization (consider if this should raise an error or be ignored).
- The behavior when no flags are defined.
Examples
Example 1: Basic Flag Management
# Initialize the manager with some flags
manager = FeatureFlagManager()
manager.add_flag("new_dashboard", True)
manager.add_flag("beta_feature", False)
# Check flag status
print(manager.is_enabled("new_dashboard")) # Expected: True
print(manager.is_enabled("beta_feature")) # Expected: False
print(manager.is_enabled("non_existent_flag")) # Expected: False (or indicate not found)
# Toggle a flag
manager.disable_flag("new_dashboard")
print(manager.is_enabled("new_dashboard")) # Expected: False
manager.enable_flag("beta_feature")
print(manager.is_enabled("beta_feature")) # Expected: True
Explanation:
This example demonstrates the fundamental operations: adding flags, checking their status, and toggling them. is_enabled returns True if the flag exists and is enabled, False otherwise.
Example 2: Retrieving All Flags
manager = FeatureFlagManager()
manager.add_flag("email_notifications", True)
manager.add_flag("dark_mode", False)
manager.add_flag("api_throttling", True)
all_flags = manager.get_all_flags()
print(all_flags)
Expected Output:
{'email_notifications': True, 'dark_mode': False, 'api_throttling': True}
Explanation:
The get_all_flags method should return a dictionary or similar structure containing all defined flags and their current boolean states.
Example 3: Handling Non-Existent Flags
manager = FeatureFlagManager()
manager.add_flag("user_profile_v2", True)
# Attempting to toggle a non-existent flag
manager.enable_flag("experimental_feature")
manager.disable_flag("obsolete_feature")
# Checking a non-existent flag after toggling attempts
print(manager.is_enabled("experimental_feature")) # Expected: False
print(manager.is_enabled("obsolete_feature")) # Expected: False
# Check if flags were added unintentionally
print(manager.get_all_flags())
Expected Output:
False
False
{'user_profile_v2': True}
Explanation: This example shows that attempting to toggle flags that don't exist should not add them to the manager and checking them should return the default (disabled) state.
Constraints
- Flag names must be strings.
- Flag states must be booleans (
TrueorFalse). - The implementation should be efficient for a moderate number of flags (up to 1000).
- The class should be thread-safe if multiple threads might access it concurrently (consider this as an advanced consideration, but aim for a basic non-thread-safe version first).
- Do not use any external libraries for feature flag management. Implement it from scratch using standard Python data structures.
Notes
- Consider how you will handle adding a flag that already exists. Should it overwrite, raise an error, or be ignored? Document your chosen behavior.
- The
is_enabledmethod should returnFalseif the flag does not exist in the manager. This simplifies checking, as you don't need to check for existence before callingis_enabled. - Think about how you might extend this system later to support more complex targeting rules (e.g., percentage rollouts, user-specific flags). This is beyond the scope of this challenge but good to keep in mind for design.
- The
add_flagmethod is suggested for initialization. You might also consider an__init__method that accepts an initial dictionary of flags.