1

アプリケーションが機能するために必要な、データベースから取得されたオブジェクトのコレクションをどこに保存するかを見つけようとしています。たとえば、Reportオブジェクトを使用するレポートアプリケーションを再設計しようとしていParameterます。これらのオブジェクトは、XML形式でデータベースに保存されます。Dictionary<string, string>最も単純なレベルでは、定義のコレクションを(オブジェクトキー、オブジェクト定義XML)として格納できます。

XML定義からのこれらのオブジェクトの作成を処理するファクトリパターンを実装したいと思います。

IReport GetReport(string reportName)
IParameter GetParameter(string parameterName)

これらのメソッドでは、ファクトリがレポートとパラメータのコレクションを保存する必要があります。

だから、私の質問は次のとおりです。

  1. 工場でオブジェクトのコレクションを保存する必要があるのか​​、それとも定義からオブジェクトを作成することだけを担当するのか、メソッドを次のように変更する必要があります。IReport GetReport(string reportDefinition)
  2. ファクトリがオブジェクトを格納する必要がある場合、ファクトリクラスのコンストラクタにコレクションを単純に注入する必要がありますか?
  3. 単体テスト-#2のルートに進むと、テストコレクションを工場に注入するだけだと思いますよね?
4

3 に答える 3

2

これは、すべてSRP (Single Responsibility Principle)に準拠するさまざまな方法で構成できます。

1 つの方法は次のとおりです。レポート識別子を受け取り、インスタンスIReportLoadingServiceを返すメソッドを使用して、 1 つのインターフェイス を持ちます。IReport

これの実装は、依存関係としてIReportLoadingService持つことができます。IReportDefinitionRetrievalService

public class ReportLoadingService : IReportLoadingService
{
    private readonly IReportDefinitionRetrievalService _definitionService;

    public ReportLoadingService(IReportDefinitionRetrievalService definitionService)
    {
        _definitionService = definitionService;
    }

    public IReport GetReport(string reportName)
    {
        var reportDefinition = definitionService.GetDefinition(reportName);
        return GenerateReportFromDefinition(reportDefinition);
    }

    private IReport GenerateReportFromDefinition(string definition)
    {
        // Logic to construct an IReport implementation
    }

}

のライブ実装はIReportDefinitionRetrievalService、データベースにアクセスして XML を返します。これで、別のサービスが実際にレポート定義を取得する責任を負いながら、インスタンスにデータを入力する責任が発生しますReportLoadingServiceIReport

単体テストでは、必要なことを実行する のモックを作成できますIReportDefinitionRetrievalService(辞書で定義を検索するなど)。優れたモッキング フレームワークについては、Moqを参照してください。次のようなことができるようになります。

[Test]
public void GetReportUsesDefinitionService()
{
    var mockDefinitionService = new Mock<IReportDefinitionRetrievalService>();
    mockDefinitionService.Setup(s => s.GetDefinition("MyReportName")).Returns("MyReportDefinition");

    var loadingService = new ReportLoadingService(mockDefinitionService.Object);

    var reportInstance = loadingService.GetReport("MyReportName");

    // Check reportInstance for fields etc

    // Check the definition service was used to load the definition
    mockDefinitionService.Verify(s => s.GetDefinition("MyReportName"), Times.Once());
}
于 2012-08-17T14:44:17.943 に答える
2

アプリケーションは永続的に無知である必要があるため、レポート ファクトリ (またはリポジトリは、データ ストアよりもファサードを表すより適切な用語です。実際には、実際にはリポジトリではなくデータ アクセス オブジェクトです) は、レポート定義形式を使用しないでください。

Get メソッドは、レポートの一意の識別子 (これはレポート名である必要がありますか?) を受け取り、レポート エンティティのすべての値を持つ DTO 型を返す必要があります。

抽象ファクトリ パターンを使用して、リポジトリのさまざまな実装、XML 逆シリアル化を行うもの、および単体テスト用のモック実装を使用できます。

データベースがデータ ストアとして既にある場合、レポジトリはコレクションをメモリに保存する必要はありませんが、アプリケーションが抽象化に対して動作している場合は、レポジトリにキャッシングを追加する方が簡単です。

于 2012-08-17T14:38:28.583 に答える
0

1.ファクトリはオブジェクトのコレクションをまったく格納する必要がありますか、またはメソッドを IReport GetReport(string reportDefinition) に変更して、定義からオブジェクトを作成することのみを担当する必要があります

上記のどれでもない。ファクトリは具体的な実装セレクタです。入力に基づいて具体的なオブジェクトをインスタンス化する静的メソッドとして実装されます。インターフェイスと名前を正しく分離する作業が完了しました。そこで止まれ。

static IReport GetReport(string reportName)

IReport concreteReport = Factory.GetReport("myReportName")

単体テストによる工場のテストは簡単です。レポート名の配列を作成し、IReportリフレクションまたは任意の既知のアサーションを介して正しい実装であることを確認できます。依存性注入は、まったく別のトピックです。

于 2012-08-17T14:48:05.063 に答える