2009-07-03 4 views
6

状況は次のとおりです。あまりにも多くのことをしているクラスがあります。主に構成情報にアクセスするためのものですが、データベース接続もあります。これはシングルトンとして実装されているため、これはまた、ほとんどのコードがかなり密接に結合されているため、単体テストを難しくしています。これは、インポート時の依存関係を作成する(Pythonでこれをやっている)ので、特定のモジュールを特定の順序でインポートする必要があるため、さらに問題があります。理想的には、私はこれを2つのクラスに分割し、それを非シングルトンにしたいと思います。どちらがもっと悪いのですか:不必要なシングルトンや神のオブジェクトですか?

幸いにも私の雇用主は、この種のテストが良いという事実に暖かくなり、コードをよりテスト可能にするなら、私がこのような変更を加えることを許可する意思があります。しかし、私は彼らが私にを過度に費やすことを喜んで受け入れるのではないかと疑う。時間。むしろ、私はむしろ根本的すぎることを試みるのではなく、徐々にこれを修正したいと思います(シングルトン)構成オブジェクトと(非シングルトン)データベースオブジェクトに

  1. ブレーク設定オブジェクト:

    だから、私はここに3つの選択肢を参照してください。これは少なくとも、インポート時の依存関係としてデータベースを削除することを可能にします。

  2. 構成オブジェクトを非シングルトンにして、それを必要とするオブジェクトに渡します。私はこれが短期的なニーズをよりよく解決すると感じていますが、かなり時間がかかると思います。
  3. あなたの答えであなたが提案したことを考えなかったことをしてください。 :-)

どうすればいいですか?

答えて

5

あなたは2つのクラスに分かれていると思います。ファクトリを使用して、必要に応じてデータベースコンテキスト/接続を作成することを検討することをお勧めします。この方法では、接続を、オブジェクトの存続期間中に単一の接続を維持するのではなく、必要に応じて作成/廃棄される作業単位の単位として扱うことができます。しかし、YMMV。

構成に関しては、シングルトンが正しい選択であることがわかった場合の1つです。単体テストが難しいので、必ずしもそれをダンプするとは限りません。ただし、インターフェイスを実装するには、それを構築することを検討することをお勧めします。次に、依存関係注入を使用して、テスト中にインタフェースの疑似インスタンスを提供することができます。あなたの生産コードは、注入された値がnullの場合にシングルトンインスタンスを使用するように、またはシングルトンインスタンスを注入するために構築されます。また、プライベートメソッドを使用して再初期化できるようにクラスを構築し、setup/teardownテストメソッドでこれを呼び出して、テストに適切な構成があることを確認することもできます。前者は後者の実装に優先していますが、インタフェースを直接制御することはできません。

変更を段階的に行うことは間違いなく道のりです。可能であれば、テストで現在の機能をラップし、変更した後でもテストが合格していることを確認してください(もちろん、変更を直接処理するものではありません)ので、他のコードを破壊していないことを確認する良い方法です。

5

あなたのコードを見ることなく知るのは難しいですが、あなたが言うことをしないでください。最初に手順1を実行し、データベースを分割します。

これがすばやく戻ってくると、2つではなく1つの小さなオブジェクトだけが停止するようになりました。したがって、ステップ2はすばやくなります。あるいは、この段階で、シングルトンからリファクタリングできる他のコードを見ることができます。

あなたはステップバイステップで、どのステップでも巨額の時間税を払うことなく、シングルトンにあるものを消滅させるまで減らすことができます。

たとえば、設定の一部が独立している場合、たとえば、構成の一部を一度にシングルトンにすることができます。だから多分GUI構成は、ファイル構成がリファクタリングされている間にシングルトンを残した、あるいはそれに類するものでしょうか?

+0

私は思っていなかったものが*と思われます。オブジェクトを分割することで、シングルトンを解除することが容易になります(単語の場合)。 –

+0

どのようにdesingulate? –

+1

または複数かもしれませんか? :-) –

2

オプション1は、すべてのアプリケーションで必要なものです。設定オブジェクトシングルトンとデータベースオブジェクトは、オンデマンドで作成したり、注入したりします。

構成オブジェクトをシングルトンとして使用することは、常に私には最適です。構成ファイルは1つしかありません。アプリケーションの起動時には常にそのファイルを読みたいと思っています。

+0

しかし、それが問題の原因です。アプリケーションの開始時に設定ファイルを読みたいのですが、設定オブジェクトがグローバルである場合、他のコードが初期化される前に他のコードにアクセスしようとしないようにするにはどうすればよいですか?私はそれが音よりも防止するのがはるかに難しいことを知っています。 –

+0

私は、シングルトンでアクセスされるすべてのプロパティを作成し、すべてのコンフィグレーションクラスの初期状態ロジックをその静的コンストラクタに入れることに気づきました。これは、構成オブジェクトの任意のプロパティに最初にアクセスしようとするとすぐに、それ自体を初期化することを意味します。私はC#でそのアプローチを使用していますが、Pythonが静的なプロパティとコンストラクタで同じアプローチをしているかどうかはわかりません。 – sipwiz

2

言い訳私はどんなのPythonを知らないので、私は任意の擬似コードは、理にかなって願っていたという事実...あなたのシングルトンの責任は小さくなるように

私は最初の2つの部分にオブジェクトを分割したいです残りの設定シングルトンを取り、それを通常のクラスに変更します(2番目の提案を実行するようにします)。

私はこれまで私は、構成クラスのメソッドを公開し、新しいラッパーシングルトンを作成したいということだと思いたら:アプリケーションが最初に行うことがのインスタンスを注入している今

class ConfigurationWrapper : IConfigurationClass 
{ 
    public static property ConfigurationWrapper Instance; 

    public property IConfigurationClass InnerClass; 

    public method GetDefaultWindowWidth() 
    { 
     return InnerClass.GetDefaultWindowWidth(); 
    } 

    etc... 
} 

ConfigurationClassをラッパーに追加します。

ConfigurationClass config = new ConfigurationClass() 
ConfigurationWrapper.Instance.InnerClass = config; 

最後に、あなたは現在、(クイック検索可能と置き換える必要があります)ラッパーシングルトンへ上シングルトンに依存しているクラスを移動することができます。今度はクラスを1つずつ変換してコンストラクタを使ってconfigオブジェクトを取得してステージ2を完成させることができます。時間のないものはラッパーシングルトンを使用できます。一度それらを移動すると、ラッパーを取り除くことができます。

一方、使用法のリファクタリングを無視して、テスト用のシングルトンラッパーに模擬設定クラスを挿入するだけで、基本的には貧しい人の依存関係注入を行うことができます。

関連する問題