4

ほとんどの大規模プロジェクトに共通する側面の1つは、多くのドメインエンティティで共通の追跡データが必要なことです。たとえば、ほとんどの大規模なプロジェクトでは、多くのドメインエンティティの次のプロパティを追跡します。

DateTime DateCreated
User CreatedBy
DateTime LastModified
User LastModifiedBy

このデータは非常に自明であり、ドメインオブジェクトに対して誰がいつ何をしたかを追跡するために使用されます。

問題は、大規模なアプリケーションのドメインモデルを設計するときに、この追跡データを処理するための最良の方法は何かということです。

古典的な方法は、基本クラスを使用してから、関連するドメインクラスにその基本クラスから継承させることです。しかし、これは継承警報ベルよりも私の好意的な構成を引き立たせます。私が取り組んできたプロジェクトが多ければ多いほど、手に負えない相続を拒否するようになりますが、それが最良の選択肢であるという状況があるわけではありません。たとえば、この場合などです。別の継承ソリューションはインターフェイスを使用することですが、このソリューションはあまり結合されていませんが、ドメインエンティティでこのアプローチを使用した例はあまりありません。

2番目の方法は、コンポジションを使用して、ある種の追跡オブジェクトを各ドメインエンティティに追加することです。これに関する唯一の問題は、これらを別個のテーブルとして表さないようにデータ層に具体的に指示する必要があることです。マイナーなタスクですが、見返りがない場合は正当化するのが難しいタスクです。

追跡データを処理する最後の方法は、これを透過的に実行するようにデータレイヤーを構成することです。Entity-Frameworkを使用してこれを行うことはおそらく可能だと思いますが、過去にこのソリューションを実装したことがない場合、これは最も先行する時間のかかるソリューションになります。この解決策が問題に値するかどうかを予測することは困難です。

この質問は客観的に見えるかもしれませんが、これは実際には、ほとんどの大規模プロジェクトが何らかの方法で対処しなければならない一般的なタスクです。

メタデータを追跡するためのドメインモデルや大規模なプロジェクトを設計するための最良の方法は何ですか?

4

2 に答える 2

2

ベストプラクティスは主観的なものであることが多く、解決するのと同じくらい多くの問題を引き起こす可能性があります。いつ継承する必要がありますか?いつ作曲すべきですか?学者たちは、問題の細部をめぐって論争することに何年も費やします。シンプルなインターフェースによる基本的な継承は実用的で効果的です。それがすべてのエンティティの標準機能である場合は、継承がおそらくより良いオプションです。

監査プロパティを持つ基本クラスがあり、これらのプロパティのインターフェイスを実装しました。次のコードを使用して、への呼び出しをインターセプトしcontext.SaveChanges()ます。シンプルで機能します。追跡対象のエンティティがインターフェイスを実装していない場合、失敗するように拡張される可能性がありIAuditます。

    public override int SaveChanges()
    {
        var entities = this.GetChangedAuditDataEntities();

        foreach (var entity in entities)
        {
            this.SetModificationInfo(entity);
        }

        return base.SaveChanges();
    }

    private IEnumerable<IAuditData> GetChangedAuditDataEntities()
    {
        return (
            from entry in _context.ChangeTracker.Entries()
            where entry.State != EntityState.Unchanged
            select entry.Entity)
            .OfType<IAuditData>();
    }

    private void SetModificationInfo(IAuditData entity)
    {
        entity.lastModifiedBy = _currentUser.Name;
        entity.lastModified = System.DateTime.Now;
    }

これは、自動的に「正しい」答えが得られない質問の1つです。Jon Skeetがそれに答えるとしたら、それはベストプラクティスと見なされます。他の唯一の正解は、あなたの特定の偏見を確認するか、少なくとも正しい知的メモを打つ必要があります。

数年前、継承は蔓延しており、これからの多くの反発の1つは、「継承に対する価値構成」のマントラでした。結構ですが、継承にはその場所があります。

ドメインオブジェクト(「ドメインオブジェクト」という言葉は共通のレイヤーを意味します)など、同じタイプのオブジェクトの多くを含むアーキテクチャレイヤーは、共通の基本クラスを持つことで大幅に強化できることをお勧めします。System.Objectその良い例です。別の例を挙げましょう。ソリューションの例外デコレータを定義するときに、ToString()メソッドを拡張して、オブジェクトを一意に識別する値を作成することにしました。

public override string ToString()
{
    if (this is IAuditData)
    {
        IAuditDataidentifiable = this as IAuditData;
        return string.Format(@"{0} {{ id: {1}, ETag: {2} }}",
            identifiable.GetType().Name,
            identifiable.id,
            identifiable.ETag);
    }
    else return base.ToString();
}

7行のコード-実用的でシンプルかつ効果的。あなたの質問から、あなたは多くの焦げた指から生まれなければならない継承に完全に反対しているように聞こえます。私も;-)ですが、この場合はそれがより良いオプションであると私はまだ主張しています。

于 2013-02-22T14:51:48.717 に答える
0

qujckが彼の回答とコメントで言ったことは好きですが、追跡情報がインフラストラクチャの概念を表す場合は、監査やロギングなどを担当するインフラストラクチャレイヤーに配置します。それ以外の場合は、何かを追加します。それらはドメインの概念であり、ドメインモデルレイヤーに属していれば、私は本当に維持したいと思っています。この場合、複雑なオブジェクト(値オブジェクト)を使用してそれらを表現し、作成するたびに手動で設定する負担を軽減します。追跡対象オブジェクト追跡対象オブジェクトが要求されるたびにファクトリまたはIoCコンテナによって呼び出されるメソッドを定義します。私のポイントは、変更を一元化し、それらが属する概念を維持することです。

于 2013-02-24T00:31:45.930 に答える