5

私は自分のレイヤーを可能な限り分離したいシステムに取り組んでいます.システムの残りの部分を大幅に変更することなく、データベースなどを切り替えることができるある種のモジュラーアプリケーション.

それで、私は x 間、Robert C. Martin のグッド プラクティス、クリーンなコード、デカップリング アーキテクチャなどについての講演の 1 つを見て、インスピレーションを得ました。私がちょっと変だと思うのは、彼のシステムの説明と、 s のFitnesseストア/ロード メソッドの実装方法ですWikiPage。ビデオもリンクしています: Robert C. Martin - Clean Architecture and Design

彼が説明しているのは (少なくとも私の理解では)、エンティティは永続層から自身を格納およびロードする方法を認識しているということです。ウィキページをメモリ内に保存したいとき、彼は単純にウィキページをオーバーライドして、新しい を作成しましたInMemoryWikiPage。それらをデータベースに保存したいとき、彼は同じことをしました...

私の質問の 1 つは、このアプローチを何と呼ぶか​​ということです。私はリポジトリのパターンなどについてずっと学んできましたが、なぜこのような永続性を無視するようなクラスであるべきなのか、彼がしたことに関する資料を見つけることができないようです. 私のアプリケーションはモジュールで構成されているため、エンティティの集中ストアを作成する必要なく、これが問題を解決するのに役立つと思います...すべてのモジュールは、そのエンティティの永続性を含め、単にそれ自体を処理します。

コードは次のようになると思います。

public class Person : IEntity
{
   public int ID { get;set; }
   public string Name { get;set; }

   public void Save()
   {
       ..
   }

   public void Update()
   {
   }

   public void Delete()
   {
   }

   ...
}

少し変な感じですが... それとも、彼がビデオで言ったことを誤解したのでしょうか?

2 番目の質問は、このアプローチに同意しない場合、そのようなモジュラー アプリケーションでどのような道をたどるかと​​いうことです。

可能であれば、いくつかの説明とともに例を提供してください。

4

2 に答える 2

4

2 番目の質問にお答えします。にも興味があると思いますDependency Injection

私はDIの専門家ではありませんが、できる限り明確に説明しようとします.

まず、ウィキペディアから:

依存関係の挿入は、ハードコードされた依存関係を削除し、実行時またはコンパイル時に変更できるようにするソフトウェア設計パターンです。

依存関係注入パターンの主な目的は、コンパイル時ではなく、実行時または構成ファイルを介して、特定の依存関係インターフェイスの複数の実装から選択できるようにすることです。

AutoFac、SimpleInjector、Ninject、Spring .NET など、この設計パターンを実装するのに役立つ多くのライブラリがあります。

理論的には、コードは次のようになります (AutoFac の例)

var containerBuilder = new ContainerBuilder();
//This is your container builder. It will be used to register interfaces
// with concrete implementations

次に、インターフェース型の具象実装を登録します。

containerBuilder.RegisterType<MockDatabase>().As<IDatabase>().InstancePerDependency();
containerBuilder.RegisterType<Person>().As<IPerson>().InstancePerDependency();

この場合、InstancePerDependencyは、 を解決しようとするたびIPersonに、新しいインスタンスを取得することを意味します。たとえばSingleInstance、 を解決しようとするとIPerson、同じ共有インスタンスが取得されます。

次に、コンテナを構築して使用します。

 var container = containerBuilder.Build();
 
 IPerson myPerson = container.Resolve<IPerson>(); //This will retrieve the object based on whatever implementation you registered for IPerson
 myPerson.Id = 1;

 myPerson.Save(); //Save your changes

この例で使用したモデル:

interface IEntity
{            
    int Id { get; set; }            
    string TableName { get; }
    //etc
}

interface IPerson: IEntity
{
    void Save();
}

interface IDatabase
{
    void Save(IEntity entity);
}

class SQLDatabase : IDatabase
{
    public void Save(IEntity entity)
    {
        //Your sql execution (very simplified)
        //yada yada INSERT INTO entity.TableName VALUES (entity.Id)
        //If you use EntityFramework it will be even easier
    }
}

class MockDatabase : IDatabase
{
    public void Save(IEntity entity)
    {
        return;
    }
}

class Person : IPerson
{
    IDatabase _database;

    public Person(IDatabase database)
    {
        this._database = database;
    }

    public void Save()
    {
        _database.Save(this);
    }

    public int Id
    {
        get;
        set;
    }

    public string TableName
    {
        get { return "Person"; }
    }
}

心配する必要はありません。AutoFac はPersonなどの依存関係を自動的に解決しIDatabaseます。

このように、データベースを切り替えたい場合は、次のように簡単に実行できます。

containerBuilder.RegisterType<SqlDatabase>().As<IDatabase>().InstancePerDependency();

詳細については、キックスタートとして機能する単純化された(使用に適していない)コードを作成しました。Googleの「依存性注入」を参照してください。これが役立つことを願っています。幸運を。

于 2013-04-12T12:08:35.867 に答える
3

投稿したパターンはActive Recordです。

リポジトリとアクティブ レコード パターンの違いは、アクティブ レコード パターンでは、データのクエリと永続性、およびドメイン オブジェクトが 1 つのクラスにあることです。一方、リポジトリと同様に、データの永続性とクエリはドメイン オブジェクト自体から分離されています。

調べる必要がある別のパターンはクエリ オブジェクトです。これは、可能なすべてのクエリ (フィルター、並べ替え、グループ化など) でメソッドの数が増加するリポジトリ パターンとは異なり、クエリ オブジェクトは流暢なインターフェイスを使用して表現力を高めることができます[1 ]または専用のパラメータ[2]を渡すことができます

最後に、コマンド クエリの責任分離アーキテクチャを見てアイデアを得ることができます。私は個人的にそれを大まかにたどり、私を助けることができるアイデアを拾い上げました。

お役に立てれば。

コメントに基づいて更新

リポジトリ パターンの 1 つのバリエーションはこれです

UserRepository
{
    IEnumerable<User> GetAllUsers()
    IEnumerable<User> GetAllByStatus(Status status)
    User GetUserById(int id)
    ...
}

これは、リクエストされる追加のクエリに対してリポジトリが更新されるため、スケーリングされません。

もう 1 つのバリエーションは、クエリ オブジェクトをパラメーターとしてデータ クエリに渡すことです。

UserRepository
{
    IEnumerable<User> GetAll(QueryObject)
    User GetUserById(int id)
    ...
}


var query = new UserQueryObject(status: Status.Single)
var singleUsers = userRepo.GetAll(query)

.Net の世界では、QueryObject の代わりに Linq 式が渡されることがあります

var singleUsers = userRepo.GetAll(user => user.Status == Status.Single)

もう 1 つのバリエーションは、CQRS と同様に、クエリ オブジェクトを使用してデータの取得を送信しながら、一意の識別子によって 1 つのエンティティの取得専用のリポジトリを作成して保存することです。

更新 2

SOLIDの原則に慣れることをお勧めします。これらの原則は、疎結合で凝集性の高いアーキテクチャを作成する際に非常に役立ちます。

SOLID pricples に関する Los Techies の編集には、SOLID pricplesに関する優れた紹介記事が含まれています。

于 2013-04-12T11:12:34.717 に答える