God Objects に関するウィキペディアのエントリを読むと、クラスがあまりにも多くのことを知っているか、あまりにも多くのことを行うと、クラスは神のオブジェクトであると書かれています。
この背後にあるロジックはわかりますが、それが本当なら、どのようにしてすべての異なるクラスを結合しますか? ウィンドウ管理やDB接続などの接続にいつもマスタークラスを使っていませんか?
God Objects に関するウィキペディアのエントリを読むと、クラスがあまりにも多くのことを知っているか、あまりにも多くのことを行うと、クラスは神のオブジェクトであると書かれています。
この背後にあるロジックはわかりますが、それが本当なら、どのようにしてすべての異なるクラスを結合しますか? ウィンドウ管理やDB接続などの接続にいつもマスタークラスを使っていませんか?
メイン関数/メソッドは、ウィンドウ、データベース、およびその他のオブジェクトの存在を認識している場合があります。モデルをコントローラーに導入するなど、包括的なタスクを実行する場合があります。
しかし、それはすべての細部を管理するという意味ではありません。データベースまたはウィンドウがどのように実装されているかについては、おそらく何も知りません。
もしそうなら、それは神のオブジェクトであると非難される可能性があります.
神オブジェクトは、アプリケーション内のすべてではないにしてもほとんどのオブジェクトへの直接または間接的な参照を含むオブジェクトです。質問が観察するように、アプリケーションに神オブジェクトが含まれることを避けることはほとんど不可能です。 一部のオブジェクトは、UI、データベース、通信、ビジネスロジックなど、さまざまなサブシステムへの参照を保持する必要があります。神オブジェクトはアプリケーション定義である必要はないことに注意してください。多くのフレームワークには、「アプリケーションコンテキスト」、「アプリケーション環境」、「セッション」、「アクティベーター」などの名前の神オブジェクトが組み込まれています。
問題は、神オブジェクトが存在するかどうかではなく、それがどのように使用されるかです。極端な例で説明します...
私のアプリケーションで、数値を表示するときに表示する精度の小数点以下の桁数を標準化したいとします。ただし、精度を構成できるようにしたい。数値を文字列に変換する責任を持つクラスを作成します。
class NumberFormatter {
...
String format(double value) {
int decimalPlaces = getConfiguredPrecision();
return formatDouble(value, decimalPlaces);
}
int getConfiguredPrecision() {
return /* what ??? */;
}
}
問題は、getConfiguredPrecision何を返すかをどのように理解するかということです。1つの方法はNumberFormatter、と呼ばれるメンバーフィールドに格納するグローバルアプリケーションコンテキストへの参照を提供すること_appContextです。次に、次のように書くことができます。
return _appContext.getPreferenceManager().getNumericPreferences().getDecimalPlaces();
これにより、私たちもNumberFormatter神オブジェクトになりました!なんで?これで、アプリケーション内のほぼすべてのオブジェクトをその_appContextフィールドを介して(間接的に)参照できるようになりました。これは悪いですか?はい、そうです。
の単体テストを作成しNumberFormatterます。パラメータを設定しましょう...アプリケーションコンテキストが必要ですか?!WTF、それは私がモックする必要がある57のメソッドを持っています。ああ、それは設定マネージャーだけを必要とします... WTF、私は14のメソッドをモックする必要があります!数値設定!?!それをねじ込み、クラスは十分に単純です、私はそれをテストする必要はありません...
アプリケーションコンテキストに別のメソッドがあるとしましょうgetDatabaseManager()。先週はSQLを使用していたため、メソッドはSQLデータベースオブジェクトを返しました。しかし今週、NoSQLデータベースに変更することを決定し、メソッドは新しい型を返すようになりました。NumberFormatter変更の影響を受けますか?うーん、思い出せません...ええ、そうかもしれませんが、コンストラクターでアプリケーションコンテキストを使用しているようです...ソースを開いて見てみましょう...いいえ、幸運です:それアクセスのみgetPreferenceManager()...次に、アプリケーションコンテキストをパラメータとして受け取る他の93クラスを確認しましょう...
これと同じシナリオは、設定マネージャーまたは数値設定オブジェクトに変更が加えられた場合に発生します。物語の教訓は、オブジェクトはその仕事を実行するために必要なものへの参照のみを保持する必要があり、それらの物のみを保持する必要があるということです。の場合、NumberFormatter知っておく必要があるのは単一の整数、つまり小数点以下の桁数だけです。これは、フォーマッターを神オブジェクト自体に変えることなく、マジックナンバー(または設定マネージャー、さらには数値設定)を知っているアプリケーションの神オブジェクトによって直接作成できます。さらに、数値をフォーマットする必要のあるコンポーネントには、神オブジェクトの代わりにフォーマッターを与えることができます。すべての周りに勝ちます。
したがって、要約すると、問題は神オブジェクトの存在ではなく、他のオブジェクトに神のようなステータスを意地悪に与える行為です。
ちなみに、この問題に正面から取り組む設計原理は、デメテルの法則として知られるようになりました。または、「レストランで支払うときは、財布ではなくサーバーにお金を渡してください。」
私の経験では、これは、"Develop as you go" プロジェクト管理 (またはその欠如) の産物であるコードを扱っているときに最もよく発生します。プロジェクトが十分に検討および計画されておらず、オブジェクトの責任が緩く、適切に委任されていない場合。これらのシナリオでは、明確な組織や委任を持たないコードのキャッチオールである「神のオブジェクト」が見つかります。
神オブジェクトの問題は、さまざまなクラスの相互接続性や結合ではなく、神オブジェクトが、その派生子のすべての責任とは言わないまでも、多くの場合、ほとんどの責任を果たすことができ、かなり予測不可能であるという事実です (他の誰によっても)。開発者より) 彼らの定義された責任が何であるかについて。
「複数の」クラスについて知っているだけでは、そのクラスが神になるわけではありません。いくつかのサブ問題に分割されるべき問題を解決するために 複数のクラスについて知ることは、その人を神にします。
特定のオブジェクトが知っているクラスの数ではなく、問題をいくつかのサブ問題に分割する必要があるかどうかに焦点を当てる必要があると思います(指摘したように、いくつかのクラスについて知る必要がある場合があります)。
神々は誇大宣伝されています。