概述

DDD领域驱动设计,它是对面向对象的的分析和设计(OOAD,Object Orient Analysis Design)的一个补充,对技术框架进行了分层规划,同时对每个类进行了策略和类型划分。领域模型是领域驱动的核心 ,采用DDD的设计思想,业务逻辑不再集中在几个大型的类上,而是在大量相对小的领域对象上,这些类具有自己的状态和行为,每个类都是完成的独立的,并与现实领域的业务对象形成一种映射。基于DDD的架构设计,保证了系统的可维护性,扩展性和敏捷性,在处理复杂业务逻辑方面有着明显的优势!

在DDD设计中,系统分为UserInterface->Application->Domain->Infrastructure,每一层都独立的职责,UserInterFace也就是所谓的UI层,负责页面展示;Application层是很薄的一层,对外为展现层提供各种应用功能(包括查询或命令),对内调用领域层(领域对象或领域服务)完成各种业务逻辑,应用层不包含业务逻辑。Domain是领域层,负责主要的业务逻辑,这一层是业务的核心。Infrastructure是基础设施层,主要为其他层提供通用的技术支持,为领域层实现持久化机制;

领域层是业务的核心层,有几个概念需要阐述下;

  • 实体(Entity)

    实体就是领域中需要唯一标识的领域概念。因为我们有时需要区分是哪个实体。有两个实体,如果唯一标识不一样,那么即便实体的其他所有属性都一样,我们也认为他们两个不同的实体;因为实体有生命周期,实体从被创建后可能会被持久化到数据库,然后某个时候又会被取出来。所以,如果我们不为实体定义一种可以唯一区分的标识,那我们就无法区分到底是这个实体还是哪个实体。另外,不应该给实体定义太多的属性或行为,而应该寻找关联,发现其他一些实体或值对象,将属性或行为转移到其他关联的实体或值对象上。
  • 值对象(Value Object)

    实在领域中,并不是没一个事物都必须有一个唯一标识,也就是说我们不关心对象是哪个,而只关心对象是什么。,如果两个对象的所有的属性的值都相同我们会认为它们是同一个对象的话,那么我们就可以把这种对象设计为值对象。因此,值对象没有唯一标识,这是它和实体的最大不同。另外值对象在判断是否是同一个对象时是通过它们的所有属性是否相同,如果相同则认为是同一个值对象;而我们在区分是否是同一个实体时,只看实体的唯一标识是否相同,而不管实体的属性是否相同;值对象另外一个明显的特征是不可变,即所有属性都是只读的。因为属性是只读的,所以可以被安全的共享;
  • 领域服务(Domain Service)

    领域中的一些概念不太适合建模为对象,即归类到实体对象或值对象,因为它们本质上就是一些操作,一些动作,而不是事物。这些操作或动作往往会涉及到多个领域对象,并且需要协调这些领域对象共同完成这个操作或动作。如果强行将这些操作职责分配给任何一个对象,则被分配的对象就是承担一些不该承担的职责,从而会导致对象的职责不明确很混乱。但是基于类的面向对象语言规定任何属性或行为都必须放在对象里面。所以我们需要寻找一种新的模式来表示这种跨多个对象的操作,DDD认为服务是一个很自然的范式用来对应这种跨多个对象的操作,所以就有了领域服务这个模式。

    领域服务还有一个很重要的功能就是可以避免领域逻辑泄露到应用层。因为如果没有领域服务,那么应用层会直接调用领域对象完成本该是属于领域服务该做的操作,这样一来,领域层可能会把一部分领域知识泄露到应用层。

  • 工厂(Factory)

    DDD中的工厂也是一种体现封装思想的模式。DDD中引入工厂模式的原因是:有时创建一个领域对象是一件比较复杂的事情,不仅仅是简单的new操作。正如对象封装了内部实现一样(我们无需知道对象的内部实现就可以使用对象的行为),工厂则是用来封装创建一个复杂对象尤其是聚合时所需的知识,工厂的作用是将创建对象的细节隐藏起来。客户传递给工厂一些简单的参数,然后工厂可以在内部创建出一个复杂的领域对象然后返回给客户。目前渐渐通过IOC替代,常用的IOC组件有Unity、StructureMap等
  • 仓储(Repository)

    仓储被设计出来的目的是基于这个原因:领域模型中的对象自从被创建出来后不会一直留在内存中活动的,当它不活动时会被持久化到数据库中,然后当需要的时候我们会重建该对象;重建对象就是根据数据库中已存储的对象的状态重新创建对象的过程;所以,可见重建对象是一个和数据库打交道的过程。从更广义的角度来理解,我们经常会像集合一样从某个类似集合的地方根据某个条件获取一个或一些对象,往集合中添加对象或移除对象。也就是说,我们需要提供一种机制,可以提供类似集合的接口来帮助我们管理对象。仓储就是基于这样的思想被设计出来的;

    仓储里面存放的对象一定是聚合,原因是之前提到的领域模型中是以聚合的概念去划分边界的;仓储还有一个重要的特征就是分为仓储定义部分和仓储实现部分,在领域模型中我们定义仓储的接口,而在基础设施层实现具体的仓储。

     

关于DDD的一些思考

1、聚合根尽量要小,封装了聚合根内部的所有操作;外部必须通过聚合根才能操作聚合根内部的实体;
2、多个聚合根协调完成一项工作,通常采用的处理方式有两种:领域服务和领域事件

1>、领域服务将多个聚合根整合在一起协调处理完成相应的业务。

2>、领域事件通过订阅发布的形式完成多个聚合根的协同工作,事件异步通讯框架EQueue、nservicebus;

3、Repository是聚合根的仓储,用于储存聚合根的数据;IRepository的定义放在领域Domain,Repository的实现放在基础设施层,这样就可以做到领域不依赖基础设施层,而仅仅依赖接口;Repository一般包含CRUD的操作,领域层通过Repository仅仅获取数据,返回最新聚合根。而应用层却通过Repository来持久化数据到DB;数据持久化的组件也有很多:EF、NHibernate、Dapper;
4、一个聚合根的Update流程:

1>、应用层通过仓储获取领域层相应的聚合根;

2>、调用聚合根内部的方法来更新聚合根到最新状态,返回最新聚合根到应用层;

3>、应用层利用仓储更到DB;

备注:当然上述是简单流程,视情况而定,有时候,我们会调用聚合根内部的方法来Rasie一个领域事件,让相应的EventHandler来处数据

参考文章:

http://www.cnblogs.com/netfocus/archive/2011/10/10/2204949.html

http://www.cnblogs.com/jesse2013/p/the-first-glance-of-ddd.html

DDD的思考的更多相关文章

  1. 领域驱动设计(DDD)实践之路(一)

    本文首发于 vivo互联网技术 微信公众号 链接: https://mp.weixin.qq.com/s/gk-Hb84Dt7JqBRVkMqM7Eg  作者:张文博 领域驱动设计(Domain Dr ...

  2. Repository 仓储,你的归宿究竟在哪?(一)-仓储的概念

    写在前面 写这篇博文的灵感来自<如何开始DDD(完)>,很感谢young.han兄这几天的坚持,陆陆续续写了几篇有关于领域驱动设计的博文,让园中再次刮了一阵"DDD探讨风&quo ...

  3. Repository 仓储,你的归宿究竟在哪?(上)

    Repository 仓储,你的归宿究竟在哪?(上) 写在前面 写这篇博文的灵感来自<如何开始DDD(完)>,很感谢young.han兄这几天的坚持,陆陆续续写了几篇有关于领域驱动设计的博 ...

  4. 关于领域驱动设计(DDD)中聚合设计的一些思考

    关于DDD的理论知识总结,可参考这篇文章. DDD社区官网上一篇关于聚合设计的几个原则的简单讨论: 文章地址:http://dddcommunity.org/library/vernon_2011/, ...

  5. DDD实践问题之 - 关于论坛的帖子回复统计信息的更新的思考

    之前,在用ENode开发forum案例时,遇到了关于如何实现论坛帖子的回复的统计信息如何更新的问题.后来找到了自己认为比较合理的解决方案,分享给大家.也希望能和大家交流,擦出更多的火花. 论坛核心领域 ...

  6. DDD 领域驱动设计-三个问题思考实体和值对象(续)

    上一篇:DDD 领域驱动设计-三个问题思考实体和值对象 说实话,整理现在这一篇博文的想法,在上一篇发布出来的时候就有了,但到现在才动起笔来,而且写之前又反复读了上一篇博文的内容及评论,然后去收集资料, ...

  7. (DDD)仓储的思考

    (DDD)仓储的思考 为什么需要仓储呢?领域对象(一般是聚合根)的被创建出来后的到最后持久化到数据库都需要跟数据库打交道,这样我们就需要一个类似数据库访问层的东西来管理领域对象.那是不是我们就可以设计 ...

  8. 对结合BDD进行DDD开发的一点思考和整理

    引言 二十年前的我,还在学校里抱着一台DIY机(德州486+大众主板+16M内存+3.5inch软驱+昆腾320M硬盘,当时全校最快主机没有之一),揣着一本<Undocumented DOS&g ...

  9. 领域驱动设计(DDD)的实践经验分享之ORM的思考

    原文:领域驱动设计(DDD)的实践经验分享之ORM的思考 最近一直对DDD(Domain Driven Design)很感兴趣,于是去网上找了一些文章来看看,发现它确实是个好东西.于是我去买了两本关于 ...

随机推荐

  1. am335x sd卡启动系统参数设置

    首先直接记录结果 在u-boot 中修改参数 #define AUTO_UPDATESYS */ 直接把这个参数注释掉. 这个参数是原来用来升级nor flash 启动系统设置的一个参数,也就是说, ...

  2. 读书笔记-JVM

    局部变量表(虚拟机栈中的一部分)在编译期完成分配,运行期不会再改变大小: 每个方法对应一个栈帧(存储局部变量表.操作数栈.动态链接.方法出口等),栈帧被存储到虚拟机栈中,每个线程对应一个虚拟机栈,方法 ...

  3. flask路由和视图和cookie

    什么是路由 """ 客户端(例如web浏览器)把请求发送给Web服务器,Web服务器再把请求发送给Flask程序实例. 程序实例需要知道对每个URL请求运行那些代码,所以 ...

  4. IntelliJ IDEA License Server本地搭建教程

    Licence地址直接填入 http://idea.qinxi1992.cn/ http://jetbrains.tencent.click 直接破解 本地教程: 2016年3月20日更新支持自定义端 ...

  5. SQL 执行计划(二)

    最近总想整理下对MSSQL的一些理解与感悟,却一直没有心思和时间写,晚上无事便写了一篇探索MSSQL执行计划,本文讲执行计划但不仅限于讲执行计划. 网上的SQL优化的文章实在是很多,说实在的,我也曾经 ...

  6. Post方法调用公司发Mail的接口

    调用公司发Mail的接口. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http ...

  7. Factor Combinations

    Factor Combinations Problem: Numbers can be regarded as product of its factors. For example, 8 = 2 x ...

  8. 通过代理连接go01ge

     日本:https://pac.mcplay.cn/jp.pac台湾:https://pac.mcplay.cn/tw.pac如果想上Google可以试试简单的方法,在ie的代理自动配置脚本设置这个p ...

  9. linux下的防火墙iptables

    防火墙(firewall),也称为防护墙,是由Check Point创立者Gil Shwed于1993年发明并引入国际互联网.它是一项信息安全的防护系统,依照特定的规则,允许或者是限制传输的数据通过. ...

  10. 基础03 JVM到底在哪里?

    1.Java是编译型语言还是解释型语言? 是解释型定义: 编译型语言:把做好的源程序全部编译成二进制代码的可运行程序.然后,可直接运行这个程序. 解释型语言:把做好的源程序翻译一句,然后执行一句,直至 ...