複数の設定値によって、別の複数の設定値が決まるようなアレ

今日悩みながら書いたコードについてメモ。C#です。

まず、何かDTOがあると思ってください。

public class SomeObject
{
    public string Fuga { get; set; }
    public int Piyo { get; set; }
    
    public bool IsFoo { get; set; }
    public bool IsBar { get; set; }
}

このDTOのIsFooとIsBarが正しく設定されたオブジェクトが、出力です。

設定に必要な情報が、入力です。

次に、入力と出力のマッピングを定義します。入力はint配列、出力は設定の処理そのものとします。

public class Mapping :  IEqualityComparer<int[]>
{
    public IDictionary<int[], Func<SomeObject, SomeObject>> getPatterns() {
    
        IDictionary<int[], Func<SomeObject, SomeObject>> dic = 
        new Dictionary<int[], Func<SomeObject, SomeObject>>(this){
            {new[] {0, 0}, setStatus(false, true)}
            , {new[] {0, 1}, setStatus(true, true)}
            , {new[] {1, 0}, setStatus(false, false)}
            , {new[] {1, 1}, setStatus(true, false)}
        };
        return dic;
    }

    private Func<SomeObject, SomeObject> setStatus(bool foo, bool bar) {
        Func<SomeObject, SomeObject> func = delegete(SomeObject obj){
            obj.IsFoo = foo;
            obj.IsBar = bar;
            return obj;
        };
        return func;
    }

   bool IEqualityComparer<int[]> Equals(int[] x, int[] y){
        if (x.Length != y.Length )
        {
            return false;
        }
        for( int n = 0; n < x.Length; n++ )
        {
            if ( x[n] != y[n] ){
                return false;
            }
        }
        return true;
    }
    
    int IEqualityComparer<int[]> GetHashCode(int[] x)
    {
        int sum = 0;
        foreach (int n in x)
        {
            sum += n.GetHashCode();
        }
        return sum;
    }
}

上のコードでは省略しましたが、扱う入力状態は数百パターンあるものとします。

(実際には、状態表のような設計書を先に別途作り、それを見ながら実装するような感じです。お察しください)

使う側のコードはこうなります。

public class UserCode
{
    public SomeObject exec(){
        var obj = new SomeObject();
        
        var mapping = new Mapping();
        var patterns = mapping.getPatterns();
        
        // 入力を与える
        var pattern = patterns[ new[] {
            getHoge() // 何らかの仕様にしたがって0か1が返ってくると思ってほしい
            , getMoga() // ここも同じ
            } ];
        
        pattern.Invoke(obj);
        
        return obj;
    }
}

Keyを配列にせずクラスにすべきとか、いろいろありますが、根本的に改善するにはどうすればよいか。

ぐぬぬ