10

私は当初、このコード プロジェクトの記事で概説されている s# アーキテクチャの例に従ってシステムを設計しました(残念ながら、私は NHibernate を使用していません)。基本的な考え方は、永続化レイヤーと通信する必要があるドメイン オブジェクトごとに、対応するデータ アクセス オブジェクトを別のライブラリに持つというものです。各データ アクセス オブジェクトはインターフェイスを実装し、ドメイン オブジェクトがデータ アクセス メソッドにアクセスする必要がある場合、常にインターフェイスに対してコーディングし、DAO 自体に対してコーディングすることはありません。

当時も今も、このデザインは非常に柔軟だと思いました。しかし、ドメイン モデル内のオブジェクトの量が増えるにつれて、ここに組織上の問題がないか疑問に思うようになりました。たとえば、ドメイン内のほぼすべてのオブジェクトは、最終的に対応するデータ アクセス オブジェクトとデータ アクセス オブジェクト インターフェイスになります。それだけでなく、これらはそれぞれ別の場所にあるため、いくつかの名前空間をシフトするような単純なことをしたい場合、維持するのがより困難になります。

興味深いことに、これらの DAO (および対応するインターフェイス) の多くは非常に単純な生き物です。最も一般的なものには、GetById() メソッドが 1 つしかありません。私は次のようなたくさんのオブジェクトになってしまいます

public interface ICustomerDao {
  Customer GetById(int id);
}

public interface IProductDao {
  Product GetById(int id);
}
public interface IAutomaticWeaselDao {
  AutomaticWeasel GetById(int id);
}

それらの実装者も通常非常に些細なことです。これは、単純なデータ アクセス タスク用に 1 つのオブジェクトを用意し、もう少し何かを必要とするタスクのために専用のデータ アクセス オブジェクトの作成を予約することで戦略を切り替えることで、別の方向に進む方が簡単ではないかどうか疑問に思っています。複雑。

public interface SimpleObjectRepository {
      Customer GetCustomerById(int id);
      Product GetProductById(int id);
      AutomaticWeasel GetAutomaticWeaselById(int id);
      Transaction GetTransactioinById(int id);
}
public interface TransactionDao {
  Transaction[] GetAllCurrentlyOngoingTransactionsInitiatedByASweatyGuyNamedCarl();
}

このようなアーキテクチャの経験がある人はいますか? 全体的に、これらすべての小さなファイルを管理することだけが私の関心事であるため、セットアップに非常に満足しています. しかし、データアクセスレイヤーを構築するための他のアプローチが存在するかどうかはまだ疑問に思っています。

4

5 に答える 5

3

単純なシステム以外では単純なアプローチに反対することをお勧めします。通常は、集計ごとにカスタム リポジトリを作成し、その中にできるだけ多くの適切なロジックをカプセル化することをお勧めします。

したがって、私のアプローチでは、CustomerRepository など、それを必要とする各集計のリポジトリを用意することになります。これには Add (保存) メソッドがあり、その集計に適している場合は、Remove (削除) メソッドがあります。また、クエリ (GetActive) を含む適用される他のカスタム メソッドもあり、それらのクエリの一部は仕様を受け入れる可能性があります。

これは大変な作業のように聞こえますが、カスタム クエリ以外のほとんどのコードは、少なくとも最新の ORM を使用している場合は実装が非常に簡単なので、継承 (ReadWriteRepositoryBase where T: IAggregateRoot) および/または構成 (callingを RepositoryHelper クラスに追加します)。基本クラスには、GetById など、すべての場合に適用されるメソッドが含まれる場合があります。

お役に立てれば。

于 2008-10-25T16:46:10.827 に答える
2

私は PHP で作業していますが、データ アクセス レイヤーに同様の設定をしています。次のようなインターフェイスを実装しました。

interface DataAccessObject
{
public static function get(array $filters = array(), array $order = array(), array $limit = array());
public function insert();
public function update();   
public function delete();
}

そして、各データ アクセス オブジェクトは次のように機能します。

class DataAccessObject implements DataAccessObject
{
    public function __construct($dao_id = null) // So you can construct an empty object
    {
        // Some Code that get the values from the database and assigns them as properties
    }
    public static function get(array $filters = array(), array $order = array(), array $limit = array()) {};  // Code to implement function
    public function insert() {};  // Code to implement function
    public function update() {};  // Code to implement function 
    public function delete() {};  // Code to implement function        
}

現在、各データ アクセス オブジェクト クラスを手動で作成しているため、データベースにテーブルを追加したり、既存のテーブルを変更したりするときは、明らかに新しいコードを手動で作成する必要があります。私の場合、これは私たちのコード ベースがあった場所からの大きな前進です。

ただし、これらのデータ アクセス オブジェクトを生成するために、SQL メタデータを使用することもできます (外部キー制約などを利用するかなり健全なデータベース設計があると仮定します)。理論的には、単一の親 DataAccessObject クラスを使用して、クラスのプロパティとメソッドを構築し、データベース内の他のテーブルとの関係を自動的に構築することもできます。これは、多かれ少なかれ、説明しているのと同じことを達成します。これは、DataAccessObject クラスを拡張して、手動で構築されたコードがある程度必要な状況にカスタム メソッドとプロパティを提供できるためです。

.NET 開発の補足として、Subsonic など、データ アクセス層の基礎となる構造を処理するフレームワークを見たことがありますか? そうでない場合は、そのようなフレームワークを検討することをお勧めします: http://subsonicproject.com/ .

または、PHP 開発の場合、Zend Framework などのフレームワークが同様の機能を提供します: http://framework.zend.com

于 2008-09-27T21:41:17.097 に答える
2

ジョージ、あなたの気持ちはよくわかります。Billy のアーキテクチャは私には理にかなっていますが、コンテナー、Imapper、およびマッパー ファイルを作成する必要があるのは苦痛です。次に、NHibernate を使用している場合は、対応する .hbm ファイルと通常はいくつかの単体テスト スクリプトを使用して、すべてが機能していることを確認します。

NHibernate を使用していなくても、まだジェネリック基本クラスを使用してコンテナーをロード/保存していると思います。

public class BaseDAO<T> : IDAO<T> 
{
     public T Save(T entity)
     { 
       //etc......
     }
}
public class YourDAO : BaseDAO<YourEntity>
{
}

NHibernate がなければ、リフレクションやその他のメカニズムを使用して、どの SQL/SPROC を呼び出すかを決定していると思いますか?

いずれにせよ、これについての私の考えは、DAO が基本クラスで定義された基本的な CRUD 操作を実行するだけでよく、カスタム マッパーとインターフェイスを記述する必要はないということです。これを実現する唯一の方法は、Reflection.Emit を使用して DAO をその場で動的に作成することです。

于 2008-09-29T12:04:58.183 に答える
1

また、DAO にリポジトリ パターンを使用しており、非常に満足しています。はい、かなりの数の小さなクラスになってしまいますが、非常に保守が容易です。インターフェイス(LINQ)を使用すると、もう少し強力になります。かなり一貫したデータベース構造がある場合は、IQueriableジェネリック(のようなもの)を使用することもできます。T GetById<T>(int id)

于 2008-09-27T21:40:36.070 に答える
0

2 番目のアプローチの主な欠点は単体テストにあります。SimpleObjectRepository のような大きなファクトリ メソッドをモック化するには、ICustomerDao だけをモック化するよりも多くの作業が必要です。しかし、私のプロジェクトでは、関連性の高いオブジェクト (ほとんどが単体テストで使用される) に対する 2 番目のアプローチを採用しています。

あなたのシステムをより保守しやすく、理解しやすくし、それを実行しやすくしている理由を理解します。

于 2008-09-29T12:12:00.243 に答える