主要是在开发过程当中,我的对于领域驱动设计的实践感悟和总结;也是对新进开发人员的培训资料;但愿对关注DDD的童鞋有所帮助。数据库
领域驱动不是纯粹的技术问题,领域建模(创建数据表只是一部分)是领域专家(客户/产品团队)和开发人员沟通努力、抽象的的结果。后端
领域建模的目的是,通过有效的沟通、详细分析、 良好设计能够更好的适应将来的变化。架构
领域驱动设计的核心是创建正确的领域模型。app
后端开发人员、产品人员框架
领域驱动设计是什么?dom
领域驱动设计的核心是创建正确的领域模型,正确的反应业务,并适应变化。设计
为何创建一个领域模型是重要的对象
(1). 领域模型是具备边界的领域抽象,反映了领域业务需求的本质,边界指只领域内所关注的部分;blog
(2). 领域模型只反映业务,和任何技术实现无关, 包括实体概念(如商品)和过程概念(资金转帐);接口
(3).领域模型确保业务逻辑内聚在一个模型中,帮助可理解和重用;
(4). 领域模型帮助开发人员平滑转换为软件构造;
(5).领域模型贯穿软件分析设计开发整个过程,领域专家、设计、开发人员始终保持沟通,共享信息,确保软件真正知足需求;
(6).创建正确的领域模型并不简单,须要领域专家、设计、开发人员积极沟通共同努力,而后才能使你们对领域(业务需求)的认识不断深刻,从而不断细化和完善领域模型;
(7).领域模型是整个软件的核心,是最有价值和最具竞争力的部分;设计足够精良且符合业务需求的领域模型可以更快速的响应需求变化;
领域建模时思考问题的角度
在PC页面、APP界面、WebAPI接口展现数据;
发送命令给应用层要求其执行某个用户命令;
定义系统要完成的全部任务,对用户界面层提供应用功能。对内调用领域层(领域对象或领域服务)完成业务逻辑,应用层不包含业务逻辑。
负责表达业务概念,业务状态信息以及业务规则,领域模型处于这一层,是业务软件的核心。
限界上下文是个高内聚的领域模型(例订单模块),是将来系统作水平拆分的关键,能够说就是将一个限界上下文模型拆分升级为一个子系统。
开发人员能够简单理解,限界上下文能够转换成代码,放在一个高内聚的dll项目;
聚合,它经过定义对象之间清晰的所属关系和边界来实现领域模型的内聚,并避免了错综复杂的难以维护的对象关系网的造成。聚合定义了一组具备内聚关系的相关对象的集合,咱们把聚合看做是一个修改数据的单元。
(1). 每一个聚合有一个根和一个边界,边界定义了一个聚合内部有哪些实体或值对象,根是聚合内的某个实体;
(2). 聚合内部的对象之间能够相互引用,可是聚合外部若是要访问聚合内部的对象时,必须经过聚合根开始导航,绝对不能绕过聚合根直接访问聚合内的对象,也就是说聚合根是外部能够保持 对它的引用的惟一元素;
(3). 聚合内除根之外的其余实体的惟一标识都是本地标识,也就是只要在聚合内部保持惟一便可,由于它们老是从属于这个聚合的;
(4). 聚合根负责与外部其余对象打交道并维护本身内部的业务规则;
(5). 基于聚合的以上概念,咱们能够推论出从数据库查询时的单元也是以聚合为一个单元,也就是说咱们不能直接查询聚合内部的某个非根的对象;
(6). 聚合内部的对象能够保持对其余聚合根的引用;
删除一个聚合根时必须同时删除该聚合内的全部相关对象,由于他们都同属于一个聚合,是一个完整的概念;
我以为咱们能够先从业务的角度深刻思考,而后慢慢分析出有哪些对象是:
有独立存在的意义,即它是不依赖于其余对象的存在它才有意义的;
能够被独立访问的,仍是必须经过某个其余对象导航获得的;
若是一个聚合只有一个实体,那么这个实体就是聚合根;若是有多个实体,那么咱们能够思考聚合内哪一个对象有独立存在的意义而且能够和外部直接进行交互。
不能独立存在的业务对象,必须挂在聚合根上。
定义:在领域中,不须要惟一键标识的对象,包括:
常见的值对象:
字符串常量;
枚举;
无主键约束的引用对象;
若是有两个Customer的地址信息是同样的,咱们就会认为这两个Customer的地址是同一个。也就是说只要地址信息同样,咱们就认为是同一个地址Address。
领域中的一些概念不太适合建模为对象,即归类到实体对象或值对象,由于它们本质上就是一些操做,一些动做,而不是事物。这些操做或动做每每会涉及到多个领域对象。
领域服务一个很重要的功能就是能够避免领域逻辑泄露到应用层。
容易下降耦合,方便作到高扩展性;
领域聚合根之间很难作到强一致性,大多数都是最终一致性;
本层为其余层提供通用的技术能力;提供了层间的通讯;为领域层实现持久化机制;总之,基础设施层能够经过架构和框架来支持其余层的技术需求;
开发人员/团队须要和产品团队/客户保持充分的沟通。