4

我正在使用 DDD 技术编写应用程序。这是我第一次尝试 DDD 项目。这也是我的第一个绿地项目,我是唯一的开发商。我已经充实了域模型和用户界面。现在我从持久层开始。像往常一样,我从单元测试开始。

[Test]
public void ShouldAddEmployerToCollection()
{
    var employerRepository = new EmployerRepository();
    var employer = _mockery.NewMock<Employer>();

    employerRepository.Add(employer);
    _mockery.VerifyAllExpectationsHaveBeenMet();
}

如您所见,我没有为 Add() 函数编写任何期望。我做到了这一点,并意识到我还没有选择特定的数据库供应商。事实上,我什至不确定它是否需要一个数据库引擎。平面文件或 xml 可能同样合理。所以我想知道我的下一步应该是什么。

我应该添加另一层抽象...比如 DataStore 接口还是寻找已经为我完成工作的现有库?如果可以的话,我想避免将程序与特定的数据库技术联系起来。

4

5 回答 5

8

根据您的要求,您真正需要的唯一抽象是具有基本 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);

If you haven't used DI containers before, there are lots of good questions and answers about them here on SO (such as Which C#/.NET Dependency Injection frameworks are worth looking into? and Data access, unit testing, dependency injection), and you would definitely want to read Martin Fowler's Inversion of Control Containers and the Dependency Injection pattern).

于 2009-11-03T14:33:53.223 回答
1

At some point you will have to make a call as to what your repository will do with the data. When you're starting your project it's probably best to keep it as simple as possible, and only add abstraction layers when necessary. Simply defining what your repositories / DAOs are is probably enough at this stage.

通常,存储库/存储库/DAO 应该知道您决定使用哪个数据库或 ORM 的实现细节。我希望这就是您在 DDD 中使用存储库的原因。这样,您的测试可以模拟存储库并且与实现无关。

于 2009-11-03T14:34:10.877 回答
0

我写了一篇关于在 NHibernate 之上实现存储库模式的博客文章,我认为无论您是否使用 NHibernate,它都会使您受益。

创建一个通用的通用和可扩展的 NIBerate 存储库

于 2009-11-03T14:40:18.803 回答
0

我发现持久层的一件事是确保有一个地方可以开始进行抽象。如果您的数据库在增长,您可能需要开始实施分片,除非已经有一个可用的抽象层,否则以后添加一个可能会很困难。

于 2009-11-03T20:10:28.357 回答
0

我相信你不应该仅仅为了单元测试的目的在存储库类下面添加另一层,特别是如果你没有选择你的持久性技术。我不认为你可以创建一个比“repository.GetEmployee(id)”更精细的接口而不暴露有关持久性方法的细节。

如果您真的在考虑使用纯文本或 XML 文件,我相信最好的选择是坚持使用存储库接口抽象。但是,如果您决定使用数据库,并且您只是不确定供应商,那么 ORM 工具可能是您的最佳选择。

于 2009-11-04T02:39:22.343 回答