在数据持久层中需要多少级抽象? [英] How many levels of abstraction do I need in the data persistence layer?

查看:18
本文介绍了在数据持久层中需要多少级抽象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm writing an application using DDD techniques. This is my first attempt at a DDD project. It is also my first greenfield project and I am the sole developer. I've fleshed out the domain model and User interface. Now I'm starting on the persistence layer. I start with a unit test, as usual.

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

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

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

As you can see I haven't written any expectations for the Add() function. I got this far and realized I haven't settled on a particular database vendor yet. In fact I'm not even sure it calls for a db engine at all. Flat files or xml may be just as reasonable. So I'm left wondering what my next step should be.

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

Should I add another layer of abstraction... say a DataStore interface or look for an existing library that's already done the work for me? I'd like to avoid tying the program to a particular database technology if I can.

推荐答案

根据您的要求,您真正需要的唯一抽象是具有基本 CRUD 语义的存储库接口,以便您的客户端代码和协作对象仅处理 IEmployerRepository 对象而不是具体的存储库.您有几个选择:

With your requirements, the only abstraction you really need is a repository interface that has basic CRUD semantics so that your client code and collaborating objects only deal with IEmployerRepository objects rather than concrete repositories. You have a few options for going about that:

1) 不再抽象.只需在您需要的顶级应用程序中构建具体的存储库:

1) No more abstractions. Just construct the concrete repository in your top-level application where you need it:

IEmployeeRepository repository = new StubEmployeeRepository();
IEmployee           employee   = repository.GetEmployee(id);

在一百万个地方改变它会过时,所以这种技术只适用于非常小的项目.

Changing that in a million places will get old, so this technique is only really viable for very small projects.

2) 创建存储库工厂以在您的应用程序中使用:

2) Create repository factories to use in your application:

IEmployeeRepository repository = repositoryFactory<IEmployee>.CreateRepository();
IEmployee           employee   = repository.GetEmployee(id);

您可以将存储库工厂传递给将使用它的类,或者您可以创建一个应用程序级别的静态变量来保存它(它是一个单例,不幸的是,但相当有界).

You might pass the repository factory into the classes that will use it, or you might create an application-level static variable to hold it (it's a singleton, which is unfortunate, but fairly well-bounded).

3) 使用依赖注入容器(本质上是一个通用工厂和配置机制):

3) Use a dependency injection container (essentially a general-purpose factory and configuration mechanism):

// A lot of DI containers use this 'Resolve' format.
IEmployeeRepository repository = container.Resolve<IEmployee>();
IEmployee           employee   = repository.GetEmployee(id);

如果您以前没有使用过 DI 容器,那么 SO 上有很多关于它们的很好的问题和答案(例如 哪些 C#/.NET 依赖注入框架值得研究?数据访问、单元测试、依赖注入),你肯定想阅读 Martin Fowler 的 控制容器反转和依赖注入模式).

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).

这篇关于在数据持久层中需要多少级抽象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆