11

リッチ ドメイン モデルを使用する利点を示す簡単な例を探しています。理想的には、前後のコード リストが必要です (できるだけ短くする必要があります)。

前のコード リストは貧弱なドメイン モデルと多くのかなり手続き型のサービス層コードを使用して解決された問題を示し、後のコード リストは豊富なオブジェクト指向ドメイン モデルを使用して解決された同じ問題を示す必要があります。

理想的には、コード リストは Java または Groovy である必要がありますが、かなり似たもの (C# など) であれば何でもかまいません。

4

3 に答える 3

3

実際の製品コードの簡単な例を示します。

Person.groovy:

  List addToGroup(Group group) {
    Membership.link(this, group)
    return groups()
  }

メンバーシップ.groovy:

 static Membership link(person, group) {
    def m = Membership.findByPersonAndGroup(person, group)
    if (!m) {
        m = new Membership()
        person?.addToMemberships(m)
        group?.addToMemberships(m)
        m.save()
    }
    return m
}

人をグループにバインドしたいときはいつでも、person.addToGroup(group)を実行できます

手続き型コードは、コントローラーで次のようになります。

def m = Membership.findByPersonAndGroup(person, group)
 if (!m) {
        m = new Membership()
        person?.addToMemberships(m)
        group?.addToMemberships(m)
        m.save()
}

一見すると、それを関数にラップすることができ、準備ができていると言えます。しかし、私見によるリッチ ドメイン デザインの利点は、それがあなたの考え方に近く、したがって合理化に近いことです。この特定の例では、人をグループに追加したいだけで、コードはそれを読み取ります。

これはあなたが尋ねたような短い例ですが、この例を拡張して、適切なドメイン モデリングを使用して複雑な相互作用を構築できることを確認するのは簡単です。

これら 2 つのパターンの簡単な説明については、 Martin Fowler のTransaction Script vs Domain Modelを参照してください。これは DDD に関連していると考えられます。

于 2009-11-17T09:59:16.490 に答える
2

そのような比較をした人は誰もいないと思います。ドメイン駆動設計は複雑さを解決しようとしますが、単純な例には複雑さが含まれていません。

おそらく、ドメイン駆動設計のステップバイステップでいくつかの答えが得られます。

于 2009-11-02T22:30:17.720 に答える
-5

これはあなたの質問に正確に答えるものではありませんが、ドメイン駆動設計の反対はデータベース駆動設計だと思います。データベース駆動型設計では、最初にデータベーススキーマが作成され、次にスキーマがどのように見えるかを完全に理解した上でクラスが作成されます。利点は、「内部で」何が起こっているのかをよりよく理解し、インピーダンスの不一致の影響を最小限に抑えることです。ただし、欠点は、データベーススキーマがオブジェクト指向ではなくリレーショナルであるため、オブジェクトにあまり変換されないことです(たとえば、リレーショナルデータベースにはコレクションの概念がありません)。

ドメイン駆動設計では、理論的には、他のクラスと同じようにデータオブジェクトを作成し、データベースを単なる永続層として扱います。レイマンの用語では、データベースは単なるストレージコンテナであり、オブジェクトがどのように格納されるかは気にせず、何らかの方法で格納されるだけです。これにより、インピーダンスの不整合がなくなり、心配することが1つ少なくなります。ただし、実際には、オブジェクトがどのように格納されるかを認識しておく必要があり、使用しているORMが複雑なSQLクエリを吐き出そうとするとパフォーマンスの問題が発生する可能性があります。

編集:

原則として、ドメイン駆動設計がどのようなものであるかの例を次に示します。(C#で)次のようなPersonクラスがあるとします。

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Address Address { get; set; }
    public ICollection<Person> Relatives { get; set; }
    public Company Employer { get; set; }
}

さて、リレーショナルデータベースでは、これはおそらく3つのテーブル、Personテーブル、Addressテーブル、Companyテーブルに変換され、それらの間には多数の関係があります。ただし、これは、プログラマーがこのオブジェクトを見る方法とは大きく異なります。プログラマーは、これを4つのパラメーターを持つPersonオブジェクトのインスタンスと見なします。そのうちの1つはICollectionです。これはデータベーステーブルの構造とあまり一致しないため、「インピーダンスの不一致」、つまりレイメンの用語では、リレーショナルモデルとオブジェクトモデルのレイアウトの違いがあります。

ドメイン駆動設計では、これを実行できるはずです。

Person person = new Person();
// set each property to something
Database.Save(person);

これで、personオブジェクトが保存されます。私はそれを次のように取得できます:

Person databasePerson = Database.Get<Person>(idOfPerson);

そして、Person保存する前と同じように、オブジェクトが返されます。このように、データベースがどのようにデータを保存しているか、またはインピーダンスの不一致について心配する必要はありません。保存して、必要に応じて取得します。

しかし、これはすべて理論上です。実際には、おそらく手動で「マッピング」を指定する必要があります。つまり、データを取得するデータベース内のテーブル/列をクラスがどのように認識するかを指定する必要があります。ディクショナリやその他のADTなどのより複雑なタイプにマップしようとしている場合や、複数のテーブルから1つのクラスにデータをプルしようとしている場合は、かなり複雑になる可能性があります。

于 2009-11-02T22:12:21.283 に答える