Data structures 存储库模式vs.“;“聪明的”;业务对象

Data structures 存储库模式vs.“;“聪明的”;业务对象,data-structures,architecture,repository-pattern,Data Structures,Architecture,Repository Pattern,在.NET上创建更大规模的企业级应用程序(Winforms、WPF、ASP.NET)时,我看到了两个主要的“思想流派” 有些人使用“存储库模式”,它使用一个知道如何获取、插入、更新和删除对象的存储库。这些对象相当“愚蠢”,因为它们不一定包含很多逻辑——例如,它们或多或少都是数据传输对象 另一个阵营使用我称之为“智能”的业务对象,它们知道如何加载自己,并且通常具有Save()、Update()甚至Delete()方法。在这里,您真的不需要任何存储库——对象本身知道如何加载和保存它们自己 大问题是:

在.NET上创建更大规模的企业级应用程序(Winforms、WPF、ASP.NET)时,我看到了两个主要的“思想流派”

有些人使用“存储库模式”,它使用一个知道如何获取、插入、更新和删除对象的存储库。这些对象相当“愚蠢”,因为它们不一定包含很多逻辑——例如,它们或多或少都是数据传输对象

另一个阵营使用我称之为“智能”的业务对象,它们知道如何加载自己,并且通常具有Save()、Update()甚至Delete()方法。在这里,您真的不需要任何存储库——对象本身知道如何加载和保存它们自己

大问题是:您使用或更喜欢哪个?为什么

您是否在所有应用程序中使用相同的方法,或者在选择一种方法而不是另一种方法时,您是否有任何特定的标准?如果是,这些标准是什么

我不是想在这里挑起一场火焰战——只是想找出大家对这件事的看法和你的看法,以及为什么你使用一种(或两种)模式而不是另一种


谢谢你的建设性意见

我使用存储库模式是因为单一责任原则。我不想让每个单独的对象都知道如何保存、更新和删除自己,因为这可以由一个通用存储库处理

存储库模式不一定会导致哑对象。 如果对象在保存/更新之外没有逻辑,那么您可能在对象之外做了太多的工作

理想情况下,永远不要使用属性从对象中获取数据、计算内容并将数据放回对象中。这是封装的中断

因此,对象不应该贫血,除非使用带有CRUD操作的简单DTO对象


然后,将持久性关注点与对象关注点分离是一种承担单一责任的好方法。

我认为使用存储库模式与使用该模式相比,最重要的副作用是测试和可扩展性

如果ActiveRecord对象本身不包含存储库,您如何在测试用例中隔离数据检索?你不能轻易地假装或嘲笑它


除了测试之外,交换数据访问技术也要困难得多,例如从Linq到SQL,再到NHibernate或EntityFramework(尽管这并不经常发生)。

以下是我遇到的两篇有趣的文章


这实际上取决于应用程序的需求,但在处理复杂的业务模型时,我更喜欢ActiveRecord。我可以在一个地方封装(并测试)业务逻辑

大多数ORM(EF、nHibernate等)都是您的存储库。许多人认为一个ORM之上的层封装了所有数据交互作为一个存储库,我认为这是错误的。根据Martin Fowler的说法,存储库将数据访问封装为一个集合。因此,对所有数据检索/变异使用单独的方法可能需要使用数据映射器或数据访问对象

使用ActiveRecord,我希望有一个“实体”基类。我通常将ORM(存储库)与这个基类一起使用,因此我的所有实体都有一个GetById、AsQueryable、Save和Delete方法


如果我更多地使用面向服务的体系结构,我将使用存储库(一个屏蔽直接数据访问或ORM的存储库),并在我的服务中直接调用它

在这种情况下,一个通用存储库需要知道如何加载所有类型的对象。因为它是通用的,所以它可以处理加载所有类型的对象。同时也使单元测试更简单。我也喜欢存储库样式,因为数据传输对象更灵活。您可以在任何地方使用它们,不依赖于框架、层等。它们只表示概念、模型。如果您想要在模型和BD之间架起一座桥梁,那么您需要构建持久层。您希望在模型和构建UI的用户之间架起一座桥梁。您需要计算事物,实现用例,构建业务逻辑。所有这些都与简单的模型对象有关,这些对象只与业务概念本身无关。不,当然-我的busobj并不完全“愚蠢”-我的意思是“愚蠢”,因为他们不知道如何加载和保存自己-他们确实有其他功能,显而易见:-)这是明智的设计。我个人认为“bo知道如何加载自己”是不雇佣开发人员的理由-显然,e从未听说过责任分离,也从未见过正确封装的DAL。您使用过CSLA吗?它在我们使用它的一个项目上运行得非常好,该项目涉及到N层部署。