POCO!=域对象?

时间:2011-01-07 16:26:31

标签: design-patterns orm architecture domain-driven-design

当我使用ORM完成我的第一个大型项目时,我开始意识到ORM将成为创建具有表现力和传达意图的域对象的一大障碍。

也就是说,我知道我们不希望域对象只是公众可访问的getter和setter的包。另外,我开始意识到仅仅具有IList< T>。所有地方都没有表达意图,并且可能会邀请使用这些对象的开发人员滥用。例如,拥有ReadOnlyCollection< T>可能更好。裸露。 (顺便说一句,我正在使用.NET和实体框架。)而不是IList< MyDomainObject>,我发现自己想要从MyDomainObject公开派生的对象列表。 (这些东西在EF中都不容易。也许我需要使用NHibernate或ADO.Net。)

我的问题是:我是否试图以这种方式制作域对象?这些问题是否应该成为其他应用程序组件的一部分?或者我应该有一个“真正的”域对象(具有表达性的东西)和一个由ORM水合的“哑”POCO对象?


(编辑:系统吃了一堆尖括号。)

5 个答案:

答案 0 :(得分:2)

我的观点是,你让EF做它的事情并创建免费的POCO。你也可以称他们为DTO - 他们的角色是从记忆到坚持和回归的桥梁。就你的“域名”而言,我从未接受过你的数据库架构反映一个连贯的域模型的想法。因此,我总是在Persistence(或存储库)层之上创建一个Domain层,该层代表业务域,使作为Persistence的香肠工厂保持不变。此域层可以根据需要混搭您的DTO,以使面向开发人员的模型有意义。使用工厂模式从DTO创建域对象,反之亦然 - 将DTO保留在客户端代码之外,以便您可以将架构更改与使用者隔离。

这是更多的工作,更多的映射代码等但它是值得的 - EF已经削减了你的代码,我认为你实际上应该花时间来编写域逻辑和表示,它是什么让你比代码更好生成工具:)

祝你好运。

答案 1 :(得分:1)

  

(这些都不容易做到   在EF。也许我需要使用NHibernate   或者ADO.Net。)

宾果。 EF不支持您的域与持久性基础架构之间的相同级别的独立性,因为NHibernate或自定义构建的解决方案可以。

对于暴露的类型,我坚持使用IEnumerable并在父级上使用Add和Remove方法,通常是..有时是自定义集合,但从不IList。

答案 2 :(得分:1)

这是一个非常好的问题 - 当我尝试将ORM用于域对象时,我已经意识到这一点。我的域对象公开IEnumerable类型的公共属性,它返回ReadOnlyCollection,因此添加到集合的唯一方法是在父级上调用自定义Add方法。

在我看来,不,你不会用这种方式来制作你的物品。

我完全容忍尝试将对象封装到最大程度,保持字段私有并提供原子的公共方法,显式显示意图,并确保对象只能存在于有效状态。如果这意味着使用原始ADO.NET,那么就这样吧。对我来说,保持域对象的严格设计不应该因选择DAL技术而受到损害。

然而,我讨厌编写锅炉板DAL代码并用sprocs编写原始ADO.NET会在这些日子里成为我的头脑。我已经意识到,如果使用Event Sourcing作为域对象的持久性机制,那么为封装的域对象编写DAL会变得更容易很多。您只需要一个Event表,它将您的所有事件存储为序列化数据。由于域对象本身不是持久的,因此存储库无权访问域对象上的List属性并不重要。然后,您的工作单元“提升”查询组件可以处理的这些事件,这将填充/更新使用简单DTO和OR​​M所需的任何表。

Here's an example of event sourcing

CQRS&事件源实际上旨在提供高可伸缩性,并且根据定义包括基于“最终一致”范例的大量异步操作。但是,即使在处理不需要这种级别的可伸缩性的项目时,我发现以同步方式遵循这些模式提供了一种机制来保持我的域对象完全封装,同时不必编写单行手工制作的DAL代码,节省大量时间,并为每次采取的行动提供完整的审计跟踪(事件),免费投入。如果您的系统需要通过消息传递与第三方系统进行通信,这也是一个非常宝贵的工具。

答案 3 :(得分:1)

我尝试在几个项目中使用POCO作为域对象,坦白说它只适用于简单/小型项目。

我喜欢ORM并且不会停止使用它们。但我总是在orm / repository层之上构建一个域层。我创建了在我的应用程序中使用的特定域对象。我使用像automapper之类的映射框架将域对象转换为数据对象/从数据对象转换。

我建议您在使用实体框架时停止使用POCO,让EF为您生成数据对象。然后改为创建域对象,让automapper处理域层中的映射。

这是一项更多的工作,但它更灵活,更容易使用。

答案 4 :(得分:0)

没有任何东西可以说POCO不能包含你自己的复杂物体。使POCO成为POCO的原因是它没有与数据状态的链接,而不是它只能包含列表作为对象。