17611538698
webmaster@21cto.com

初探领域驱动设计(1)为复杂业务而生

资讯 0 16050 2017-04-27 12:01:21
[h1]概述[/h1]
  领域驱动设计也就是3D(Domain-Driven Design)已经有了10年的历史,我相信很多人或多或少都听说过这个名词,但是有多少人真正懂得如何去运用它,或者把它运用好呢?于是有人说,DDD和TDD这些玩意是一些形而上的东西,只是一茶余饭后的谈资,又或是放到简历上提升逼格而已。前面这句话我写完之后犹豫了,犹豫要不要把它删掉,因为它让我看起来像个喷子,我确实感到不解,为什么别人10年前创造总结出来的东西,我们在10年之后对它的理解还处于这么低的一个层次。开篇就说远了,我也是最近才开始认真学习领域驱动设计,并且得到了园子里面netfocus,刘标才田园里的蟋蟀的帮助,在此再次表示感谢。希望能和大家一起把DDD普及下去。

  我们之前有一个关于领域驱动设计的讨论,另外dax.net也有一个关于领域驱动设计的系列写得不错,有兴趣的同学可以看看。本文会以一个初学者的角度来讲解DDD,让我们一切从零开始,我相信你跟我一样也会爱上它的。

  本篇主要讨论一下为什么我们要用DDD,它能够为我们带来什么?

[h1]领域驱动系列[/h1]
  初探领域驱动设计(1)为复杂业务而生
  初探领域驱动设计(2)EF 和 Repository
  初探领域驱动设计(3)写好单元测试
  ......

[h1]目录[/h1]













[*]厘清业务关系 - 聚合与聚合根[/*]
[*]独立领域业务层 - 高内聚,低耦合,可测试[/*]
[*]干净漂亮的代码[/*]
[*]小结[/*]











[/list]
这一篇文章讲解的很清楚。总之,我们的领域模型以及相关的类比如工厂等会被独立成为一层来与应用层和基础设计层交互。




   领域层是独立的,首先它是应用层的下层,所以肯定不会有对应用层的依懒,但是领域有一些模型或者服务少不了是要与数据库打交道的,比如说我们在注册用户的时候需要去验证当前的邮箱是不是已经被占用了。而这一类操作都是属于基础设施层做的事情,包含像一些数据库操作,日志,缓存等等。那么我们如何避免领域层对基础设施层的依懒呢?感谢面向对象设计 - 面向接口编程,只不过这里面的场景特别有代表性,它是一个非常常见的问题,于是它成为了一个模式:仓储(Repository)。http://repositoryandef.codeplex.com
欢迎大家Follow。注意代码还没有写完,只是一个初级版本,我们后面会慢慢完善。这个项目会使用EF来作业ORM框架,Autofac作依懒注入容器,用Xunit作单元测试框架的同时引入了Fluent Assertions。

小结
   本文主要介绍了DDD的一些基础概念:

  • 领域模型:领域实体、领域服务以及值对象;建模一定要从真实的领域业务出发,多与领域专家进行沟通来完善模型。
  • 聚合与聚合根:它的主要作用是用来确保各种关系下的实体的数据一致性;但是确认聚合根这个过程,实际上也是对业务的梳理过程。
  • 架构分层: 每一层都职责清楚;依懒于接口来降低耦合。
  • 封装和测试: 所有的业务都放到领域层,同时对领域层进行单元测试来确保最核心的逻辑不会遭到破坏。

  个人感觉没有必要太强调Repository的概念,从领域实体的生命周期(创建-持久化到数据库-销毁-从数据库重建)你会发现其实这个过程很普遍,并不是只有DDD才有的。所以我认为Repository主要是将数据访问功能给隔离开,避免领域实体对基础设施层的依懒。那它和三层有什么区别? BLL 引用DAL不也是依懒于接口么?给我的感觉是,DDD的领域实体持久化这一块就是三层里面的思路。这可能是在学习DDD初期的想法,因为真实的大型项目中是不会直接把领域实体给持久化的,那个叫DTO,于是Repository<>里面放的就不是我们的领域实体了,而是将领域实体转换成对应的DTO。 

  是否一定要使用DTO呢?领域实体和DTO互相转换,最后到了表现层DTO还要和ViewModel转换,会不会带来复杂性和性能上的损失?Repository和EF还有Unit Of Work怎么来协调?抱怨写单元测试么?怎么样让写单元测试不变成只是走过场而已? 这些问题留给我们后面再解决吧。

评论