FeatureFlagのIF文多すぎ問題を解決する

この記事はZOZOアドベントカレンダー　 Series1の24日目の記事です。

アウトカムをどんどん出していくためにFeatureFlagを活用しているチームは多いと思います。

簡単に機能をON/OFFできる仕組みは有用ですし、なにより安心してリリースできるのがいいですよね。(前回と同じこと書いてる・・・)

しかし、FeatureFlagを多様していると、IF文が増えて困ります。

FeatureFlagを活用する上で最も注意すべき点としては、ONにして問題なければできるだけ早くFeatureFlagを削除することですが、顧客の都合や関連システムの都合でなかなかONにすることができない機能もあるかと思います。

そこで、FeatureFlagを使うために有用なパターンを3つ紹介します。ちなみにこの3点は技術顧問でお世話になっているかとじゅんさんにアドバイスをいただいたものになっています。本当にありがとうございます！

# 1. モジュールごと分けてしまう。

もうモジュールごと分離してしまいましょう。ON用のモジュールとOFF用のモジュールに分けます。不要になったらモジュールごと削除すればOKなので、運用も簡単です。

# 2. ファクトリパターンを使う

ファクトリパターンを使って分離しましょう。不要になったらクラスを削除するだけなので運用も簡単です。

```java
// Feature.java
public interface Feature {
    void performFeature();
}
```
```java
// NewFeatureEnabled.java
public class NewFeatureEnabled implements Feature {
    @Override
    public void performFeature() {
        System.out.println("New feature is enabled. Performing new feature actions.");
    }
}

// NewFeatureDisabled.java
public class NewFeatureDisabled implements Feature {
    @Override
    public void performFeature() {
        System.out.println("New feature is disabled. Performing default actions.");
    }
}
```
```java
// FeatureFactory.java
public class FeatureFactory {
    public static Feature createFeature(boolean isNewFeatureEnabled) {
        if (isNewFeatureEnabled) {
            return new NewFeatureEnabled();
        } else {
            return new NewFeatureDisabled();
        }
    }
}
```
```java
// MainClass.java
public class MainClass {
    public static void main(String[] args) {
        boolean isNewFeatureEnabled = /* フィーチャーフラグの値を取得するロジック */;

        Feature feature = FeatureFactory.createFeature(isNewFeatureEnabled);
        feature.performFeature();
    }
}
```

# 3.ストラテジパターンを使う

２と似てます。ほぼ一緒かもですが、そのあたりは都合の良いように実装できればよいと思います。
同様に削除するのも容易です。

```java
// FeatureStrategy.java
public interface FeatureStrategy {
    void performFeature();
}
```


```java
// NewFeatureEnabledStrategy.java
public class NewFeatureEnabledStrategy implements FeatureStrategy {
    @Override
    public void performFeature() {
        System.out.println("New feature is enabled. Performing new feature actions.");
    }
}

// NewFeatureDisabledStrategy.java
public class NewFeatureDisabledStrategy implements FeatureStrategy {
    @Override
    public void performFeature() {
        System.out.println("New feature is disabled. Performing default actions.");
    }
}
```
```java
// FeatureContext.java
public class FeatureContext {
    private FeatureStrategy featureStrategy;

    public FeatureContext(FeatureStrategy featureStrategy) {
        this.featureStrategy = featureStrategy;
    }

    public void performFeature() {
        featureStrategy.performFeature();
    }
}
```
```java
// MainClass.java
public class MainClass {
    public static void main(String[] args) {
        boolean isNewFeatureEnabled = /* フィーチャーフラグの値を取得するロジック */;

        FeatureStrategy strategy;
        if (isNewFeatureEnabled) {
            strategy = new NewFeatureEnabledStrategy();
        } else {
            strategy = new NewFeatureDisabledStrategy();
        }

        FeatureContext featureContext = new FeatureContext(strategy);
        featureContext.performFeature();
    }
}
```

重要なのは、フラグを消すときにいかに容易に、詳細を気にすることなくバサッと消すことができるかです。
主要なビジネスロジックではないところに気を使って時間をかけず行ける方法を考えて実装しましょう。