13

これは長い質問なので、すぐに要点に行きます。これは、問題をよりよく説明するための疑似コードです。

DB構造

ユーザー (ユーザー ID、名前、姓)

Address(AddressID, UserID, Street, City, State, ZipCode) =>多対1のユーザー関係

電話 (PhoneID、UserID、Number、IsPrimary) => 多対 1 のユーザー関係

ドメイン クラス

class User:IEntity
{
public string Name {get;set;}
public string LastName {get;set;}
public ContactInfo{get;set;}
}

class Phone: IValueObject or IEntity? will see later.
{
public int id; // persistence ID, not domain ID
public string Number {get;set;}
}

class Address: IValueObject or IEntity? will see later.
{
public string Line1 {get;set;}
public string City {get;set;}
public string State {get;set;}
public string ZipCode {get;set;}
}

class ContactInfo: IValueObject or IEntity? will see later.
{
List<Address> Addresses {get;set;}
List<Phone> PhoneNumbers {get;set;}
}

ここまでで、このドメインとそのモデルの非常に基本的な表現ができました。

私の質問は次のとおりです。最初に入力されたときにスペルミスがあったため、アドレスの1つを更新するか、番号の1つの市外局番を修正したいとしましょう.

DDD に関する Evan のバイブルに従えば、値オブジェクトは不変でなければなりません。つまり、作成後にプロパティやフィールドを変更する必要はありません。その場合、電話番号の文字列の一部が間違っているという理由だけで ContactInfo クラス全体を再作成することはできないため、私のクラスはどれも ValueObject ではないと思います。それで、それは私のすべてのクラスをエンティティにすると思いますか?

このクラスはデータベースに格納されているため、各クラスに「永続性 ID」があることに注意してください。

コンストラクターで簡単に再作成できるため、Phone を値オブジェクトにすることにしたとします。

public Phone(string newNumber)

それで、それは User (agg root) AND contactinfo にメソッドを追加するようなものでしょうか? (デメテル法)

お気に入り...

User....
public void UpdatePrimaryPhoneNumber(string number)
{
this.ContactInfo.UpdatePrimaryPhoneNumber(number);
}

ContactInfo....
public void UpdatePrimaryPhoneNumber(string number)
{
var oldPhone = Phones.Where(p=>p.IsPrimary).Single();
var newPhone = new Phone(number, oldPhone.persistenceid???-> this is not part of the domain)
oldPhone = newPhone;
}

しかし、私はまだ永続化IDに対処する必要があります... grrrrr。なんて頭が痛い。

それらのブログを読んでいると、オブジェクトを重視するほとんどの「ddd エキスパート」が乱用されている、または誤用されていると感じることがあります。

このシナリオの最善の解決策は何ですか? ありがとうございました

4

3 に答える 3

11

DDDに関するEvanの聖書に従う場合、値オブジェクトは不変である必要があります。つまり、作成後にプロパティやフィールドに変更はありません。その場合、電話番号の文字列の一部が間違っているという理由だけでContactInfoクラス全体を再作成することはできないため、私のクラスはどれもValueObjectではないと思います。だから、それは私のすべてのクラスをエンティティにするのだと思いますか?

VO自体は不変である可能性がありますが、VOはそれ自体では存在せず、常に集合体の一部です。したがって、VOは不変である可能性がありますが、そのVOを参照するオブジェクトは不変である必要はありません。VOを理解するのに役立ったのは、それらをプリミティブなInt32値のようなものと比較することです。個々の整数の値は不変です。5は常に5です。ただし、Int32がある場合は、そこに別の値を設定できます。

ドメインの場合、これは、不変のアドレスVOを持つことができますが、特定の使用エンティティはアドレスVOの任意のインスタンスを参照できることを意味します。これにより、修正やその他の変更を行うことができます。アドレスVOの個々のフィールドを変更するのではなく、まったく新しいVOインスタンスに置き換えます。

次に、「永続性ID」はドメインコードのどこにも表現されるべきではありません。それらはリレーショナルデータベースのニーズを満たすためだけに存在し、NoSQLデータベースはそれらをまったく必要としません。

主な電話のシナリオは、次のようになります。

public void UpdatePrimaryPhoneNumber(string number)
{
  var existingPrimaryNumber = this.Phones.FirstOrDefault(x => x.IsPrimary == true);
  if (existingPrimaryNumber != null)
      this.Phones.Remove(existingPrimaryNumber);
  this.Phones.Add(new Phone(phoneNumber: number, isPrimary = true));
}

この方法は、既存の主要電話番号を更新するという考えをカプセル化します。電話番号VOが不変であるという事実は、既存の値を削除して新しい値に置き換える必要があることを意味します。特にNHibernateのようなORMでデータベース側で通常発生することは、SQLの削除とそれに続く挿入を発行して、すべての電話番号を効果的に置き換えることです。VOのIDは関係ないので、これは問題ありません。

于 2012-12-09T22:46:18.887 に答える