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