数据持久层需要多少个抽象级别?
-
13-09-2019 - |
题
我正在使用 DDD 技术编写一个应用程序。这是我第一次尝试 DDD 项目。这也是我的第一个绿地项目,我是唯一的开发商。我已经充实了域模型和用户界面。现在我从持久层开始。像往常一样,我从单元测试开始。
[Test]
public void ShouldAddEmployerToCollection()
{
var employerRepository = new EmployerRepository();
var employer = _mockery.NewMock<Employer>();
employerRepository.Add(employer);
_mockery.VerifyAllExpectationsHaveBeenMet();
}
正如您所看到的,我没有写出对 Add() 函数的任何期望。到目前为止,我意识到我还没有选定特定的数据库供应商。事实上,我什至不确定它是否需要数据库引擎。平面文件或 xml 可能同样合理。所以我想知道我的下一步应该是什么。
我应该添加另一层抽象吗?说一个 DataStore 接口或寻找一个已经为我完成工作的现有库?如果可以的话,我想避免将程序与特定的数据库技术联系起来。
解决方案
根据您的要求,您真正需要的唯一抽象是具有基本 CRUD 语义的存储库接口,以便您的客户端代码和协作对象只处理 IEmployerRepository
对象而不是具体的存储库。您有几种选择:
1) 不再有抽象. 。只需在您需要的顶级应用程序中构建具体存储库即可:
IEmployeeRepository repository = new StubEmployeeRepository();
IEmployee employee = repository.GetEmployee(id);
在一百万个地方改变它会变得过时,所以这种技术只对非常小的项目真正可行。
2)创建 存储库工厂 在您的应用程序中使用:
IEmployeeRepository repository = repositoryFactory<IEmployee>.CreateRepository();
IEmployee employee = repository.GetEmployee(id);
您可以将存储库工厂传递到将使用它的类中,或者您可以创建一个应用程序级静态变量来保存它(它是一个单例,这很不幸,但界限相当明确)。
3)使用 依赖注入容器 (本质上是通用工厂和配置机制):
// A lot of DI containers use this 'Resolve' format.
IEmployeeRepository repository = container.Resolve<IEmployee>();
IEmployee employee = repository.GetEmployee(id);
如果您以前没有使用过 DI 容器,那么这里有很多关于它们的很好的问题和答案(例如 哪些 C#/.NET 依赖注入框架值得研究? 和 数据访问、单元测试、依赖注入),你肯定会想读一下马丁·福勒(Martin Fowler)的 控制容器反转和依赖注入模式).
其他提示
在某些时候,你将不得不拨打电话,什么你的仓库将与数据做。当你开始你的项目很可能是最好保持尽可能简单,只在必要时添加抽象层。简单地定义你的资料库/ DAO的是大概够在这个阶段。
一般情况下,储存库/存储库/ DAO中应该知道的实现细节的数据库或ORM的你已经决定使用。我希望这就是为什么你在DDD使用存储库。这样,你的测试可以嘲笑库和不可知的执行。
我写了一篇关于实施NHibernate的顶部Repository模式一篇博客文章中,我想不管你是否使用NHibernate的或不将有利于你。
有一件事情我已经与持久层发现的是,以确保有一个地方,你可以开始做抽象。如果你的数据库的增长,你可能需要开始实施分片,除非已经有一个抽象层已经上市,它可能很难在以后添加一个。
我相信你不应该仅仅进行单元测试的目的添加该存储库类之下又一层,特别是如果你没有选择你的持久化技术。我不认为你可以创建一个接口要比“repository.GetEmployee(ID)”更细粒度的不暴露有关持久性方法的细节。
如果你真的使用纯文本或XML文件的考虑,我认为最好的办法是坚持与存储库抽象接口。但是,如果你已经决定使用数据库,你只是不知道供应商,ORM工具可能是要走的路。