クラス重複パターン?


11

私は現在、現在のプロジェクトでソロ開発者として働いています。私は別の開発者からプロジェクトを引き継ぎました。これは、C#のモデルビューコントローラースタイルのWebアプリケーションです。オブジェクトリレーショナルマッピングにEntity Frameworkを使用します。また、ドメインモデルの型には、2つの異なるクラスセットがあります。1つのセットはORMとの対話に使用され、もう1つのセットはMVCシステムのモデルとして使用されます。たとえば、次の2つのクラスがあるとします。

public class Order{
    int ID{get;set;}
    String Customer{get;set;}
    DateTime DeliveryDate{get;set;}
    String Description{get;set;}
}

そして

public class OrderModel{
    String Customer{get;set;}
    DateTime DeliveryDate{get;set;}
    String Description{get;set;}
    public OrderModel( Order from){
        this.Customer= from.Customer;
        // copy all the properties over individually
    }
    public Order ToOrder(){
        Order result =new Order();
        result.Customer = this.Customer;
        // copy all the properties over individually
    }

}

このアプローチのいくつかの欠点(何かが変更された場合にコードを変更する場所が増える、メモリ内に存在するオブジェクトが増える、データのコピーに費やす時間が増える)を考えることができますが、ここでの利点はよくわかりません。モデルクラスの柔軟性が増したと思いますか?しかし、エンティティクラスもサブクラス化することで取得できます。私の傾向は、これら2つのクラスグループをマージするか、モデルクラスをエンティティクラスのサブクラスにすることです。ここで重要な何かが欠けていますか?これは私が知らない一般的なデザインパターンですか?私が考えているリファクタリングを行わない理由はありますか?

更新

ここでの回答のいくつかは、プロジェクトの最初の説明に重要な詳細が欠けていたことに気づかせています。プロジェクトには、ページモデルクラスという3つ目のクラスグループもあります。それらは、ページを支えるモデルとして実際に使用されているものです。また、UIに固有の情報も含まれており、注文とともにデータベースに保存されることはありません。ページモデルクラスの例は次のとおりです。

public class EditOrderPagelModel
{
    public OrderModel Order{get;set;}
    public DateTime EarliestDeliveryDate{get;set;}
    public DateTime LatestAllowedDeliveryDate{get;set;}
}

この3番目のグループの有用性はここではまったく異なると思いますが、他のものとマージする予定はありません(名前を変更する場合があります)。

モデルグループのクラスは現在、アプリケーションのAPIでも使用されています。これは、それが良いアイデアであるかどうかについての意見を聞くことにも興味があります。

また、ここで文字列として表されているお客様は例を単純化するためのものであり、実際にはシステムでそのように表されているためではありません。実際のシステムでは、独自のプロパティを持つドメインモデルの異なるタイプとして顧客がいます


1
「私はこのプロジェクトを他の開発者から引き継ぎました。開発者はその後、会社を辞めました」この方法から始まるストーリー専用のサイトがあります。

あなたのアップデートに関して:それは十分な利益のためにはあまりにも間接的なようです。
ロバートハーベイ

@RobertHarvey間接参照が多すぎるとは何ですか?
ロバートリケッツ

1
OrderModel。OrderViewModel(おそらくEditOrderPageModelと呼んでいるもの)で十分です。以下の私の答えを見てください。
ロバートハーヴェイ

@RobertHarveyこれは、私が実際に尋ねようとしていた質問に対する答えのように聞こえます
Robert Ricketts

回答:


16

ここで重要な何かが欠けていますか?

はい

これらは同じように見え、ドメイン内で同じものを表しますが、同じ(OOP)オブジェクトではありません。

1つは、Orderコードのデータストレージ部分で知られているものです。もう1つは、OrderUIで認識されているものです。これらのクラスが同じプロパティを持っているのは楽しい偶然の一致ですが、それらが保証されているわけではありませ

または、別の観点からそれを見るには、単一責任原則を検討してください。ここで重要な動機は、「クラスには変更する理由が1つある」ということです。特に、ORMやUIフレームワークなどの普及しているフレームワークを扱う場合、フレームワークを変更するとエンティティが変更されることが多いため、オブジェクトを分離する必要があります。

エンティティを両方のフレームワークに結び付けることにより、それをさらに悪化させています。


7

ビューモデルの目的は、ビューが必要とする形状でデータを提供することにより(モデルに依存せず)、(特にMVVMでは)ビューロジックの一部またはすべてをビューから戻すことにより、2つの方法で分離を提供することです。ビューモデルに。

完全に正規化されたモデルでは、Customerはモデルでは文字列ではなくIDで表されます。モデルは、顧客の名前が必要な場合、OrdersテーブルにあるCustomerIDを使用してCustomersテーブルから名前を検索します。

一方、ビューモデルNameは、IDではなく、顧客の方に関心がある可能性があります。お客様がモデルで更新されていない限り、IDは必要ありません。

さらに、ビューモデルは異なる形状をとることができます(通常、それは純粋なCRUDでない限り)。請求書ビューモデルオブジェクトには顧客名、住所、およびラインアイテムが含まれる場合がありますが、モデルには顧客と説明が含まれています。

つまり、請求書は通常表示と同じ方法では保存されません。


3

いくつかの点であなたは正しいです。どちらも同じと呼ばれる同じdomainobjectを参照していorderます。しかし、あなたはこれまでのところ間違っています。それは、異なる目的から生じた、異なる表現よりも実際の複製ではありません。注文を永続化したい場合は、たとえば、すべての列にアクセスする必要があります。しかし、それを外部に漏らしたくないのです。エンティティ全体をネットワーク経由でプッシュする以外に、本当に望んでいることではありません。MBのコレクションがordersKBで十分なクライアントに出荷されたケースを知っています。

長い話を短くするために、これがあなたがそれをしたい主な理由です:

1)カプセル化-アプリケーションの情報隠蔽

2)小規模モデルはシリアル化が高速で送信が簡単

3)は重複していますが、目的が異なります。したがって、異なるオブジェクトが存在する必要があります。

4)場合によっては、クエリごとに異なる値オブジェクトを使用することが理にかなっています。C#ではどうなるかわかりませんが、JavaではPOJOを使用して結果を収集できます。単一のものが必要な場合orderOrder -Entity を使用しますが、データの金額で満たされた列がいくつかだけ必要な場合は、小さいオブジェクトを使用するが効率的です。


エンティティフレームワークの構造、エンティティはプレーンな古いC#オブジェクトであるため、ネットワーク経由でエンティティを送信することはそれほど問題ではありません。状況によっては、注文のコンテンツの一部のみを送信できることの有用性がわかります。
ロバート・リケッツ

私が言ったように、1つまたは束は問題ではありません。ただし、MBのデータがあり、読み込み時間が遅くなる場合があります。モバイルの読み込み時間について考えてみましょう
Thomas Junk、

0

(免責事項:この方法で使用されているのを見ただけです。実際の使用目的を誤解している可能性があります。この回答は疑いを持って扱ってください。)

もう1つの不足しているビットは、Orderとの間の変換OrderModelです。

Order一方、クラスは、あなたのORMに結びついているOrderModel、あなたのビューモデルの設計に結びついています。

通常、この2つの方法は「魔法の方法」で提供されます(DI、IoC、MVVMなどと呼ばれることもあります)。つまり、これらの2つの変換メソッドをの一部として実装する代わりに、これらの変換方法はOrderModel、これらの相互変換専用のクラスに属します。そのクラスはフレームワークになんらかの方法で登録されるため、フレームワークで簡単に検索できます。

public class OrderModel {
    ...
    public OrderModel(Order from) { ... }
    public Order ToOrder() { ... }
}

これを行う理由は、からOrderModelへ、Orderまたはその逆への交差があるときは常に、一部のデータがORMからロードまたはORMに保存されている必要があることを知っているためです。


私は両方の周りを保管しております場合、私は間違いなく変換がより自動化することが持っているそれらを設定したい
ロバート・リケッツ

@RobertRicketts私が見たものは次のようになります:IMvxValueConverter。その目的を誤解したかもしれませんが。
rwong
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.