2009-09-01 7 views
1

指定されたプロパティを持つドメインオブジェクト内のコレクションからオブジェクトを取得するためのベストプラクティスは何ですか?ドメインモデルからコレクション内のアイテムを取得するためのベストプラクティスは何ですか?

たとえば、私たちは車の保険の2つのクラスを持つ自動車保険アプリケーションを持っています。特定のVINを持つPersonからCarを取得する必要がある場合は、その方法を実装する最善の方法は何ですか?私は以下のいくつかの例を提供してきました - 他の人が

例1
はVINプロセスは次のようになり、アプリケーションからそう


    public class Person 
    { 
     private HashSet<Car> cars = new HashSet<Car>(); 

     public Set<Car> getCars() 
     { 
       return this.cars; 
     } 

     public Car getCarByVin(VIN vin) 
     { 
       //loop over cars and retrieve the car with the VIN 
     } 
    } 
 

に取得するために、Personエンティティ内に新しいメソッドを追加します歓迎されています。 ..


    VIN vin = new VIN(...); 
    Person person = personDao.getPerson(); 
    Car personCar = person.getCarByVin(vin); 

例2
新しいリストCを作成します。だから、アプリケーションからのプロセスはできるだけ早くあなたが指定したVINと車を言うように...


    VIN vin = new VIN(...); 
    Person person = personDao.getPerson(); 
    Car personCar = person.getCars().byVin(vin); 
+0

この実車が最初に必要な理由を教えてください。それは表示用か、実装しようとしている特定の動作ですか? –

+0

@ShaneC - 与えられた例は、完全なドメインについて説明することなく投稿できる簡単な例です。私の実際の問題では、別のエンティティオブジェクト内のビジネスルールにコレクションのオブジェクトを使用しようとしています。 –

答えて

3

私はDemeterの法則がここに当てはまると思います。これは最初の例を好むものです。 foo.getBar()。doBlah()のような連鎖しているときはいつでも、それはDemeterの法則を破っています。明らかに法律ではありませんが、クラスが別のクラス内のビットに関する詳細をあまりにも多く知っている必要がある場合には、良い指針です。

+1

ああ、LoD ...あなたは正しい - 細​​部が隠れているので、最初のものは2番目のものより優れている。クリスおかげで! –

2

だろうコレクション


    public class Person 
    { 
     private CarSet cars = new CarSet(); 

     public CarSet getCars() 
     { 
       return this.cars; 
     } 
    } 

    public class CarSet 
     implements Set<Car> 
    { 
     //implement required methods for Set 

     public Car byVin(VIN vin) 
     { 
       //loop over set and retrieve the car with the VIN 
     } 
    } 
 

にVIN法により取得をPersonエンティティ内ollectionと追加し、あなたはこれがエンティティであり、価値オブジェクトではないと思うようにします...また、エンティティであることを意味する値を「取得」する必要がある場合、値ではありません。バリューオブジェクトは一般的には取得する必要はありませんが、必要に応じてその場で作成することができます... DDDのエンティティ要素と値要素の区別は明確ですか?

追加:あなたが言ったことから、Carがエンティティである場合、それは集約ルートとしてPersonを含む集計のメンバーエンティティである必要があります。 (それはそれ自身の集合体のルートかもしれませんが)いずれにせよ、Personリポジトリは、集合体をフェッチするときに、その人物のCarsも取得できるように構築する必要があります。 Personクラスには、Type Cars、CarCollection、またはCars、OwnedCarsなどのプロパティがあり、Type(CarsまたはCarCollection)にはVINに基づいて特定のCarを取得するインデクサーが必要です。このような場合には

public class Person  
{ 
    private int persId; 
    // other fields 
    private Cars cars; 

    public Cars Cars { get; set; } 
    // all other stuff 
} 

public class Cars: Collection<Car> // or 'public class Cars: List<Car>' or ... 
{ 
    public bool Contains(string VinNumber] 
    { 
     foreach (Car c in this) 
      if (c.VinNumber = VinNumber) return true; 
     return false; 
    } 
    public Car this[string VinNumber] 
    { 
     get 
     { 
      foreach (Car c in this) 
       if (c.VinNumber = VinNumber) return c; 
      return null; 
     } 
    } 
} 
+1

+1有用な質問 – KLE

+1

これは「回答」よりもコメントとして優れていると思います。 – jsight

+0

あなたはおそらく正しいでしょう。これはエンティティオブジェクトであるように見えます。感謝チャールズ。 –

1

、私はそれが簡単ではなく、コレクションクラスをサブクラス化しようとするよりも、オブジェクト自体に検索方法を置くことを見つける(そして一見それから生じうる設計上の決定の変更のすべてを一緒に持って来ます簡単な決定)。

上記のすべては、基本的なデザインが実際にあなたが望むものであることを前提としています。私は一般的に、人物自体を検索するのではなく、人と村人が車両を検索できるようにするためのファサードを好んでいます。

+0

他のアプリケーションには、データアクセスロジック上にファサードを作成する「サービス」レイヤーがあります。それはあなたが示唆していることですか?

 public class CarFinderService { public Car findCar(PersonId personId, VIN vin) { //find the car with the VIN for the person specified } } 

+0

@Jared - はい、これらの行に沿ったものです。 – jsight

1

私はCarSetであなたのデザインを本当に嫌いです。特別な振る舞いなしに、その目的のために特別なクラスを見たいとは思わないでしょう。これは単純な例であることを示しています。

しかし、あなたのPersonの例にも反対します。静的な型のSetを持つはずのHashSetへのプライベートリファレンスがあります。次に、そのプライベートデータメンバーへの参照を返すゲッターがあります。これは誰でも操作できる変更可能な参照であることを理解する必要があります。あなたの私的修飾子は無意味です。

この場合、java.util.Collectionsクラスを使用して不変なSetへの参照を返すことで、クライアントがプライベート状態を変更できないようにすることができます。

+1

あなたは正しいです、Collections.unmodifiableXXX()メソッドは私たちの友達です。この例では、読みやすく、省略しています。ありがとうダフィー! –

関連する問題