2

私が現在取り組んでいるデータベースアプリケーションは、あらゆる種類の設定をデータベースに保存します。これらの設定のほとんどは、特定のビジネスルールをカスタマイズするためのものですが、他にもいくつかあります。

アプリには、特定の複雑な計算など、特定のタスクを具体的に実行するオブジェクトが含まれています。これらの非UIオブジェクトは単体テストされていますが、これらのグローバル設定の多くにアクセスする必要もあります。これを今実装している方法は、実行時にアプリケーションコントローラーによって入力されるオブジェクトプロパティを与えることです。テスト時には、テストでオブジェクトを作成し、(データベースからではなく)テスト用の値を入力します。

これはうまく機能しますが、いずれの場合も、これらすべてのオブジェクトにグローバル設定オブジェクトが必要になるよりもはるかに優れています---もちろん効果的に単体テストが不可能になります:)欠点は、数十のプロパティを設定する必要がある場合や、必要な場合があることです。これらのプロパティをサブオブジェクトに「浸透」させます。

したがって、一般的な質問は、コードを単体テストできる一方で、グローバル変数を必要とせずに、プロジェクト内のグローバルアプリケーション設定へのアクセスをどのように提供するかということです。これは何百回も解決された問題であるに違いありません...

(注:お気づきのように、私は経験豊富なプログラマーではありませんが、学ぶのは大好きです!もちろん、このトピックについてはすでに調査を行っていますが、最初にいくつかを探しています。 -手の経験)

4

4 に答える 4

1

Martin Fowlers ServiceLocator パターンを使用できます。php では、次のようになります。

class ServiceLocator {
  private static $soleInstance;
  private $globalSettings;

  public static function load($locator) {
    self::$soleInstance = $locator;
  }

  public static function globalSettings() {
    if (!isset(self::$soleInstance->globalSettings)) {
      self::$soleInstance->setGlobalSettings(new GlobalSettings());
    }
    return self::$soleInstance->globalSettings;
  }
}

プロダクション コードは、次のようにサービス ロケーターを初期化します。

ServiceLocator::load(new ServiceLocator());

テストコードでは、次のようにモック設定を挿入します。

ServiceLocator s = new ServiceLocator();
s->setGlobalSettings(new MockGlobalSettings());
ServiceLocator::load(s);

これは、テスト目的で交換できるシングルトンのリポジトリです。

于 2008-08-15T12:25:19.483 に答える
1

Service Locator パターンから構成アクセスをモデル化するのが好きです。これにより、必要な構成値を取得するための単一のポイントが得られ、それをアプリケーションの外の別のライブラリに配置することで、再利用とテスト容易性が可能になります。ここにいくつかのサンプル コードがあります。使用している言語はわかりませんが、C# で記述しました。

まず、ConfigurationItem をモデル化するジェネリック クラスを作成します。

public class ConfigurationItem<T>
{
    private T item;

    public ConfigurationItem(T item)
    {
        this.item = item;
    }

    public T GetValue()
    {
        return item;
    }
}

次に、構成項目の public static readonly 変数を公開するクラスを作成します。ここでは、単に xml である構成ファイルから ConnectionStringSettings を読み取っています。もちろん、より多くのアイテムについては、任意のソースから値を読み取ることができます。

public class ConfigurationItems
{
    public static ConfigurationItem<ConnectionStringSettings> ConnectionSettings = new ConfigurationItem<ConnectionStringSettings>(RetrieveConnectionString());

    private static ConnectionStringSettings RetrieveConnectionString()
    {
        // In .Net, we store our connection string in the application/web config file.
        // We can access those values through the ConfigurationManager class.
        return ConfigurationManager.ConnectionStrings[ConfigurationManager.AppSettings["ConnectionKey"]];
    }
}

次に、ConfigurationItem を使用する必要がある場合は、次のように呼び出します。

ConfigurationItems.ConnectionSettings.GetValue();

そして、タイプ セーフな値が返されるので、それをキャッシュしたり、好きなことをしたりできます。

サンプルテストは次のとおりです。

[TestFixture]
public class ConfigurationItemsTest
{
    [Test]
    public void ShouldBeAbleToAccessConnectionStringSettings()
    {
        ConnectionStringSettings item = ConfigurationItems.ConnectionSettings.GetValue();
        Assert.IsNotNull(item);
    }
}

お役に立てれば。

于 2008-08-15T12:57:22.337 に答える
0

通常、これは ini ファイルまたは XML 構成ファイルによって処理されます。次に、必要に応じて設定を読み取るクラスを作成します。

.NET にはこれが ConfigurationManager クラスに組み込まれていますが、実装は非常に簡単で、テキスト ファイルを読み取るか、XML を DOM にロードするか、コードで手動で解析するだけです。

データベースに構成ファイルを入れることは問題ありませんが、データベースに結び付けられ、ini/xml ファイルが解決するアプリの追加の依存関係が作成されます。

于 2008-08-15T11:44:52.217 に答える
0

これは私がしました:

public class MySettings
{
    public static double Setting1
        { get { return SettingsCache.Instance.GetDouble("Setting1"); } }

    public static string Setting2
        { get { return SettingsCache.Instance.GetString("Setting2"); } }
}

これを別のインフラストラクチャ モジュールに入れて、循環依存関係の問題を取り除きます。
これを行うと、特定の構成方法に縛られず、アプリケーション コードで文字列が混乱することはありません。

于 2008-08-15T12:20:26.450 に答える