DDD概览
2023-07-19 15:39:16 11 举报
AI智能生成
DDD-领域驱动设计,整体概览
作者其他创作
大纲/内容
两个阶段
确定领域模型
以一种领域专家、设计人员、开发人员都能理解的“通用语言”作为相互交流的工具
在不断交流的过程中发现和挖出一些主要的领域概念,然后将这些概念设计成一个领域模型;
由领域模型驱动软件设计
用代码来表现该领域模型
领域需求的最初细节,在功能层面通过领域专家的讨论得出。
八大特点
领域模型是对具有某个边界的领域的一个抽象
反映了领域内用户业务需求的本质。
领域模型是有边界的,只反应了我们在领域内所关注的部分
领域模型只反映业务,和任何技术实现无关
领域模型不仅能反映领域中的一些实体概念,如货物,书本,应聘记录,地址
还能反映领域中的一些过程概念,如资金转账等
领域模型确保了业务聚焦
软件的业务逻辑都在一个模型中,都在一个地方
这样对提高软件的可维护性,业务可理解性以及可重用性方面都有很好的帮助
领域模型贯穿软件分析、设计,以及开发的整个过程
领域专家、设计人员、开发人员通过领域模型进行交流,彼此共享知识与信息。
因为大家面向的都是同一个模型,所以可以防止需求走样,可以让软件设计开发人员做出来的软件真正满足需求;
领域模型能够帮助开发人员相对平滑地将领域知识转化为软件构造
领域建设是个持续的过程
要建立正确的领域模型并不简单,需要领域专家、设计、开发人员积极沟通共同努力
然后才能使大家对领域的认识不断深入,从而不断细化和完善领域模型
领域模型是整个软件的核心
是软件中最有价值和最具竞争力的部分
设计足够精良且符合业务需求的领域模型能够更快速的响应需求变化
八个概念
实体(entity)
一个由它的标识定义的对象叫做实体”
通常实体具备唯一id,能够被持久化,具有业务逻辑,对应现实世界业务对象。
实体一般和主要的业务/领域对象有一个直接的关系。
实体不等于ORM中存储的实体,两者不是同一个概念
值对象(value object)
描述事物的对象;一个没有概念上的标识符只是用来描述一个领域方面的对象。
这些对象是用来表示临时的事物,或者可以认为值对象是实体的属性,这些属性没有特性标识但同时表达了领域中某类含义的概念。
与实体区别
实体具有唯一标识,而值对象没有唯一标识
值对象另外一个明显的特征是不可变,即所有属性都是只读的
聚合及聚合根(aggregate、aggregate root)
聚合(aggregate)
聚合是用来定义领域对象所有权和边界的领域模式
聚合的作用是帮助简化模型对象间的关系。
聚合通过定义对象之间清晰的所属关系和边界来实现领域模型的内聚,并避免了错综复杂的难以维护的对象关系网的形成
聚合定义了一组具有内聚关系的相关对象的集合,可以把聚合看作是一个修改数据的单元。
通常把聚合组织到一个文件夹或一个包中。每一个聚集对应一个包,并且每个聚集成员包括实体、值对象,domain事件,仓储接口和其它工厂对象。
聚合根(aggregate root)
一个聚合是一组相关的被视为整体的对象。每个聚合都有一个根对象(聚合根实体),从外部访问只能通过这个对象。
根实体对象有组成聚合所有对象的引用,但是外部对象只能引用根对象实体。
只有聚合根才能使用仓储库直接查询,其它的只能通过相关的聚合访问。
如果根实体被删除,聚合内部的其它对象也将被删除。
特点
每个聚合有一个根和一个边界,边界定义了一个聚合内部有哪些实体或值对象,根是聚合内的某个实体;
聚合内部的对象之间可以相互引用,但是聚合外部如果要访问聚合内部的对象时,必须通过聚合根开始导航,绝对不能绕过聚合根直接访问聚合内的对象,也就是说聚合根是外部可以保持对它的引用的唯一元素;
聚合内除根以外的其他实体的唯一标识都是本地标识,也就是只要在聚合内部保持唯一即可,因为它们总是从属于这个聚合的;
聚合根负责与外部其他对象打交道并维护自己内部的业务规则;
基于聚合的以上概念,我们可以推论出从数据库查询时的单元也是以聚合为一个单元,也就是说我们不能直接查询聚合内部的某个非根的对象;
聚合内部的对象可以保持对其他聚合根的引用;
删除一个聚合根时必须同时删除该聚合内的所有相关对象,因为他们都同属于一个聚合,是一个完整的概念。
工厂(factories)
工厂用来封装创建一个复杂对象尤其是聚合时所需的知识,作用是将创建对象的细节隐藏起来。
客户传递给工厂一些简单的参数,然后工厂可以在内部创建出一个复杂的领域对象然后返回给客户。
仓储(repositories)
仓储是用来管理实体的集合
仓储里面存放的对象一定是聚合,原因是domain是以聚合的概念来划分边界的。我们只对聚合设计仓储
仓储分为仓储定义部分和仓储实现部分
在领域模型中定义仓储的接口
在基础设施层实现具体的仓储
respositories和dao
dao是面向数据访问的,是关系型数据库和应用之间的契约
repository:位于领域层,面向aggregation root
repository是一个独立的抽象,使用领域的通用语言,它与dao进行交互,并使用领域理解的语言提供对领域模型的数据访问服务的“业务接口”。
dao方法是细粒度的,更接近数据库,而repository方法的粒度粗一些,而且更接近领域。领域对象应该只依赖于repository接口。客户端应该始终调用领域对象,领域对象再调用dao将数据持久化到数据 存储中。
处理领域对象之间的依赖关系,通 常的设计方案是让服务类或外观类直接调用repository,在调用repository的时候返回实体对象给客户端。
服务(services)
服务提供的操作是它提供给使用它的客户端,并突出领域对象的关系
service只负责协调并委派业务逻辑给领域对象进行处理,其本身并真正实现业务逻辑,绝大部分的业务逻辑都由领域对象承载和实现了。
service可与多种组件进行交互,这些组件包括:其他的service、领域对象和repository 或 dao。
应用中一般包括:domain模型服务和应用层服务
领域服务逻辑须以非常干净简洁的代码实现。
3个特征
a. 服务执行的操作涉及一个领域概念,这个领域概念通常不属于一个实体或者值对象
b. 被执行的操作涉及到领域中其它的对象
c. 操作时无状态的
domain事件
企业级应用程序事件
:系统事件
应用事件
领域事件
领域事件
触发点在领域模型(domain model)中
将领域对象从对repository或service的依赖中解脱出来,避免让领域对象对这些设施产生直接依赖
做法就是当领域对象的业务方法需要依赖到这些对象时就发出一个事件,这个事件会被相应的对象监听到并做出处理。
通过使用领域事件,我们可以实现领域模型对象状态的异步更新、外部系统接口的委托调用,以及通过事件派发机制实现系统集成。另外,领域事件本身具有自描述性。它不仅能够表述系统发生了什么事情,而且还能够描述发生事件的动机。
domain事件也用表进行存储。
DTO(dto- datatransfer object(数据传输对象))
how
开发步骤
根据需求建立一个初步的领域模型
识别出一些明显的领域概念以及它们的关联,关联可以暂时没有方向但需要有(1:1,1:n,m:n)这些关系;可以用文字精确的没有歧义的描述出每个领域概念的涵义以及包含的主要信息;
分析主要的软件应用程序功能
识别出主要的应用层的类;这样有助于及早发现哪些是应用层的职责,哪些是领域层的职责;
分析领域模型
识别出哪些是实体,哪些是值对象,哪些是领域服务;
分析关联
通过对业务的更深入分析以及各种软件设计原则及性能方面的权衡,明确关联的方向或者去掉一些不需要的关联
找出聚合边界及聚合根
这是一件很有难度的事情;因为你在分析的过程中往往会碰到很多模棱两可的难以清晰判断的选择问题,所以,需要我们平时一些分析经验的积累才能找出正确的聚合根
为聚合根配备仓储
一般情况下是为一个聚合分配一个仓储,此时只要设计好仓储的接口即可
走查场景
确定我们设计的领域模型能够有效地解决业务需求;
创建领域实体或值对象
通过工厂还是直接通过构造函数;
持续重构
寻找模型中觉得有些疑问或者是蹩脚的地方,持续重构
领域驱动架构 VS N层架构设计
领域驱动架构
整体架构
分支主题
各层定义
user interface
该层包含与其他系统/客户进行交互的接口与通信设施
三类组件
dto
主要是以粗粒度的数据结构减少网络通信并简化调用接口
assembler
dto与领域对象之间的相互转换工作
facade
用意在于为远程客户端提供粗粒度的调用接口。
facade本身不处理任何的业务逻辑
主要工作就是将一个用户请求委派给一个或多个service进行处理,同时借助assembler将service传入或传出的领域对象转化为dto进行传输。
application
service
service的组织粒度和接口设计依据与传统transaction script风格的service是一致的,但是两者的实现却有质的区别
transaction script
核心是过程
面向过程设计
通过过程的调用来组织业务逻辑
业务逻辑在服务(service)层进行处理
事务简单,导致业务代码负责,应用架构容易出现“胖服务层”和“贫血的领域模型”。同时,service层积聚越来越多的业务逻辑,导致可维护性和扩展性变差
domain
维护一个使用面向对象技术实现的领域模型,几乎全部的业务逻辑会在该层实现
包含entity、valueobject、domain event和repository等多种重要的领域组件。
infrastructure
为interfaces、application和domain三层提供支撑
所有与具体平台、框架相关的实现会在infrastructure中提供
n层架构设计
层(layers)被视为构成应用或服务的水平堆叠的一组逻辑上的组件
提供一个最大化复用和可维护性的设计
每个解决方案的组件必须分隔到不同的层
每层的组件必须内聚而且有大约相同的抽象级别
每个一级层应该和其他的一级层松耦合。
0 条评论
下一页