XML設定ファイルのクラス表現を渡すことは、デメテルの法則に違反することを気にする必要がありますか?

StackOverflow https://stackoverflow.com/questions/3689118

質問

ツールを使用して、階層的に整理されたXMLファイルのクラス表現を自動的に生成します。 XMLファイルは、アプリがアクセスできるようにする必要がある設定ファイルです(読み取り専用)。

トップレベルのノードを渡すと(例: AppSettings)1つ以上の設定にアクセスする必要があるクラスには、次のようなコードに簡単に表示できます。

var windowSize = AppSettings.Views.Windows.Dashboard.Size;

これはデメテルの法則の深刻な違反のようですが、私は気にするべきかどうか疑問に思っています。私は各クラスに必要な正確な設定を通過するために大きな痛みを抱くことができましたが、この場合、それらの複数のドットがどのように私を傷つけるかを見るのに苦労しています。

私のコードをXMLファイル形式にしっかりと結合して、将来メンテナンスの問題やその他の問題を作成する可能性が高いですか、それともOOPの設計原則に宗教的に従わないことが理にかなっている例ですか?

役に立ちましたか?

解決

はい、非常に実用的な理由で、気にする必要があります!

設定を使用するクラスは、絶対にそれらの設定の保存方法に依存する必要はありません。

将来、アプリケーションの複数のテーマをサポートしたいと想像してください。たとえば、ダッシュボードのサイズの可能性は1つではなく、多くの可能性になります。

AppSettings.Views.ThemeA.Windows.Dashboard.Size;
AppSettings.Views.ThemeB.Windows.Dashboard.Size;

UIクラスにはまだ1つのものが必要です。これは、その可変ウィンドウズの値であり、現在使用されているテーマを知る必要はありません。

XMLインターフェイスを持っているところはどこでも、コード内のどこでもスキーマに依存したくはありませんが、1つの中央の場所にのみです。

たとえば、このように、内部で使用する設定をマップに配置できます。

public class SettingsReader {

    public static final String VIEW_WINDOW_DASHBOARD_SIZE = "Views.Windows.Dashboard.Size";

    private Map settings = new Hashmap();

    public SettingsReader(AppSettings appSettings) {
        settings.put(VIEW_WINDOW_DASHBOARD_SIZE, appSettings.Views.Windows.Dashboard.Size);
    }

    public String getSettingValue(String key) {
        return settings.get(key);
    }
}

次に、このようなテーマをサポートするためにリファクタリングする場所が1つだけあります。

public class SettingsReader {

    public static final String VIEW_WINDOW_DASHBOARD_SIZE = "Views.Windows.Dashboard.Size";

    private Map settings = new Hashmap();

    public SettingsReader(AppSettings appSettings, String theme) {
        settings.put(VIEW_WINDOW_DASHBOARD_SIZE, appSettings.Views + theme + Windows.Dashboard.Size);
    }

    public String getSettingValue(String key) {
        return settings.get(key);
    }
}

擬似コードとJavaコードの私の組み合わせが人々、特に人々を混乱させる可能性があるという理由だけで、最後のメモです。 appSettings.Views + theme + Windows.Dashboard.Size: :XMLインターフェイスを使用する場合、XPathは通常、素敵なライブラリのおかげでオブジェクトを操作する場合でも非常に便利です jxpath (Javaの場合、他の言語についてはわかりません)。

他のヒント

愚かなデータを吐き出している場合、それを行うより良い方法はありません。

ただし、コンテキストをプッシュしてポップできるソリューションに向けて取り組む傾向があります。

PushContext(AppSettings)
  // do child contexts
  PushContext(Views)
    // more child contexts
    PushContext(Windows)
    // etc.
    PopContext()
  PopContext()
PopContext()

通常、異なるプッシュは異なる機能またはファイルにありますが、説明のためにここに示されています。とにかく、ビューのコンテキストに押し込むと、オブジェクトの根源にいるかのようにそれを解析します。

ただし、これがdumbdataの場合、「ビュー」がそれを解析するコードに表すタイプのものを渡すこともできます。トップレベル、あなたのコードは次のようになります:

views.ParseSettings(AppSettings.Views);
locale.ParseSettings(AppSettings.Locale);
network.ParseSettings(AppSettings.Network);

これは確かにLOD POVから「クリーン」になるでしょうが、あなたが持っている設定の数には価値がないかもしれません。ただし、スコープの深さがあると、多くの設定があるという意味である可能性があるため、それらを責任のある領域に分割することは(設定の読み込みと保存のために)おそらく賢明です。

すべてのものは相対的であり、それは本当にプロジェクトのサイズと、メンテナンスに関心がある場合に依存します。

メンテナンスを気にかけている場合、コードベースの残りの部分に構成ソースによって課される制限を強制したくありません。

これを達成する最良の方法は、インターフェイスにコーディングし、その背後にある実装を非表示にすることです。そうすれば、コードには構成インターフェイスとの契約があり、実際の構成がどのようにロードされるかは気にしません。

public interface IConfiguration
{
    Size ViewSize { get; }
}

public class AppSettingsConfiguration : IConfiguration
{
     public Size ViewSize
     {
          return AppSettings.Views.Windows.Dashboard.Size;
     }
}

すべての消費コードは、IconFigurationインターフェイスに対してコーディングする必要があります。これは、最小限の影響で構成を取得する方法を変更できることを意味します。

自動世代は、大きなプロジェクトの問題になる可能性があります。

単一の場所(たとえば単一のパッケージ)から生成されたコードを使用する場合、問題はないかもしれません。

コードを使用する場合:

var windowSize = AppSettings.Views.Windows.Dashboard.Size;

多くの場所で、あなたはこの結合の一部を隠したいかもしれません。 AppSettings:

getSize() {
  return Views.Windows.Dashboard.Size;
}

しかし、すべてのクラスにこれを行う必要がある場合、おそらくそれは実行可能ではないかもしれません。

最良の決定は、プロジェクトのサイズ(および成長する予定の場合)、それをしなければならない時間、および生成されたコードの量に依存します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top