【发布时间】:2011-02-07 19:42:48
【问题描述】:
我想到的一个优点是,如果您使用 Poco 类进行 Orm 映射,如果两者都支持 Poco,您可以轻松地从一个 ORM 切换到另一个。
拥有不支持 Poco 的 ORM,例如映射是使用 DataObjects.Net Orm 之类的属性完成的,对我来说不是问题,Poco 支持的 Orms 及其生成的代理实体也是如此,您必须知道实体实际上是绑定到某些上下文/会话的 DAO 对象,例如序列化是一个问题,等等。
【问题讨论】:
我想到的一个优点是,如果您使用 Poco 类进行 Orm 映射,如果两者都支持 Poco,您可以轻松地从一个 ORM 切换到另一个。
拥有不支持 Poco 的 ORM,例如映射是使用 DataObjects.Net Orm 之类的属性完成的,对我来说不是问题,Poco 支持的 Orms 及其生成的代理实体也是如此,您必须知道实体实际上是绑定到某些上下文/会话的 DAO 对象,例如序列化是一个问题,等等。
【问题讨论】:
POCO 是关于松散耦合和可测试性的。
因此,当您进行 POCO 时,您可以单独测试您的领域模型(例如,如果您正在做 DDD)。您不必担心它是如何持久化的。您不需要存根上下文/会话来测试您的域。
另一个优点是泄漏的抽象更少。因为持久性问题不会被推送到域层。所以你正在执行 SRP 原则。
我可以看到的第三个优势是,使用 POCO 你的领域模型更加进化和灵活。与将新功能耦合到持久性相比,您可以更轻松地添加新功能。
例如,我在做 DDD 时使用 POCO,但对于某些类型的应用程序,您不需要做 DDD(如果您正在做基于小数据的应用程序),所以关注点不一样。
希望对你有帮助
【讨论】:
没有。观点。人们喜欢到处乱扔的所有优势都是在大范围内不重要的优势。我更喜欢实体对象的强大基类,它实际上包含许多集成代码(例如在属性更改时抛出属性更改事件),而不是自己编写所有这些东西。请注意,在“LINQ”或“ObjectSpaces”甚至存在之前,我确实为 .NET 编写了一个(当时市售的)ORM。我已经使用了 15 年的 O/R 映射器,但从未发现 POCO 真的值得为此付出麻烦。
也就是说,由于其他原因,属性可能不好。这些天我更喜欢 Fluent NHibernate 方法 - 用属性启动了我自己的(现已退休的)映射器,然后转移到基于 XML 的文件。
“POCO 让我一无所获”的主题主要来自实体不是普通对象的观点。它们有很多额外的功能以及限制(如查询速度等),用户无论如何都应该注意这些。尽管有 LINQ,但 ORM 无论如何都不可替代 - 如果您开始使用它们真正有趣的更高功能,那就不要了。所以,最后你得到了 POCO,但仍然被基类和左右不同的语义所吸引。
我发现大多数 POCO 的支持者(例如:“必须有”,而不是“会很好”)通常没有认为他们的论点达到了真正的目的。你会得到各种非常糟糕的想法,几乎是在“存储过程比动态 SQL 更快”的水平上——这些想法根本不成立。比如:
一般来说,POCO 人们也忽略了真正要使其正确的大量工作 - 诸如事务对象更新之类的东西。基类中有大量代码。一些 .NET 接口很难在 POCO 级别上实现,但如果您可以绑定到 ORM 会容易得多。
在这里担任 Thomas Jaskula 的职位:
POCO 都是关于松散耦合和 可测试性。
假设您可以在没有它的情况下测试数据绑定?可测试性是模拟框架的东西,有真正强大的甚至可以“重定向”方法调用。
所以当你在做 POCO 时,你可以 测试你的领域模型(如果你是 做 DDD 例如)孤立。 你不必担心它是怎么做的 持续存在。你不需要存根 用于测试您的域的上下文/会话。
其实不然。持久性应该是任何领域模型测试的一部分,因为领域模型是要被持久化的。您始终可以通过不提交更改来测试非持久性场景,但许多测试将涉及持久性和失败(例如,具有无效/丢失数据的发票无效,无法写入磁盘)。
另一个优点是 更少泄漏的抽象。因为 持久性问题不会被推到 域层。所以你正在执行 SRP 原则。
其实没有。正确的域模型永远不会在实体中具有持久性方法。这是一个以(user.Save())开头的垃圾ORM。 OTOH 基类将处理诸如验证 (IDataErrorInfo) 之类的事情,处理持久字段上的属性更新事件,通常可以为您节省大量时间。
正如我之前所说,您应该拥有的某些功能很难用变量作为数据存储来实现 - 例如将实体置于更新模式、进行一些更改然后回滚的能力。不需要 - 如果在他们的数据网格中可用,请告诉使用该功能的 Microsoft(您可以更改某些属性,然后点击转义以回滚更改)。
我可以看到的第三个优势是 做 POCO 你的领域模型更多 进化和灵活。你可以加 新功能比以前更容易 耦合到持久性。
非争论。您不能在不处理持久性的情况下将字段添加到 peristet 类,并且可以将非持久性功能(方法)添加到非 poco 类,就像添加到 poco 类一样。
一般来说,我的非 POCO 基类执行以下操作:
并且它包含许多可覆盖的方法,实体可以使用这些方法来扩展行为而无需实现(公共)接口 - 因此这些方法实际上是实体私有的。它还有一些更多的内部属性,例如访问负责实体的“对象管理器”,这也是请求其他实体(提交查询)的点,这有时是需要的。
【讨论】:
ORM 中的 POCO 支持完全是关注点分离,遵循 Single Responsibility Principle。借助 POCO 支持,ORM 可以直接与域模型对话,而无需使用特定于数据访问的代码“混淆”域。这确保了域模型旨在仅解决与域相关的问题,而不是数据访问问题。
除此之外,POCO 支持可以更轻松地单独测试对象的行为,而无需数据库、映射信息甚至对 ORM 程序集的引用。拥有“独立”对象的能力可以显着简化开发,因为对象易于实例化且易于预测。
此外,由于 POCO 对象未绑定到数据源,因此无论它们是从您的主数据库、备用数据库、平面文件还是任何其他进程加载的,您都可以同等对待它们。尽管这似乎不会立即带来好处,但无论来源如何都一视同仁地对待您的对象可以使行为易于预测和使用。
我为我最近的 ORM 选择了 NHibernate,因为它支持 POCO 对象,它处理得很好。它适合项目遵循的领域驱动设计方法,并在数据库和领域之间实现了很好的分离。
能够切换 ORM 工具并不是 POCO 支持的真正理由。尽管您的类可能与 ORM 没有任何直接依赖关系,但它们的行为和形状将受到 ORM 工具和它所映射到的数据库的限制。更改 ORM 与更改数据库提供程序一样重要。一个 ORM 中总会有一些功能在另一个 ORM 中不可用,并且您的域类将反映功能的可用性或缺失。
在 NHibernate 中,您需要将所有 public 或 protected 类成员标记为 virtual 以启用对延迟加载的支持。这个限制虽然没有显着改变我的领域层,但对其设计产生了影响。
【讨论】: