2

私は大規模なプロジェクトに取り組んでおり、その一部は既存のサーバー スタックを置き換えるものです。非常に正規化された大規模なデータベースでは、多くの複合オブジェクトを構築する必要があることは明らかでした。私のクエリの例は次のとおりです: 私の複合オブジェクト定義:

[DataContract]
public class CompositeEvent
{
    Guid eventIdentity;
    string accountIdentity;
    string eventMessage;
    DateTime eventLoggedOn;
    string methodName;
    string programName;
    string userIdentity;
    List<CompositeException> exceptions = new List<CompositeException>( );
    List<CompositeParameter> methodParameters = new List<CompositeParameter>( );
    List<CompositeParameter> databaseParameters = new List<CompositeParameter>( );

    [DataMember]
    public Guid EventIdentity
    {
        get { return eventIdentity; }
        set { eventIdentity = value; }
    }
    [DataMember]
    public string AccountIdentity
    {
        get { return accountIdentity; }
        set { accountIdentity = value; }
    }
    [DataMember]
    public string EventMessage
    {
        get { return eventMessage; }
        set { eventMessage = value; }
    }

    [DataMember]
    public DateTime EventLoggedOn
    {
        get { return eventLoggedOn; }
        set { eventLoggedOn = value; }
    }

    [DataMember]
    public string MethodName
    {
        get { return methodName; }
        set { methodName = value; }
    }

    [DataMember]
    public string ProgramName
    {
        get { return programName; }
        set { programName = value; }
    }

    [DataMember]
    public string UserIdentity
    {
        get { return userIdentity; }
        set { userIdentity = value; }
    }

    public string QualifiedCreator
    {
        get 
        {
            if ( String.IsNullOrEmpty( programName ) && String.IsNullOrEmpty( methodName ) )
                return string.Empty;
            return string.Format( "{0}:{1}", String.IsNullOrEmpty( ProgramName ) ? "{undefined}" : ProgramName, String.IsNullOrEmpty( MethodName ) ? "{undefined}" : MethodName );
        }
    }
    [DataMember]
    public int EventTypeIdentity { get; set; }

    [DataMember]
    public string EventTypeName { get; set; }

    [DataMember]
    public List<CompositeException> Exceptions
    {
        get { return exceptions; }
        set { exceptions = value; }
    }

    [DataMember]
    public List<CompositeParameter> MethodParameters
    {
        get { return methodParameters; }
        set { methodParameters = value; }
    }

    [DataMember]
    public List<CompositeParameter> DatabaseParameters
    {
        get { return databaseParameters; }
        set { databaseParameters = value; }
    }
}

そして、私のサービスでの私のデータベースクエリ:

            using ( Framework.Data.FrameworkDataEntities context = new Data.FrameworkDataEntities( ) )
        {
            var list = from item in context.EventLogs
                       join typeName in context.EventLogTypes on item.EventTypeId equals typeName.Id
                       orderby item.EventLoggedOn, item.EventLogType
                       select new CompositeEvent
                       {
                           AccountIdentity = item.AccountIdentity,
                           EventIdentity = item.Id,
                           EventLoggedOn = item.EventLoggedOn,
                           EventMessage = item.EventMessage,
                           EventTypeIdentity = item.EventTypeId,
                           EventTypeName = typeName.EventTypeName,
                           MethodName = item.MethodName,
                           ProgramName = item.ProgramName,
                           UserIdentity = item.UserIdentity
                       };
            return new List<CompositeEvent>( list );
        }

これで、私の複合オブジェクトの定義から、それにはデータのみが含まれ、ビジネス ルールは含まれず、ビジネス構造、データ構造、またはその他の永続性や公開は含まれていないことが明らかです。

しかし、私のチーム メイトは、これはドメイン モデルにしか存在できず、この明確に定義されたオブジェクトから DTO にデータを移動するサイクルを費やす必要があると述べています。それだけでなく、a) すべての DTO の名前に DTO が含まれている必要があり、b) ネットワークを介して移動する目的でのみ存在する必要があります。したがって、クライアント コードを開発するときは、a) 各オブジェクト プロパティのプロパティを作成し、b) DTO からビュー モデル プロパティに移動する必要があります。

これはDTOを極限まで進めていると感じます。これは、これらがデータ転送オブジェクトである複合オブジェクトの定義に基づいています。また、このオブジェクトをクライアントに保存し、クライアントでこのオブジェクトに直接バインディングを行うことにまったく問題はありません。私がしているのは、複合オブジェクトで定義されたすべてのプロパティを取得してDTOにコピーすることだけなので、オブジェクトを作成して別のオブジェクトにコピーしてからもう一度内部にコピーするのは、時間とサイクルの膨大な無駄のようですクライアントのプロパティ。

これに関する他の意見に興味があります。私は、関心の分離や単一責任の原則などの OOP ルールに違反していないと感じています...少なくとも、これらについて極端に肛門にならない限り. ご意見????

4

1 に答える 1

2

さて、MUSTあなたの同僚が強調したすべてのことは、彼を少しOCDのように見せます。しかし、彼にはポイントがあるので、それは問題ありません。

特にMVCのDTOは、基になるデータモデルを抽象化するように設計する必要があります。これにより、DTOがビューの実際のモデルになります。それらをオブジェクトの近くに保持すると、実際に変更する必要があるのは一方だけである可能性がある場合にのみ、両方のオブジェクトのセットを変更することになります。

SoAまたはN層アーキテクチャーでDTOを設計する際に考慮すべきもう一つのことは、ビューレイヤーと基盤となるサービスおよびモデルとの間にコントラクトを作成してはならないということです。したがって、データベースで何かが変更された場合(フィールド、テーブル、ビューなど)、DTOが影響を受けないように、サービスレイヤーからすべてを下に調整できる必要があります。

ビューモデルは、少なくとも機能を追加または削除しない限り、同じままである必要があります。根本的な変更はすべてDTOに適合させる必要があります(回避策ではありませんが、常に可能であるとは限りません)。

ここで、プロジェクトをSoAおよびDTOからプレーンな2層アーキテクチャに切り替えていることに言及する必要があります(これは、DTOではなくパフォーマンスの問題が原因でした:))。内部でのみ使用するように設計された、単純なオブジェクトと複雑なオブジェクトの両方の横断的なドメインレイヤーがあります。WSコンシューマーを殺したくないので、公開されたAPIoverWebサービスは実際にDTOを使用します。多分彼らを少し傷つけます:)。

ただし、前述のように、DTOを使用する必要があります。それはあなたの状況で役立ちます(MVCで)。DTOへのマッピングを簡単にするため、およびその逆の場合は、をお勧めしAutoMapperます。あなたの人生をずっと楽にしてくれます(そしてあなたの同僚は幸せになります)。

于 2012-07-05T19:50:17.293 に答える