web-dev-qa-db-ja.com

不変/ステートレスシングルトンは悪いですか?

最近、シングルトンに対して何らかの革命が起こっていますが、それらがステートレスである場合、何か問題がありますか?

私は酷使の話とすべてを知っています...これはシングルトンだけでなくすべてに当てはまります。

12
m3th0dman
  > Are immutable/stateless singletons bad?
  • いいえ他の外部システムに依存しない場合。
    • 例:文字列内でhtmlをエスケープするStringutility。
    • 理由:単体テストでは、これをモック/シミュレーターに置き換える必要はありません。
  • はいイミュータブル/ステートレスシングルトンが他の外部システム/サービスに依存している場合、およびユニットテスト(分離テスト)を実行する場合
    • 例:外部税計算機Webサービスに依存するサービス。
    • 理由:このサービスで(単体で)単体テストを実行するには、外部のシステム/サービスをシミュレート/模擬する必要があります。

詳細は the-onion-architecture を参照してください


  • シングルトンは、単体テスト(分離)をより困難/不可能にすることができ、
  • @yBeeで説明されているように、隠れた依存関係/カップリングは問題と見なされる可能性があります

シングルトンを使用しない他の理由はわかりません。

12
k3b

それは常に使用法に依存します。革命は、すべてのプログラマーがこのパターンをtheオブジェクト指向パターンとして学習するという事実から来ていると思います。ほとんどの場合、それが意味のある場所とそうでない場所について考えることを忘れます。
もちろん、これはすべてのパターンに当てはまります。パターンを使用するだけでは、優れたコードや優れたソフトウェアを作成できません。

ステートレスなシングルトンがある場合、静的メソッドのみを提供するクラスを使用しないでください(または静的クラスを使用してください)。

ここ 一般的にグローバル変数とシングルトンに関する投稿。

私は著者ほど厳格ではありませんが、シングルトンが必要だと思うほとんどの場合、シングルトンは本当に必要ないことを彼は示しています。

10
StampedeXV

不変のステートレスシングルトンが静的クラスにできないことは何もできません。

-> Instance()が作成する複雑さのレベルを追加する理由はありませんが、静的メソッドへの単純な呼び出しは、リソースの点でより明確で、より保守的であり、おそらくより高速です。

彼らが間違っているということではありません。それを行うにはもっと良い方法があるということです。通常の(「ステートフル」)シングルトンが適切な方法であるシナリオがあります。シングルトンの悪点は、それらが頻繁に悪用され、グローバル変数と同じ悪い結果になることですが、シングルトンの使用が単に正しい特定のケースがあります。無国籍者にはそのようなケースはありません。

7
SF.

シングルトンの主な問題は、横断的な懸念のシナリオで使用すると、依存関係と結合を特別に隠すことです。詳細については シングルトンは病理学的嘘つき または シングルトンが悪である理由 を参照してください。

反対側から見れば、悪用されなければ、シングルトンの少ない状態が役立ち、パフォーマンスを向上させることができます。例を考えてみましょう:

interface Interface
{
    void Method();
}

class StatelessSingleton : Interface
{
    public static readonly StatelessSingleton Instance = new StatelessSingleton();
    private StatelessSingleton() { }

    public void Method() { }
}

class User
{
    public User(Interface i) { /* ... */ }
}

ここで、StatelessSingletonはインターフェースのデフォルト実装として機能し、Userコンストラクターに配置されます。ハードコーディングされた結合はなく、依存関係は隠されています。基になるインターフェースのために静的クラスを使用できませんが、デフォルトのインスタンスを複数作成する理由はありません。そのため、ステートレスシングルトンが適切な選択のように思われます。

ただし、デフォルトの実装には別のパターンを使用する必要があります。

class Implementation : Interface
{
    private readonly Action _method;

    public Implementation()
    {
        _method = new Action(() => { /* default */ });
    }

    public Implementation(Action custom)
    {
        _method = custom;
    }

    public void Method()
    {
        _method();
    }
}

これはStatelessSingletonに関してパフォーマンスに影響しますが、インターフェースの一般的な実装を構成します。同様のソリューションが IProgress インターフェースで使用されています。

もう一度言いますが、なぜデフォルトの振る舞いの複数の実装の作成を許可するのですか?しかし、2つを組み合わせることができます。

class Implementation : Interface
{
    public readonly Implementation Default = new Implementation();

    private readonly Action _method;

    private Implementation()
    {
        _method = new Action(() => { /* default */ });
    }

    public Implementation(Action custom)
    {
        _method = custom;
    }

    public void Method()
    {
        _method();
    }
}

結論として、シングルトンが役立つ場所が(デフォルトとして示されているように)あると思います。シングルトンの主な定義では、クラスの複数のインスタンスを作成できないとしています。それは原子力です。エネルギーまたは爆弾を生成できます。それは人間次第です。

3
yBee