cbr*_*der 38 domain-driven-design persistence-ignorance
我是DDD + TDD世界的新手.但我已经编程了将近9年.
有人可以解释我坚持不懈的好处吗?典型的nHibernate应用程序只是将类和数据库之间的依赖关系推送到映射文件.
如果我更改类文件或数据库,我必须更改映射文件.那么是不是只是通过添加一个抽象层来推动依赖?在我看来,到目前为止,我认为这不是革命性的.但我不确定我是否遗漏了什么.
最后,我如何测试映射文件?映射文件中可能会出现错误,我该如何测试它们?
Ste*_*ger 49
让我用一个例子解释一下.让我们假设您正在使用传统的SQL方法实现应用程序.您打开记录集,更改数据并提交它.
伪代码:
trx = connection.CreateTransaction();
query = connection.CreateQuery("Select * from Employee where id = empid");
resultset = query.Run();
resultset.SetValue("Address_Street", "Bahnhofstrasse");
resultset.SetValue("Address_City", "Zürich");
trx.Commit();
Run Code Online (Sandbox Code Playgroud)
使用NHibernate,它看起来像这样:
emp = session.Get<Employee>(empid);
// persistence ignorant 'logic'
emp.Address.Street = "Bahnhofstrasse";
emp.Address.City = "Zürich";
session.Commit();
Run Code Online (Sandbox Code Playgroud)
持久性无知意味着业务逻辑本身不知道持久性.或者换句话说,持久性与逻辑分离.这使它更加可重用.
将"逻辑"移动到可重用的方法:
void MoveToZuerichBahnhofstrasse(Employee emp)
{
// doesn't have anything to do with persistence
emp.Address.Street = "Bahnhofstrasse";
emp.Address.City = "Zürich";
}
Run Code Online (Sandbox Code Playgroud)
尝试使用结果集编写这样的方法,你知道持久性无知是什么.
如果您不相信,请查看单元测试的简单程度,因为与持久性相关的东西没有依赖性:
Employee emp = new Employee();
MovingService.MoveToZuerichBahnhofstreasse(emp);
Assert.AreEqual("Bahnhofstrasse", emp.Address.Street);
Assert.AreEqual("Zürich", emp.Address.City);
Run Code Online (Sandbox Code Playgroud)
DDD是不同的东西.在那里,您首先构建域模型(类模型)并根据它创建数据库设计.使用NH这非常简单,因为 - 由于持久性无知 - 您可以在拥有(确定的)数据库模型之前编写和单元测试模型和逻辑.
测试:我们通过创建实体的实例,将其存储到数据库,将其取回并进行比较来测试映射.这是通过大量反射自动完成的.但你不需要走这么远.在尝试存储实体时,大多数典型错误都会出现.
你可以对查询做同样的事情.复杂的查询值得测试.如果查询完全被编译,那将是最有趣的.你甚至不需要任何数据.
对于数据库集成测试,我们使用的是Sqlite.这很快.NH使用SchemaExport动态生成内存数据库(在每次测试之前).
我一直在思考这个领域,虽然我过去曾使用存储过程ADO.NET,但只有当我最终转向NHibernate时,我对我的持久性机制感到满意.
域驱动设计(DDD)将重点放在域模型上.这意味着主要关注的是创建一个概念模型,为用户和程序员形成一种通用语言.用户几乎从未对如何保持信息感兴趣.NHibernate通过使持久性成为捕获业务规则和了解用户真正想要从系统中获得什么的关注点来帮助您实现这种思维方式.
流畅的NHibernate减少了域模型的更改对底层映射文件的影响.它还具有自动映射功能.虽然您永远无法完全忽略系统的持久性,但NHibernate与Fluent NHibernate允许您专注于域模型.如果您不专注于使用丰富的Domain模型,那么NHibernate几乎没有什么好处.
关于测试映射,无论用什么方法实现持久性,都要编写测试(或者你应该是).这不是因为您使用NHibernate而出现的额外工作.试想一下测试你的映射是否测试你的持久性是否正常工作.
再次为此Fluent NHibernate是非常宝贵的.它有一个持久性规范测试,在大多数情况下使用起来非常简单.