Code Smell 242 - Zombie Feature Flags

Maxi Contieri - Feb 21 - - Dev Community

Feature flags are evil... and sometimes come back as zombies

TL;DR: Don't leave dead unused code. Clean your flag mess.

Problems

  • Dead Code

  • Maintainability

  • Unnecessary complexity

Solutions

  1. Clean up dead code

  2. Set up a clear lifecycle for your Feature Flags

Context

Feature flags are often used to toggle certain functionalities or features on or off dynamically, allowing for controlled rollouts or A/B testing.

However, if the code controlled by these flags becomes obsolete or is no longer needed, it can lead to dead code.

Dead code not only clutters the codebase, making it harder to understand and maintain, but it can also confuse developers.

It may give a false impression that certain functionalities are still active and supported when they are not.

A notable example happened to the Knight Capital Group.

Old code left active under a feature flag alongside new code caused the system to send a massive volume of erroneous orders to the market.

Within minutes, Knight Capital Group suffered losses of approximately $440 million, nearly bankrupting the firm.

Sample Code

Wrong

public class WeatherSimulation {
    private boolean isWeatherSimulationEnabled ; 
    // This feature flag controls weather simulation

    public WeatherSimulation() {
        Properties config = new Properties();
        FileInputStream fis = new FileInputStream("config.properties")) {
            config.load(fis);
            isWeatherSimulationEnabled = Boolean.parseBoolean(
                config.getProperty("weatherSimulation.enabled", "false"));
            // The feature toggle is read from the file
            isWeatherSimulationEnabled = false;
        }
    }

    public void simulateWeather() {
        if (isWeatherSimulationEnabled) {
            // Code to simulate weather conditions
            // ...
            System.out.println("Simulating weather...");
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Right

public class WeatherSimulation {

    public WeatherSimulation() {
        Properties config = new Properties();
        FileInputStream fis = new FileInputStream("config.properties")) {
            config.load(fis);
            String weatherSimulationEnabledValue = 
              config.getProperty("weatherSimulation.enabled");
            if (weatherSimulationEnabledValue != null) {
                throw new IllegalStateException(
                  "weatherSimulation.enabled property " + 
                  "should not be present in the configuration file.");
                // You follow the fail-fast principle. 
                // Feature is deprecated 
                // and users got a grace period notice
                // After that you should stop the execution              
            }
        }
    }

    public void simulateWeather() {
       // You remove the simulated code and simplify it
    }
}
Enter fullscreen mode Exit fullscreen mode

Detection

[X] Semi-Automatic

You can use mutation testing and remove the potential dead code to see if your coverage net catches a defect.

Tags

  • Bloaters

Level

[X] Intermediate

AI Assistants

AI assistants don't usually add dead code or feature flags unless you tell them explicitly.

Conclusion

You should regularly review and clean up feature flags and their associated code to remove any unnecessary or obsolete sections.

This ensures that the code remains lean, understandable, and free from potential issues caused by dead code.

Feature flags should be shortlived and the lifecycle must be supervised.

Relations

More Info

A feature flag disaster

Disclaimer

Code Smells are my opinion.

Credits

Photo by the blowup on Unsplash


The software isn’t finished until the last user is dead.

Sidney Markowitz


This article is part of the CodeSmell Series.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .