包含集合的 Web 应用程序域对象是否应该具有“添加”属性? 和“移除” 项目方法?
假设我有一个 Person 类,其中包含 Dog 对象的集合。 这种关系是双向的。
public class Person {
private List<Dog> dogs;
// getter and setter for dogs
}
public class Dog {
private Person person;
// getter and setter for person
}
好吧,现在如果我只是处理这些对象,我会在 Person 中有方法来添加狗和删除狗,这样客户端就不会直接处理集合。
public void removeDog(Dog dog) {
dogs.remove(dog);
dog.setPerson(null);
}
public void addDog(Dog dog) {
dog.setPerson(this);
dogs.add(dog);
}
或类似的规定。
我的问题是在服务层中使用这些对象时出现的。 我可以通过 addDog 添加一条新狗给一个人,然后简单地保存该人,它将自动保留新狗。 但是,通过removeDog删除狗然后保存该人不会自动从持久存储中删除狗......它只会将狗引用设置为空。
所以我最终得到这样的结果:
Dog dog = dogDAO.getDogById(int id);
dogDAO.remove(dog);
因为这是一个网络应用程序,并且人和狗不保存在内存中,所以它工作得很好,而且我从未调用过 Person.removeDog()。 下次我加载最初引用这只狗的人时,它将不会包含该狗,因为它已从存储中删除。 同样的事情也适用于添加狗:
Person person = personDAO.getPersonById(int id);
Dog dog = new Dog();
dog.setPerson(person);
dogDAO.save(dog);
即使我从未调用过 Person.addDog(),这也能正常工作。
那么在我的 Person 类中使用 addDog 和 removeDog 方法有什么意义吗?
Let's say I have a Person class that has a collection of Dog objects. The relationship is bidirectional.
public class Person {
private List<Dog> dogs;
// getter and setter for dogs
}
public class Dog {
private Person person;
// getter and setter for person
}
Ok now if I was just working with these objects, I would have methods in Person for adding a dog and removing a dog, so that the client isn't directly working with the collection.
public void removeDog(Dog dog) {
dogs.remove(dog);
dog.setPerson(null);
}
public void addDog(Dog dog) {
dog.setPerson(this);
dogs.add(dog);
}
or something along those lines.
My question comes when working with these objects in the service layer. I can add a new dog to a person via addDog and simply save the person which will automatically persist the new dog. However, removing a dog via removeDog and then saving the person will not automatically delete the dog from persistent storage...it'll just set the dog reference to null.
So I end up with something like:
Dog dog = dogDAO.getDogById(int id);
dogDAO.remove(dog);
Because this is a web app and Persons and Dogs are not maintained in memory, this works fine, and I never called Person.removeDog(). The next time I load up the Person who originally referenced this dog, it will not contain the dog because it was removed from storage. The same thing can apply to adding a dog:
Person person = personDAO.getPersonById(int id);
Dog dog = new Dog();
dog.setPerson(person);
dogDAO.save(dog);
Again this works fine even and I never called Person.addDog().
Is there any point to having the addDog and removeDog methods in my Person class then?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果没有人工干预,这总是很难做到。 一旦删除对象引用并拥有陈旧的对象。 在另一个用例中,您只需删除其他对象指向的对象(列表)。 这应该也是一个问题。 如果这被懒惰地接受,它将覆盖很多错误。
为简单起见,您可以将 dao 删除操作添加到 person removeDog() 中,但是从一个人身上删除狗并将其添加到另一个人的用例是不可能的。 如果你知道必须把狗从人身上移走,然后把它从持久性中移走,那么问题是什么? 你省得一步。 因此,归还被删除的狗将为您带来一种
亲自添加和删除的模式,使您不仅可以模仿列表行为,而且还可以拥有一些额外的功能。 就您而言,很难决定,因为这是一个简单的设置,并且取决于 dao 内容的可访问性以及您喜欢将其放在哪里。
您至少应该对您想要支持的每个用例有一个印象。 然后需要定义强制和可选的对象链接和设置。 通过一些实用主义(例如,将持久性内容与对象耦合),我们必须有机会做一些更容易使用的面向对象的设置(因此不易出错)
This is always hard to do without manual intervention. Once you remove the object reference and have a stale object. In the other use case you just remove the object to which some other object points (the list). This should be a problem, too. If this is accepted to lazily it will cover a lot of errors.
For simplicity you could add the dao remove operation to the person removeDog() but then the use case removing the dog from one person and add it to another wouldn't be possible. What is the problem that you remove the dog from the person and then remove it from the persistence if you know it has to be removed at all? You spare one step. So returning the removed dog will bring you a pattern of
Having the add and remove in person enables you not only to mimick the list behaviour but also to have some extra functionality. In your case it is hard to decide because it is an easy setup and it depends how accesible the dao stuff is and where you like to put that.
You should at least have an impression of every single use case you want to support. Then the mandatory and optional object links and settings need to be defined. With some pragmatism (e.g. coupling the persistence stuff with the objects) we have to chance to do some more object oriented setup that is easy (and therefor less error prone) to use
如果从逻辑上讲,将狗从人中添加和删除就是这样做的方式,那么就没有理由有方法将人从狗中添加和删除。 您的目标是您的数据模型始终处于一致状态。 如果您允许将人从狗身上移走,那么您就必须让狗将自己从人身上移走,以保持数据模型的一致性。 那么你就必须避免递归。
听起来你的方式很好、清晰、明确。 如果需要,您可以随时向 Dog 类添加注释,以添加没有 addPerson 和 removePerson 方法是有目的的,并且应该通过从人身上删除狗或将狗添加到人来完成此操作。
代码中不需要完美的对称性或完美的正交性。 目标不是为了这个,而是为了以干净、易于理解的方式保持数据模型的一致性。
If, logically, adding and removing dogs from people is how it will be done, then there is no reason to have methods for adding and removing people from dogs. Your goal is that your data model is always in a consistent state. If you allow removing people from dogs, then you'll have to have the dog remove itself from the person to keep your data model consistent. Then you'll have to avoid recursion.
It sounds like the way you have it is fine and clear and unambiguous. If you want, you can always add a comment to the Dog class to add that it's purposeful that there's no addPerson and removePerson method, and that this should be done instead by removing the dog from the person or adding the dog to the person.
There is no need for perfect symmetry or perfect orthogonality in code. The goal is not for that, but for keeping your data model consistent in a clean, understandable fashion.