拥有纯POCO模型有什么好处?


15

拥有纯POCO模型的主要好处是什么?我认为模型应该简洁明了,但是我倾向于将维护子对象保留在模型类中。例如,如果我有一个,ClassA并且ClassB定义如下:

public class ClassA
{
    public string MyProp { get; set; }
    public IEnumerable<ClassB> Children { get; }

    public void AddChild(ClassB newChild) { /*... */ }
    public void RemoveChild(ClassB child) { /* ... */ }
}

public class ClassB
{
    public string SomeProp { get; set; }
} 

拥有add和remove方法有天生的错误吗?我是否应该只公开列表并允许客户端代码添加任何传递简单数据验证职责的内容,例如不为null,并且不重复其他类?

感谢您的帮助。


我将删除Add / Remove方法,除非它们添加了一些值,例如将空的ClassB参数转换为对象的NullObject模式版本:AddChild(ClassB newChild) => Children.Add(newChild ?? new NullClassB())
Graham

如果您曾经使用数百种方法来解决ActiveRecord类的头痛问题,那么在任何时候可能都可以,也可以不需要,我想这很容易理解。
Casey

避免这种特殊设计的主要原因是因为它违反了.net设计准则。它是完全任意的,但是人们希望集合中包含变异方法。
Frank Hileman

@Casey我没有使用Active Record模式,add方法只是在做一些次要的数据验证。因为没有公开集合,所以存在remove方法,它们只是在内部列表中添加和删除。我已经更改了它,尽管使用了不同的集合类型,该类型允许我在仍然使用内置的“添加/删除”方法的同时进行验证。
杰西(Jesse)

Answers:


42

您的两个问题无关。

拥有纯POCO模型有什么好处?

纯粹的POCO并不依赖于某些企业框架,约定,[]事物,也不依赖于与相似地依赖的某些对象的紧密连接。换句话说,围绕POCO的世界可以完全改变,它只是继续做自己想做的事情而已。您不能通过更新框架,将其移至新系统中或以有趣的方式破坏它。它一直在工作。唯一的依赖关系是它明确要求的东西。

POCO只不过是POJO的想法。J更改为C,因为当您解释使用Java编写的名称中包含Java的概念时,人们会觉得您很有趣。这个想法不依赖于语言。他们本可以简单地将其称为“普通旧物件”。但是谁愿意吹嘘使用POO?

我让福勒解释其起源:

这个词是在Rebecca Parsons,Josh MacKenzie和我在2000年9月的一次会议上准备演讲时创造的。在演讲中,我们指出了将业务逻辑编码为常规Java对象而不是使用Entity Beans的许多好处。我们想知道为什么人们反对在他们的系统中使用常规对象,并得出结论,这是因为简单的对象缺少花哨的名称。因此,我们给了他们一个,非常受欢迎。

martinfowler.com:POJO

至于其他问题:

拥有add和remove方法有天生的错误吗?

我不喜欢A直接了解B。但这是DIP而不是POJO的事情。


B为了简单起见,我直接依赖于此,理想情况下,这两个都将实现接口。但A仍然有一个清单IInterfaceBAddChild如果孩子通过接口引用松散耦合,该方法有什么问题吗?
杰西(Jesse)2015年

6
为了简单起见,我可以做很多愚蠢的事情。我不喜欢A关于B的知识。A不使用B,因此无需定义适当的A拥有的接口即可与B进行通信。据我所知,A是一个集合。因此,A应该通过<T>与B进行交易,因此不必了解任何事情。
candied_orange

2
我还看到“ PODO”代表“普通旧数据对象”,以避免在首字母缩写词中使用任何形式的语言说明符。PODO听起来有点傻(对我来说,听起来有点像您在Tatooine上听到的一个上位音),比我想的POJO或POCO听起来要多,但比POO少得多。
KRyan

2
我想知道如果福勒称呼他们为POO,他的演讲会进行得如何?
奥利弗(Oliver)

3

使用添加和删除,您可以实现Collection<T>功能。问自己,为什么要使用IEnumerable<T>而不是List<T>其他可变的类?显然不是因为您的集合应该是只读的。

我能想到的唯一原因是您想控制要发布的访问方法。在这种情况下,最好创建自己的集合类,封装列表,实现选择方法Add和Remove以及Implement IEnumerable<T>。然后使用它代替IEnumerable<T>您的孩子集合的类型。

但是在我看来,List<ClassB>这可能只会为您服务。


0

什么AddChild添加和RemoveChild删除的?如果它来自数据库(或任何类型的持久性存储),那么您已经有了一个Active Record。不一定总是一件坏事,但这确实使您几乎不必担心框架,约定,依赖项等,就像@CandiedOrange提到的那样。

同时,如果它们都在同一应用程序中,那么避免从ClassA到ClassB(或至少是InterfaceB)的依赖又有什么意义呢?在您的应用程序建模的现实世界中,事情确实相互依赖。实际对象确实具有“属于”它们的其他对象的集合。在代码中表示这些关系是完全合适的。

它变得更加复杂的唯一原因是,似乎您需要精确地管理ClassB如何与ClassA关联和脱离。因此,您需要执行一些行为。您可以在类中实现它(这完全是“合法的”;请参见/programming//a/725365/44586),也可以有某种单独的包含该行为的类。采取最适合您个人情况的方法。

在任何情况下,POJO / POCO实际上都是面向对象的,没有装饰,没有负担。遵循OOP原则,您将很安全。


确实,AddChild只是检查重复项,是否为null,不允许两者之一。RemoveChild之所以存在,是因为为了防止后门添加,该集合公开为IEnumerable。它只会执行从集合中的标准删除。
杰西

1
感谢您的解释。是的,这听起来完全像应该是POCO中的行为类型,并且绝对好于仅公开基础IEnumerable供调用者随意修改或替换。
John M Gant

我认为Active Record只是一个坏模式。
Casey

1
@Casey,您不会因此而引起任何争议。但是我也不会争论是否有人要使用它。要点是,如果Jesse确实打算使用Active Record之类的将持久性与模型定义集成在一起的模式,那么他会遇到CandiedOrange所强调的所有问题,而实际上并没有资格成为POCO。但这不是他在做什么。
John M Gant
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.