2009-10-16 6 views
8

私は、メソッドからメソッドへ、パッケージの境界を越えてコールツリーを上下に入れられるオブジェクトという名前のオブジェクトを持っています。それは約50の状態変数を有する。各メソッドは、その出力を制御するために1つまたは2つの変数を使用することがあります。神オブジェクト - 'マスター'オブジェクトへのカップリングを減らす

私はこれが悪い考えです。メソッドが機能する必要があるかどうか、あるいは現在のモジュールとまったく関係のないモジュールYのパラメータの特定の組み合わせで何が起こるかを簡単に見ることができません。

この神オブジェクトへの結合を減らす、または理想的にはそれを除去するための、良いテクニックは何ですか?自分の必要なパラメータについて

   PortefeuillesReference pr = new PortefeuillesReference(); 
      pr.ExporterExcelParFonds(parametres); 
+0

"パラメータ"は構成オブジェクトですか? –

+0

はい、そうです。ビジネスレイヤーに必要なパラメータをUIに持たせるために使用されます。 –

答えて

9

最初に、明白なことを言う危険性があります。メソッドではなく、神オブジェクトです。

しかし、他のメソッドを呼び出すため、膨大な量のパラメータを必要とするメソッドにつながる可能性があります。それは恐らくすべてを神の目的に置くためのインスピレーションでした。あまりにも多くのパラメータを持つこのようなメソッドの簡略化した例を示します。あなたは

public void PrintFilteredReport(
    Data data, FilterCriteria criteria, ReportFormat format) 
{ 
    var filteredData = Filter(data, criteria); 
    PrintReport(filteredData, format); 
} 

:-)ここでは「あまりにも多くの」== 3は、そこで問題は、私たちが神のオブジェクトに頼ることなく、パラメータの量を減らすことができる方法であることを想像する必要がありますか?答えは、手続き型プログラミングを取り除き、オブジェクト指向設計を有効に活用することです。オブジェクトは、彼らの協力者を初期化するために使用されたパラメータを知らなくても、お互いを使用することができます。

// dataFilter service object only needs to know the criteria 
var dataFilter = new DataFilter(criteria); 

// report printer service object only needs to know the format 
var reportPrinter = new ReportPrinter(format); 

// filteredReportPrinter service object is initialized with a 
// dataFilter and a reportPrinter service, but it doesn't need 
// to know which parameters those are using to do their job 
var filteredReportPrinter = new FilteredReportPrinter(dataFilter, reportPrinter); 

今FilteredReportPrinter.Print方法は、一つのパラメータのみで実現することができます。この、

ちなみに
public void Print(data) 
{ 
    var filteredData = this.dataFilter.Filter(data); 
    this.reportPrinter.Print(filteredData); 
} 

懸念と依存性注入の分離のようなものは、単にパラメータを削除するだけではありません。協力者は、インタフェースを介してオブジェクトにあなたがアクセスした場合、それはあなたのクラスになり

  • 非常に柔軟性:あなたが想像できる任意のフィルタ/プリンタの実装とFilteredReportPrinterを設定することができます
  • 非常にテスト可能:あなたは缶詰とモック協力者に渡すことができますそれらが正しくユニットテストで使用されたことを確認してください。
+1

ベスト・アンサー、私の意見です。 –

0

クエリ各クライアントとそれらを注入:

呼び出し側がどうなる
 public void ExporterExcelParFonds(ParametresExecution parametres) 
    { 
     ApplicationExcel appExcel = null; 
     LogTool.Instance.ExceptionSoulevee = false; 


     bool inclureReferences = parametres.inclureReferences; 
     bool inclureBornes = parametres.inclureBornes; 
     DateTime dateDebut = parametres.date; 
     DateTime dateFin = parametres.dateFin; 

     try 
     { 
      LogTool.Instance.AfficherMessage(Variables.msg_GenerationRapportPortefeuilleReference); 

      bool fichiersPreparesAvecSucces = PreparerFichiers(parametres, Sections.exportExcelParFonds); 
      if (!fichiersPreparesAvecSucces) 
      { 
       parametres.afficherRapportApresGeneration = false; 
       LogTool.Instance.ExceptionSoulevee = true; 
      } 
      else 
      { 

例:「パラメータ」を必要とする各「オブジェクト」は「クライアント」です。各「クライアント」は、「構成エージェント」がクライアントに必要なパラメータを問い合わせるためのインタフェースを公開します。その後、Configuration Agentはパラメータ(およびクライアントに必要なパラメータのみ)を「注入」します。

+0

これを拡張することはできますか?私はこれに同意すると思うが、私は確信したい。 – gn22

+0

私は分かりません。 –

+0

詳細を追加しました。 – jldupont

1

すべてのメソッドが同じParametersクラスを使用している場合は、関連するメソッドを含むクラスのメンバ変数である必要があります。このクラスのコンストラクタにParametersを渡して、メンバ変数に割り当てますすべてのメソッドでパラメータとして渡す必要があります。

この神のクラスをリファクタリングするには、小さな部分に分割するのが良い方法です。関連するプロパティのグループを検索し、それらをそれぞれのクラスに分割します。

次に、Parametersに依存するメソッドを再訪して、作成した小さなクラスのいずれかに置き換えることができます。

コードサンプルや実際の状況がなくても良い解決策を提供するのは難しいです。

0

デザインにオブジェクト指向(OO)の原則が適用されていないようです。 「オブジェクト」という言葉に言及しているので、私は何らかのオブジェクト指向のパラダイムの中で作業していると推測します。 "コールツリー"を、あなたが解決している問題をモデル化したオブジェクトに変換することをお勧めします。 "神の目的"は間違いなく避けるべきことです。私はあなたが何か根本的なものを見逃しているかもしれないと思う...あなたがコード例を投稿すると、私はより詳細に答えることができるかもしれない。

+0

ええ、それはレガシーシステムであり、それはあまり書かれていません、私は同意します。 –

+1

コード例を掲載してください...この状況にどのように対処するかは詳細によって異なります。 – SingleShot

-2

(これはJavaまたは.NET環境内にあると仮定しています)クラスをシングルトンに変換します。 "getInstance()"という名前の静的メソッドを追加するか、名前と値のバンドルを取得するための呼び出しに似た何かを追加してください( "コード完了"の第10章を参照してください)。

ここでは難しい部分です。おそらく、これはWebアプリケーションやその他のバッチ/シングルスレッド環境内にあります。したがって、オブジェクトが本当にシングルトンでないときに適切なインスタンスにアクセスするには、静的アクセサ内の選択ロジックを非表示にする必要があります。

javaでは、「スレッドローカル」参照を設定し、各要求またはサブタスクが開始されるときに初期化することができます。次に、そのスレッドローカルの点でアクセサをコーディングします。 .NETに類似したものが存在するかどうかはわかりませんが、現在のスレッドインスタンスをキーとして使用するDictionary(Hash、Map)を使っていつでも偽装できます。

これは始まりです...(ブロブそのものは常に分解されていますが、その中に非常に似たセミグローバルな値のストアを持つフレームワークを構築しました)

+3

私はシングルトンを避けようとしています。私は実際にシングルトンを嫌うのは、それが使われているのを見ているからです。ここでそれを使うことは一歩前進です。 –

+0

-1「シングルトン」の「グローバル性」を減らすためにthreadlocalが必要であるという事実は、最初にグローバルを使用すべきでないことを示します。 OPはとにかくシングルスレッドwinformsアプリケーションについて話しているかもしれません。 –

0

動作を指定するパラメータについては、設定された動作を示すオブジェクトをインスタンス化できます。クライアントクラスはインスタンス化されたオブジェクトを単に使用します。クライアントとサービスのどちらも、パラメータの値が何であるかを知る必要はありません。たとえば、どこからデータを読み込み、FlatFileReaderを持っているかを示すパラメータの場合、XMLFileReaderとDatabaseReaderはすべて同じ基本クラスを継承します(または同じインターフェイスを実装します)。それらのうちの1つをパラメータの値に基づいてインスタンス化すると、リーダークラスのクライアントは、データがファイルかDBかどうかを知らずに、インスタンス化されたリーダーオブジェクトにデータを要求するだけです。

大きなParametresExecutionクラスをいくつかのクラスに分割することができます。クラスは、パッケージごとに1つずつあり、パッケージのパラメータのみを保持します。

構築時にParametresExecutionオブジェクトを渡すこともできます。すべての関数呼び出しで渡す必要はありません。

関連する問題