我最近加入了一个大型团队/项目,在整个解决方案中使用存储库模式和依赖注入。我注意到存储库接口位于数据层项目中,要求业务层项目直接依赖于它。我的理解是,在使用DI时,您需要反转此依赖关系以将业务逻辑与数据访问(业务层的数据引用接口)分离。当我向团队提出这个问题时,反应不一。他们没有看到好处并反对它(“每个人都知道不要直接引用具体类型”,“我们永远不需要换掉我们的数据访问技术”等。)
将存储库接口与实现(数据层)保持在同一个项目中是一种好的做法吗?如果业务层仅引用数据层中的存储库接口,那么此设置是否有任何缺点?
答案 0 :(得分:2)
摘要[应该]由上层/政策层拥有
你可能已经读过Mark Seemann的优秀书籍Dependency Injection in .NET,他在这里展示了这个原则(参见第1版第2.2节和第2版第3章),并举例说明了具体情况您正在描述(即存储库接口作为域层的一部分)。
Mark Seemann为此做出的最重要的论点是因为它允许您用不同的数据替换您的数据访问技术,这可能是您可能想到的更可能的情况,特别是考虑到我们现在居住的世界一切都移动到云和云中,您可能没有(或想要)使用相同的数据访问技术。
但是还有其他原因想要将核心层(域层)与应用程序的其余部分隔离开来,让一切都依赖于应用程序中最重要的部分。
我想到的一件事是,让开发人员无法将此层偶然地耦合到系统的易失性(或不纯)部分,这使得以后更难以进行更改。对数据访问功能的依赖是一个显而易见的事情,因为它可以使测试更加困难,但也会考虑意外地将您的域层耦合到System.Web
,从而使开发人员可以在该部分中使用HttpContext
系统的。一旦你有依赖关系(从域层到数据访问层),很可能会随着时间的推移而变得更加困难。
另一方面,这种高度隔离是否对您的应用有益,显然取决于很多因素。特别是当应用程序已经以这种方式设计时,最好将注意力集中在其他改进上。
不要忘记Dependency Inversion Principle(DIP)和依赖注入(DI)最重要的部分是类依赖于抽象。这使得松耦合,松耦合提高了可维护性。由于那些开发人员已经在实践DI,他们已经处于一个好位置。
我做的一个典型改进是摆脱大多数存储库,并引入更高级别的概念,例如a generic abstraction over business operations,通用abstraction over queries以及有时域事件。这限制了将存储库用于内部域层。在介绍这个时,这是一个很好的时刻来反转使用这些概念的新(或迁移)代码的依赖关系,而不是I[EntityName]Repository
和I[EntityName]Service
抽象,这些抽象通常违反了大多数SOLID原则
我提倡的另一件事是阻止应用程序的核心层依赖于某些第三方日志库的记录器抽象。这再次归结为DIP,该DIP声明应用程序应该拥有抽象,而当应用程序依赖于第三方抽象时则不是这种情况。这就是我推广this等内容的原因。
答案 1 :(得分:1)
个人而言,我总是将依赖关系从最低级别“流动”到最高级别。 UI需要与业务逻辑交互,因此它依赖于服务接口。服务/业务逻辑需要数据访问,因此它依赖于存储库接口来执行此操作。
这是我在大多数代码库中看到的一般方法。
答案 2 :(得分:-3)
它属于应用程序中的数据访问层。