5 minute read
Toggling Constants With Feature Flags
Split’s React application uses a feature flag toggling system to make it easier to add and remove feature flags from our code base.
Every month or two, someone asks: “I’ve got this constant that I need to change based on the feature flag. What should I do?”
A Quick Reminder About Toggling
The toggling technique (e.g., connectToggler()
in the Split Redux SDK) involves making a separate version of functions for each feature flag treatment. These functions are then wrapped with a “toggler.”
When compared to sprinkling individual getTreatment()
calls around in the code base, this technique makes the code easier to reason about and easier to test. It also makes adding and removing feature flags much easier. We actually have a script that does most of the work for adding and removing feature flags.
This looks like:
const toggledFunction = toggler(FEATURE_FLAG_NAME, treatmentAFunction, treatmentBFunction);
…
const result = toggledFunction(someArgment);
Code language: Arduino (arduino)
Constants
The problem that people find with constants is that since they are not functions, it is not clear how to use these with feature flags.
There are three techniques we’ll talk about here:
- Using distinct constant names
- Using separate constant files
- Wrapping constants with a function
In the discussion, we’ll assume that we have a constant ( SOME_CONSTANT
) whose value we want to be 23
in TreatmentA and 45
in TreatmentB:
const SOME_VALUE = 23;
Code language: Arduino (arduino)
Distinct Names
The easiest solution is just to use distinct constant names:
const SOME_VALUE_TREATMENT_A = 23;
const SOME_VALUE_TREATMENT_B = 45;
Code language: Arduino (arduino)
We can then import this into the functions that use the constant. As long as those are toggled, this works well:
import { SOME_VALUE_TREATMENT_A } from 'someConstantsFile';
const treatmentAFunction = (inputParam) =>
const newValue = inputParam * SOME_VALUE_TREATMENT_A;
…
}
import { SOME_VALUE_TREATMENT_B } from 'someConstantsFile';
const treatmentBFunction = (inputParam) => {
const newValue = inputParam * SOME_VALUE_TREATMENT_B;
…
}
Code language: JavaScript (javascript)
Pros and Cons
This technique is very easy to implement, and it is easy to understand.
However, this tends to make cleaning up the feature flag more difficult. Once you remove one of the treatments, you must manually edit the file with the constants, and then rename all the uses of the constant (though that last is very easy with some languages and IDEs).
Distinct Constant Files
A second approach is to make a separate file of constant values for each treatment. For example, before toggling the function, we might have these files:
constants.ts
myFunction.ts
Code language: CSS (css)
And after toggling, we have:
myFunction/
index.ts
TreatmentA/
constants.ts
MyFunction.ts
TreatmentB
constants.ts
MyFunction.ts
Code language: Delphi (delphi)
Pros and Cons
This solution has all the benefits of the toggling system, and so is ideal if your constants are closely related to the function being toggled.
- The constants are isolated from each other
- It is easy to remove them when the feature flag is removed
This also does not work if the file with the constants is not so easily grouped with the consumers. It is not uncommon to have a group of constants in a more “global” location, and for these values to be used in various otherwise unchanged files. In this case, this technique does not work.
Wrapping the Constants With a Function
A third technique converts all the access to your constants into a function call. The code below shows an example:
Before
// globalConstants.ts
export const SOME_VALUE = 23;
export const SOME_OTHER_VALUE = true;
// some function
import { SOME_VALUE } from '../globalConstants';
const myFunction = (props) => {
const someValue = props.foo * SOME_VALUE;
…
}
Code language: JavaScript (javascript)
After
// globalConstantsTreatmentA.ts
const getConstantsTreatmentA = () => ({
SOME_VALUE: 23,
SOME_OTHER_VALUE: true,
});
export { getConstants };
// globalConstantsTreatmentB.ts
const getConstantsTreatmentB = () => ({
SOME_VALUE: 45,
SOME_OTHER_VALUE: true,
});
export { getConstants };
// globalConstants/index.ts
import { FEATURE_FLAG_NAME } from './getConstantsTreatmentA';
import { getConstantsTreatmentA } from './getConstantsTreatmentA';
import { getConstantsTreatmentB } from './getConstantsTreatmentB;
const getConstants = toggler(FEATURE_FLAG_NAME, getConstantsTreatmentA, getConstantsTreatmentB);
export { getConstants };
// some function
import { getConstants } from '../../someLocation/getConstants;
const myFunction = (props) => {
const { SOME_VALUE } = getConstants();
const someValue = props.foo * SOME_VALUE;
…
}
Code language: PHP (php)
Now, when `myFunction` accesses the constants, it will get either the treatmentA value, or the treatmentB value based on the value of the feature flag at that moment.
Pros and Cons
This provides all the benefits of a toggling system. Other parts of the code are unaware of the presence of the feature flags, making the code easier to reason about and test. As a result, it is easy to add and remove toggled code without impacting other parts of the system. This makes adding and removing flags very safe.
The biggest downside is certainly the fact that one must make a function call to get the constant value.
Summary
Providing a constant with a different value based on the presence of a feature flag can be challenging. But when using a feature toggling system, there are several techniques you can consider using to achieve your goal.
All of the techniques here have their own benefits. You should pick the technique that will maximize your development velocity while also making it safe to add and remove your feature flags.
Want to Dive Deeper?
For additional education and relevant content, be sure to check out the following articles:
Feature toggles–or feature flags as they’re called–are a powerful development tool. Learn how they started and where they’re headed.
Discover how to use A/B testing to ensure successful canary development. Then, start setting up A/B tests with code examples from Split.
Continuous delivery (CD) and pipeline deployment (PD) are commonly associated with software development and deployment. Learn how to streamline the software development and delivery process.
Deliver Features That Matter, Faster with Split
Split is a feature management platform that attributes insightful data to everything you release. Whether your team is looking to test in production, perform gradual rollouts, or experiment with new features–Split ensures your efforts are safe, visible, and highly impactful. What a Release. Get going with a free account today, Schedule a demo to learn more, or contact us for further questions and support.