4

私はほとんどゼロから新しいウェブサイト プロジェクトを書いています。プロジェクトは C# ですが、私のバックグラウンドは PHP です (以下の疑似コードは、簡潔で宣言的であるように努めており、混在している場合があります)。

問題

2 つの場所のいずれかから構成データを取得する必要があります。ローカル データベースから取得する場合もあれば、Soap サービスから取得する場合もあります。どちらのソースからも同じ Model オブジェクトのセットを作成できるはずです。

データは、異なるデータ ソースの完全に異なる構造に格納されます。いくつかの異なる Soap 応答は、Soap 側からつなぎ合わせる必要がありますが、DB 構造は、コードでモデル オブジェクトを構造化する方法に非常に近いものです。

構成は、オブジェクトのツリーで構成されます。製品には、適用時の条件を持つオプションを含むプロパティが含まれます。

目標

可能な限り懸念事項を分離したいと思います (うまくいけば、テスト/保守/拡張機能の両方を容易にするため):

  • 私のモデルオブジェクトは、データの永続性または取得について何も知らないはずです
  • Data Persistence オブジェクトは、可能な限り、データ ソースの正確なタイプにとらわれないようにする必要があります。
  • オブジェクトの作成をできるだけ分離したいと考えています。

質問

私はこれに関するさまざまな設計パターンを認識しています (ただし、それらを完全に理解しているかどうかは完全にはわかりません)。Programmersについてこれと同様の質問をしたところ、 Persistence Ignorance (詳細はこちら) とRepositoryパターンに関する回答がありました。どちらも Microsoft の世界の概念のようです。

私が知る限り、「Persistence Ignorance」は単に、データ ストレージ メカニズムについて何も知らない Model オブジェクトを持つという概念であり、Repository パターンは Data Mapper パターンと非常によく似ているように見えますが、ファサードのようなものである可能性があります。実際に起こっていることの多くを隠します。

だから私の質問は:

Data Mapper パターンでは、Model オブジェクトごとに 1 つの Mapper が必要ですか? 構成ツリー全体に 1 つではなく?

したがって、これらすべての Mapper オブジェクトを使用する構成ツリー構築オブジェクトが必要でしょうか?

class ConfigBuilder() {
    public ConfigBuilder (productMapper, propertyMapper, optionMapper, conditionMapper) {
        // save them into local properties
    }

    public Products() {
       var products = productMapper.FetchAll();

       foreach (var product in products) {
           AddProperties(product);
       }

        return products;
    }

    private AddProperties(products) { /* ... */ }
    private AddOptions(property) { /* ... */ }
    private AddConditions(option) { /* ... */ }
}

これは良い解決策のように思えますか?

オブジェクトを構築するロジックはどこに配置する必要がありますか?

ある時点で、Soap サービスから取得した XML データのランダムな配列から構成オブジェクトを構築するためのかなりの量のロジックと、データベースから同じことを行うための少量のロジックが必要になります。

Mapper オブジェクトの別のインスタンスにオブジェクトを構築するロジックを配置する必要がありますか?

interface IProductMapper { FetchAll; FetchByCode; Create; Delete; Update  }

class ProductMapperXml implements IProductMapper {
    public ProductMapperXml(xmlDataSource) {}
    public FetchAll() { /* A whole bunch of logic to create the Product objects from XML data source */ }
}

class ProductMapperDatabase implements IProductMapper {
    public ProductMapperDatabase(databaseConnection) {}
    public FetchAll() { /* Select and build products from the database */ }
}

これでいいですか?このロジックをさらに抽象化する必要がありますか? もしそうなら、なぜですか?ProductMapperXmlまた、オブジェクト自体がかなりのロジックを持ち、Product内部でオブジェクトを作成する責任も負っていることに少し不安があります。私はそれProductFactoryを何らかの形で渡す必要がありますか?それともファクトリメソッドを使用しますか?

私の提案よりもこれを解決するエレガントな方法があるかどうか教えてください。また、見逃した抽象化またはデザインパターンのレイヤーがあれば、それから恩恵を受けることができますか?

4

1 に答える 1

3

回答が来ないので、私はこれを自分で書きます。

私はDataMapperパターンに行き着きました-賢明な方法でそれを実装したことを願っています.

クラス自体を使用してツリーを構築できたため、Factory クラスを使用することはありませんでした。

一連の Mapper インターフェースを作成しました。

interface Models.Interfaces.IModel {}
interface Mappers.Interfaces.IMapper {}
interface Mappers.Interfaces.IDatabaseMapper : IMapper {}
interface Mappers.Interfaces.IXmlMapper : IMapper {}

すべてのモデルを作成しました:

class Models.Product : IModel {}
class Models.Property : IModel {}
class Models.Option : IModel {}
class Models.Condition : IModel {}

そして、各モデルに 2 つのマッパー クラスを与えました。

class Mappers.ProductDatabaseMapper : IDatabaseMapper {}
class Mappers.ProductXmlMapper : IXmlMapper {}
/* ... (same for each model) */

各 Mapper クラスには、その子を作成するメソッドがあります。

class ProductDatabaseMapper :IDatabaseMapper {
    public List<Product> FetchAllWithChildren {
        var productRows = DbManager.FetchAll("Product");
        var products = List<Product>();

        foreach(var productRow in productRows) {
            var product = new Product(productRow["Name"]);
            product.Properties = PropertyManagerInstance.FetchAllWithChildren(product);
            products.Add(product):
        }

        return products;
    }
}

これはかなりきちんとした解決策を提示すると思います。私のさまざまなMapperクラスがオブジェクト自体を作成しているという事実については、まだ少し心配していますが。しかし、必要になったときにのみ、それを工場に分離すると思います。

于 2012-10-22T15:20:12.427 に答える