2011-09-13 6 views
20

ドメインオブジェクトの代わりにビューモデルでDTOを使用したいと思いますが、各ドメインオブジェクトに対して2セットのプロパティを維持する必要があるためメンテナンスオーバーヘッドを正当化するのは苦労しています。ドメインオブジェクトのプロパティを複製することなくDTOを使用するためのパターンはありますか?

ドメインオブジェクトのプロパティがオブジェクトのアクションから分離され、2つのプロパティセットを維持する必要がないパターンを実装しているか知っている人はいませんか?

public class Person{ 
    private String firstName; 
    private String lastName; 

    public String getFirstName(){ 
     return this.firstName; 
    } 

    public String setFirstName(string firstName){ 
     this.firstName = firstName; 
    } 

    ... 
} 

public class PersonActions extends Person{ 
    public void save(){ 
     ... 
    } 

    public Person get(){ 

    } 
} 

私はPersonAction周りを通過する必要があると思いますので、この方法では、まだ少しクルージ的な感じ:

一つは、私は私のドメインオブジェクトは、プロパティだけこと持っていることや、サブクラスなどのアクションを付けるだろうと思っていましたもし私がドメインオブジェクトの完全な表現を望むなら、クラス。

+0

ORMや他のデータベース抽象化ツール、特にソースコード生成をサポートするものを使用していますか? –

+0

DAOやアクティブなレコードパターンについて聞いたことがありますか? – maks

+0

あなたのドメインが貧血でないならば、定期的にサブクラス化することはお勧めできません。それは、リッチドメインオブジェクトであり、DTOはよりフラットで、より多くのプレゼンテーション指向になるので、それらの構造と動作が異なる必要があります。マッピングレイヤーを持つ2つの別々のモデルを維持してください。 –

答えて

2

ドメインメソッドを使用せずに、オブジェクトのデータだけを公開するインターフェイスを使用できます。あなたはまだ2つのクラスを維持する必要がありますが、ほとんどの変更がIDE(例:Eclipse)によってリファクタリングされる可能性があるため、ずっと簡単です。ここに例があります:

public interface PersonView { 
    String getFirstName(); 
    String setFirstName(); 
} 

public void Person implements PersonView { 
    private String firstName; 

    @Override // This annotation guarantees the interface is correct 
    public String getFirstName() { 
     return firstName; 
    } 

    ...domain methods... 
} 

完全な解決策ではありませんが、きれいです。

問題自体については、私は1つのためにオブジェクト全体をビューレイヤーに公開しても構いません。 IMHO、私はいくつかの方法を隠すことはオーバーヘッドの価値があるとは思わない。チームはオブジェクトを賢明に使用するための規律を持っているべきですが、それは私の意見です。

+0

私はこのアプローチの表現力が好きです。実際の作業コードで実際にどのように動作するかを実際に試してみる必要があります。正直言って私は豊富なオブジェクトを公開するという問題はほとんどありませんでしたが、十分に豊富なドメインオブジェクトをjsonに変換しようとすると最大の問題が発生しました。 – bittersweetryan

0

1つのアプローチは、あなたのDTOオブジェクトであるビューモデルにプロパティを持たせることです。

もう1つの方法は、プロパティを複製することですが、オブジェクト間のマッピングにAutoMapperと同様の方法を使用します。

最新のプロジェクトではDTOオブジェクトをプロパティとして持っていますが、DTOオブジェクトのプロパティを参照するビューモデルの個々のプロパティも公開しています。

+0

Shiraz、これらの手法を実際に表示する答えに追加できるコードスニペットはありますか? – bittersweetryan

1

ちょうどあなたのモデルあなたのコントローラの(Person)プロパティ(PersonActions)作る:

あなたの質問の履歴に基づいて
public class PersonActions { 

    private Person person; 

    public PersonActions() { 
     person = new Person(); // Or get existing one from DAO in case of edit. 
    } 

    public void save() { 
     somePersonDAO.save(person); 
    } 

    public Person getPerson() { 
     return person; 
    } 

} 

私はあなたがStrutsのを使用していることを理解しています。その場合には、それは、JSP ELは、ネストされたオブジェクトのプロパティをサポートしていることを知っている値を取得するには、このような何か良いことだ:

${personActions.person.firstName} 
${personActions.person.lastName} 

コントローラのプロパティを複製することによって、それらを平らにする必要はありません。ここで

+0

私はあなたがこれで行くところ、そして確かに私が取ることができるアプローチを見ています。このアプローチの唯一のことは、私が個人的にコントローラにあまりにも多くの制御を与えると感じていることです。それは間違いなく私の質問で指摘したようなことをすることの不利な点を強調しています。 – bittersweetryan

+0

あまりにも多くの制御?私はそこにあなたのために "コントローラ"という言葉にいくつかのあいまいさがあると思う:)他の答えは本質的にそれを不可能にするコントローラとモデルをタイトカップル。 – BalusC

+0

"コントローラ"はMVCのコンテキストで話しています。私にとって、MVCコントローラは、サービスレイヤからの呼び出しメソッドを調整して、「作業ユニット」を完成させるだけですみます。通常、私は両方のアクションクラスと人のクラス(IEのリッチドメイン)を組み合わせるので、私は密接にそのプロパティとドメインオブジェクトのアクションを結合する気にしない1人のクラスを持っていただろう。 – bittersweetryan

2

は別のアイデアです:

は、ドメインオブジェクトを使用してのみ、あなたが露出するメソッドに注釈を付けます。あなたは両方の長所を取得し、このアプローチを使用することにより

@Entity // hibernate 
@XmlAccessorType(XmlAccessType.NONE) // for DTO 
@XmlRootElement 
public class Survey { 
    @Column(name = "Title") // hibernate 
    @Basic // hibernate 
    @XmlElement // for use as DTO 
    private String title; 

    @XmlElement(name = "report") 
    public SurveyReport getSurveyReport() { 
      // ... do some stuff here 
    } 
} 

を:彼らはNONEとしてアクセスタイプを修飾することで、明示的な博覧会を必要とするので、あなたは偶発的なデータのエクスポージャーを持っていない道

例それを作ることができます。さらに、メソッドで 'メタ'情報を公開し、メソッドに注釈を付けることができます(XmlAccessType.NONEのために利用可能です)。

私が見るの最大の欠点:ビュー消費のために素晴らしいことがあり、多くの方法

  • とコード

  • モノリシックオブジェクトを維持することが困難になる

    1. は、注釈の爆発ではなく、内部コードに本当に適している

    2. APIの混乱につながる
    3. 複数のドメインオブジェクトからの情報を組み合わせることなく、あなたがしたいビューを表すことができない場合があり、一日の終わりには#1
  • を参照してください。とにかく明示的なDTOが必要な状態に戻ってしまう

  • 関連する問題