PG日誌

各記事はブラウザの横幅を1410px以上にすると2カラムの見出しが表示されます。なるべく横に広げてみてください。

内部でStaticな変数に依存しない

アンチパターンのひとつで、処理がStaticなメンバーへ依存してはいけないというものがあります。

大したことはないのですが。例えば以下のようにstaticな、ある種のグローバル変数があったとします。

public class GlobalValiables
{
    public static bool InternalSwitch { get; set; }
}

次のように、処理内で利用されていたとします。

public class MyClass
{
    public int Execute()
    {
        if (GlobalValiables.InternalSwitch) // 内部でstaticな変数を利用
        {
            return 1;
        }
        else
        {
            return 2;
        }
    }
}

InternalSwitchが別の処理で書き換えられていた場合、呼び出し元は意図しない結果を受け取る可能性があります。したがって、たいていの場合でこのような処理を書くべきではありません。

また、クラスを利用する際に、変数が事前に初期化されていないといけない場合、(呼び出す前に何らかの準備が必要な事が分からない故に)単体テストの実行が妨げられたりするケースもあります。

このような場合、以下のいずれかの方針で変数への依存を外部から明示するように変更しstatic変数の依存を排除します。

  • 処理開始時の引数で条件を指定する
  • プロパティによって条件を指定する
  • コンストラクタによって条件を指定する
// 引数によって条件を指定する
public class MyClass_Csae1
{
    public int Execute(bool mode) 
    {
        //...
    }
}

// プロパティによって条件を指定する
public class MyClass_Case2
{
    public bool Mode { get; set; } = true;

    public int Execute()
    {
        if(this.Mode)
        {
            //...
        }
        else
        {
            //...
        }
    }
}

// コンストラクタで指定する
public class MyClass_Case3
{
    public MyClass_Case3(bool mode){ /* ... */ }

    public int Execute(){ /*...*/ }
}

ただ、この初期化パラメーターが大量にあれば、オブジェクトの生成処理の記述は結構面倒になります。下位のモジュールではstatic依存を除外し、上位のモジュールではstatic依存を限定的に利用するなどレイヤーによって利用する・しないを分割する方針をとるケースが多いように思います。