粉砕Attribute

こんにちは、2025年2月までクラスターでUnityエンジニアをしていたshivadukeです。先日、Cluster Tech Blogに自分も何か書ければよかったな、ということをX(旧・ツイッター)に投稿したところ、htomineさんから「寄稿できますよ」と言っていただけたので、遅ればせながら「粉砕Attribute」について紹介したいと思います。

クラスターでは機能開発にFeatureFlagを使用しています。
cluster はどのように新機能を並行開発しているのか

ここでいうFeatureFlagは世間一般におけるFeature Toggleの中のRelease Toggleに対応するもので、機能開発時に作成し、リリース後に「粉砕」します。

「粉砕」はクラスター社内用語で、なにかをやめたり無くしたりすることを意味します。ポジティブな意味で使用されるもので、多くの人が日常的に使っていたように思います。Cluster Tech Blogの中でも検索するといくつかヒットします。

https://tech-blog.cluster.mu/search?q=粉砕

さて、FeatureFlagを使った開発では、FeatureFlagの値によって既存の挙動と新しい挙動を切り替える必要があります。そのため、既存の実装はそのまま残しつつ、新しくV2を実装し、FeatureFlagでV1とV2を切り替えることが多々あります。V2の粒度はメソッド単位の場合もあればクラス単位の場合もあります。

例えば、Fooというメソッドがレガシーな実装になっているので、そのV2を作り、FeatureFlag.RefactorFooで切り替えたいとします。実装は以下のようになるでしょう。

void Foo()  
{  
  … // レガシーな実装  
}

void FooV2()  
{  
  … // 新しい実装  
}  
// 呼び出し側でフラグで分岐する  
if (FeatureFlag.RefactorFoo.IsEnable())  
{  
    FooV2();  
}  
else  
{  
    Foo();  
}  

開発が終わり機能がリリースされたあとは、FeatureFlag.RefactorFooと一緒に使わなくなったFoo関数も一緒に粉砕する方が望ましいです。粉砕対象の数が少ないうちは良いのですが、リファクタの規模が大きくなるにつれて、どれが粉砕対象かパッと見でわからない、粉砕が漏れて未使用のコードが残る、といったことが起こります。TODOコメントやObsolete属性をつけても良いですが、今度はそれらが増えて、割れ窓になる懸念があります。

こういった問題に対処するのが「粉砕Attribute」です。

まず、FeatureFlagが以下のようなenumで定義されているとします。

public enum FeatureFlag  
{  
    RefactorFoo,  
}  

以下のように粉砕Attributeを実装します。

public sealed class 粉砕Attribute : Attribute  
{  
    readonly FeatureFlag flag;

    public 粉砕Attribute(FeatureFlag flag)  
    {  
        this.flag \= flag;  
    }  
}  

そして、FeatureFlagと一緒に粉砕可能なものに粉砕属性をつけます。

[粉砕(FeatureFlag.RefactorFoo)]  
void Foo()  
{  
  …  
}  

こうすることで、FeatureFlagのenumからRefactorFooを消すと、粉砕Attributeをつけている箇所が全てコンパイルエラーになるので、粉砕漏れを減らすことができます。

TIPSとして、粉砕AttributeにStringを渡せるようにして、nameofなどで型情報を渡すようにすることも可能です。あまり濫用すると管理が難しくなるため、ある程度の制限を入れておくことをおすすめします。

おわりに

粉砕Attributeはシンプルですが、粉砕漏れの検知に気づけて存外便利だった記憶があります。そして、粉砕という社内用語がそのまま日本語でコードベースに現れるのが、クラスターらしくてお気に入りでした。ありがとうございました。