私は、2つのシングルトンクラスApp
とConfiguration
があるPythonアプリケーションに取り組んでいます。
前者は単純明快で、1つのApp
インスタンスのみをインスタンス化するだけです。後者は物議を醸すようです。
私が行った検索から、アプリケーションの構成ファイルを更新する(その後アプリケーションを更新する)他のモジュールからConfiguration
にアクセスできる必要があります。これを行うために、メタクラスの___call__
_メソッドを使用してインスタンス化を制御することにより、クラスをシングルトンとして設計しました。インスタンスにアクセスするには、任意のモジュールで次のようにします。
_from app.config import Configuration
class Foo:
def __init__(self, *args, **kwargs):
self.config = Configuration()
_
さて、Foo
はApp
に由来するいくつかの機能です。
_from app import App
class Foo:
def __init__(self, *args, **kwargs):
self.config = App().configuration
_
ここで、App()
はアプリケーションシングルトンを返し、_.configuration
_はConfiguration
が最初にインスタンス化された属性でした。さらに検索すると、Pythonはモジュールを1回だけロードするので、_app.config
_モジュールをシングルトンとして使用することもできます。したがって、クラスをシングルトンとして定義したり、モジュールをシングルトンとして扱うかどうかに関係なく、シングルトンパターンが残ります。
これらのいずれかで何が問題になっていますか:
いずれにせよ、アプリケーション全体に対して単一の構成が必要です。複数のインスタンスを作成すると、潜在的な競合状態が発生するため、これを処理するスマートな方法のように見えます。さらに、ロギングなどの機能も拡張できるようですよね?
1つしかないと絶対に1つだけ必要はよく混同されます。
後者は確かにシングルトンを必要としますが、前者は構成オブジェクトを作成し、それが使用される場所にそれを注入するためのいくつかの規則のみを必要とします。
構成オブジェクトが絶対に1度だけ存在する必要があると考える場合は、グローバル構成を使用していることが原因である可能性があります。このようなショートカットは便利ですが、必ずしも望ましいとは限らない、非常に大きな依存関係が作成されます。
いずれにせよ、アプリケーション全体に対して単一の構成が必要です。
外部構成ファイルを使用できます。複数の構成オブジェクトをインスタンス化することができます。これらのオブジェクトはすべて、このまさにこのファイルから単に読み書きすることができます。したがって、明らかに複数のインスタンスを持つことができますが、構成関連の設定の単一のセットがあります。
複数のインスタンスを作成すると、潜在的な競合状態が発生するため、これを処理するスマートな方法のように見えます。
シングルトンは競合状態に関して何の違いもありません。 2つのスレッドからシングルトンオブジェクトの同じメンバーにアクセスすることもできます。オブジェクトは同じなので、競合状態もあります。 初期化と使用方法の点でスレッドセーフを混乱させているかもしれません。 Singleton
スレッドセーフなw.r.tを作成できます。 複数のカラフルな方法 で初期化しますが、これは この単一インスタンスがスレッドセーフでも使用できる であることを意味しません。
さらに、ロギングなどの機能も拡張できるようですよね?
確かにそうですが、一度に1つのロギング実装より多くを提供するのは非常に困難です。シングルトンをそれ以上抽象化することはできないため、アプリケーションの個別の部分に使用します。シングルトンを通してすべてを公開する必要があり、事態はかなり迅速に複雑になります。
これらのいずれかで何が問題になっていますか:
- クラスシングルトンの使用
- モジュールをシングルトンとして扱う
public programming "interface"(API)を見ても、クラスの使用を完全に推測することはできません。つまり、依存関係が隠されています。適切に実装されたシングルトンにより、クラスは依存関係について嘘をつくが可能になります。どこからでもシングルトンにアクセスするということは、何をどこに保存しているかを調べるには、ソースコードを細かくスキャンするを行う必要があるということです。これにより、コードが非常に脆弱になります。
次に、突然別の構成が必要だと判断した場合、シングルトンの実装を変更するとoverpriceになります。シングルトンを使用したクラスをすべて変更して、別の実装を採用する必要があります。
アーキテクチャに関する私の個人的な提案は、Singleton
を回避することです。少なくとも、app.configを使用する場合は、それを複数のクラスの後ろに隠してください。予想されるconsumptionクラスが使用する構成設定のサブセット。おそらくentireの設定にアクセスする必要はありませんeach and every conventioning class、あなたは...?