简体   繁体   English

从域模型中检索集合中的项目的最佳实践是什么?

[英]What is the best practice for retrieving an item in a collection from a domain model?

What is the best practice for retrieving an object from a collection within a domain object with a specified property? 从具有指定属性的域对象内的集合中检索对象的最佳实践是什么?

For example, we have a car insurance application which has two classes: a Person with a list of Cars. 例如,我们有一个汽车保险应用程序,该应用程序分为两类:具有汽车列表的人员。 If I always needed to retrieve a Car from a Person with the specified VIN, what is the best way to implement the method? 如果我总是需要从具有指定VIN的人员处取回汽车,那么实现该方法的最佳方法是什么? I've provided a few examples below - others are welcome 我在下面提供了一些示例-欢迎其他示例

Example 1 例子1
Add a new method within the Person entity to retrieve the VIN 在Person实体内添加新方法以检索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
         }
    }

So from an application the process would be... 因此,从应用程序开始,该过程将...


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

Example 2 例子2
Create a new list collection within the Person entity and add the retrieve by VIN method to the collection 在Person实体中创建一个新的列表集合,并将VIN检索方法添加到该集合中


    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
         }
    }

So from an application the process would be... 因此,从应用程序来看,过程将是


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

I think the Law of Demeter applies here, which favors the first example. 我认为Demeter定律适用于此,这有利于第一个示例。 Any time you're chaining, such as foo.getBar().doBlah(), that's breaking the Law of Demeter. 每当您进行链接时,例如foo.getBar()。doBlah(),都将违反Demeter法则。 It's obviously not a law, but it's a good guideline for when a class has to know too many details about the bits within another class. 这显然不是法律,但对于一个类必须了解太多有关另一个类中的位的详细信息,这是一个很好的指导。

As soon as you say Car with specified VIN, you make me think this is Entity, not value object... Also, if you need to "retrieve" it that implies that it is Entity, not value. 当您说出具有指定VIN的Car时,您就让我认为这是Entity,而不是值对象...。此外,如果您需要“检索”它,则意味着它是Entity,而不是值。 Value objects don't generally need to be retrieved, you can just create one on the fly if you need one... Are you sure you are clear on distinction between entity and value elements in DDD? 通常不需要检索值对象,如果需要,可以只动态地创建一个。...您确定清楚DDD中实体和值元素之间的区别吗?

ADDED: Then if Car IS an entity, from what you've said, it appears that it should be a member entity in an aggregate with Person as the aggregate root. 添加:然后,如果Car是一个实体,那么从您所说的来看,它似乎应该是一个以Person为集合根的集合中的成员实体。 (Although it may be the root of it's own aggregate) In any case, the Person repository should be constructed so that when you fetch the aggregate it also gets the Cars for that person. (尽管它可能是其自身集合的根)在任何情况下,都应构建Person存储库,以便在您获取集合时,它也可以获取该人的Cars。 The Person class should have a property of Type Cars, or CarCollection, which is named Cars, or OwnedCars, or whatever, and the Type (Cars or CarCollection) should have an indexer that retrieves a specific Car based on the VIN. Person类应具有类型为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;
        }
    }
}

In cases like this, I find it easier to put the search method on the object itself, rather than trying to subclass a collection class (and bringing along all of the design decision changes that can result from that seemingly simple decision). 在这种情况下,我发现将搜索方法放在对象本身上要容易得多,而不是试图对集合类进行子类化(并带来可能由看似简单的决定引起的所有设计决定更改)。

All of the above assumes that the basic design is really what you want. 以上所有假设均假定您确实需要基本设计。 I'd generally prefer some sort of facade that allows me to search for vehicle by person and vin, rather than searching the person object itself, though. 我通常更喜欢某种外观,该外观使我可以按人和vin搜索车辆,而不是搜索人对象本身。

I really dislike your design with CarSet. 我真的不喜欢您使用CarSet的设计。 I wouldn't like seeing a specialized class for that purpose without specialized behavior; 我不希望看到没有专门行为的专门班级。 admittedly it's a simple example to demonstrate a point. 诚然,这是一个简单的例子来说明这一点。

But I also object to your Person example. 但我也反对您的“人”示例。 You have a private reference to a HashSet that should have static type of Set. 您具有对HashSet的私有引用,该引用应具有Set的静态类型。 Then you have a getter that returns a reference to that private data member. 然后,您将获得一个getter,该getter返回对该私有数据成员的引用。 You should realize that this is a mutable reference that anyone can manipulate. 您应该意识到这是任何人都可以操纵的可变参考。 Your private modifier is meaningless. 您的私人修饰语毫无意义。

The right thing to do in that case is to return a reference to an immutable Set, using the java.util.Collections class, to prevent clients from modifying private state. 在这种情况下,正确的做法是使用java.util.Collections类返回对不可变Set的引用,以防止客户端修改私有状态。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM