4

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

1 つまたは複数の設定にアクセスする必要があるクラスに最上位ノード (例: AppSettings) を渡すと、簡単に次のようなコードになる可能性があります。

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

これはデメテルの法則に対する深刻な違反のようですが、気にする必要があるかどうか疑問に思っています。各クラスに必要な正確な設定のみを渡すために多大な労力を費やすことができましたが、この場合、これらの複数のドットがどのように私を傷つけるのかを理解するのに苦労しています.

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

4

4 に答える 4

6

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

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

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

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

UI クラスに必要なのは、変数 windowSize の値だけです。現在どのテーマが使用されているかを知る必要はありません。

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 インターフェースを操作する場合、オブジェクトを操作する場合でも、優れたライブラリJXPath (Java の場合、私は他の言語についてはわかりません)。

于 2010-09-14T21:47:45.593 に答える
1

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

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

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

通常、異なるプッシュは異なる関数またはファイルにありますが、ここでは説明のために示しています。とにかく、Views コンテキストにプッシュすると、オブジェクトのルートにいるかのように解析されます。

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

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

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

于 2010-09-10T23:56:48.490 に答える
1

すべてのことは相対的なものであり、実際にはプロジェクトのサイズと、メンテナンスを気にするかどうかによって異なります。

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

これを実現する最善の方法は、インターフェイスにコーディングし、実装をその背後に隠すことです。そうすれば、コードは構成インターフェースと契約を結び、実際の構成がどのように読み込まれるかは気にしません。

public interface IConfiguration
{
    Size ViewSize { get; }
}

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

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

于 2010-09-16T22:47:17.087 に答える
0

大規模なプロジェクトでは、自動生成が問題になる場合があります。

単一の場所 (単一のパッケージなど) から生成されたコードを使用する場合は、おそらく問題はありません。

コードを使用する場合:

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

多くの場所で、このカップリングの一部を隠して、 でメソッドを作成したい場合がありますAppSettings

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

しかし、これをすべてのクラスに対して行う必要がある場合は、実行できない可能性があります。

最適な決定は、プロジェクトのサイズ (および拡大する予定がある場合)、実行に必要な時間、および生成されるコードの量によって異なります。

于 2010-09-14T12:47:12.773 に答える