DDD聚合与 领域服务
2023-12-28 16:41:20 8 举报
AI智能生成
领域驱动设计(DDD)中的聚合和领域服务是两个重要概念。聚合是一个具有一致性业务规则的一组对象,它对外提供统一的接口。聚合根是聚合中的唯一入口,它负责协调聚合内其他对象的操作。领域服务是一种封装了通用业务逻辑的服务,它不属于任何实体或值对象,可以跨越多个聚合。领域服务通常用于处理跨聚合的业务逻辑,或者实现一些与实体或值对象无关的功能。总之,聚合和领域服务都是 DDD 中用于实现高内聚、低耦合、可重用代码的重要手段。
作者其他创作
大纲/内容
实体
为什么需要实体:用于个性特征或区分不同的对象,一般表示E-R图中的实体类型。在DDD中,实体充当了业务模型的属性、行为方法的容器,是业务内聚、避免贫血模型的唯一的实例化的类对象
实体的重要特性:唯一标识
用户提供、程序生成UUID、另外的界限上下文生成、持久化机制
唯一标识具有稳定性,一旦生成不可更改,可通过setter方法隐藏或保护起来的方式保证不会被更新。并且在分布式系统中需要唯一标识
实体唯一标识的生
成方式(分布式ID)
生成要求:全局唯一性、趋势递增(B+树保证写入性能)、单调递增、信息安全(避免ID连续)、高可用性和低延迟
UUID生成方法:36位字符展示(8-4-4-4-12,前3段由时间戳+UUID版本生成,第四段是时钟序列,第五段是MAC地址或随机生成的),本地生成,性能高,没有网络消耗。缺点在于不具备可读性、信息不安全、不适于DB的自动递增
雪花算法:64位的Long类型唯一ID,由高1位+41位时间戳(69年)+10位机器码+12位序号(毫秒级时间戳)组成,趋势递增、不依赖第三方系统单独部署稳定。缺点是要防止时钟回拨(保存上一次生成的最大时间,生成后进行比较后再次生成)
数据库生成:利用数据库的主键递增机制,成本小,实现简单,ID单调递增,缺点是发号器限制在了单台MySQL机器的读写性能
美团LEAF
号段模式:通过设计包含业务标识、当前最大ID、步长等关键字段组成数据库表,通过update set 最大ID = 最大ID+步长,更新成功代表得到了号段,这一部分号段缓存到内存当中,用完再去取(未避免取号等待,可采用双buffer方式:号段消耗一定的比例就异步取号)的方式实现。优点是趋势递增、容灾性高、号码不随机
雪花算法模式:解决趋势递增的问题,10位机器码通过zookeeper注册的方式进行配置。方案为启动服务时向zk进行注册并返回机器ID,本地缓存机器ID(保证对zk的弱引用)
实体的要素
1、关键的属性,如name、password、其余的值对象等
2、关键的行为,能明确表达操作的意图。不要通过setter方式完成避免产生歧义。满足完成创建即一致(属性存在性、稳定性)原则,采用规约模式实现属性验证(正确性、长度,为保证属性的可验证性,属性在必要条件下也需要设置成值对象类型)等
3、事件溯源机制(参考DDD架构中的CQRS)
值对象
值对象是描述和度量事务的重要容器,应当避免使用实体而应该使用值对象,值对象非常方便的进行测试、维护、使用,可简化设计
值对象非常方便进行创建和传递,用完即可销毁。当我们只关心某个对象的属性时,便可赋予相关的属性和行为作为一个值对象。值对象不需要有任何身份标识,尽量避免实例的复杂性
特征
度量或描述领域对象
作为不可变量:值对象初始化后,任何方法都不可对这个对象的属性状态进行更改
不同的相关属性组成概念整体:可处理单个或级联属性,表达了一种属性联合的概念
度量和描述发生改变时,可用另外一个值对象替换:保障无副作用性,需要进行整体替换。如String、Bigdecimal等java对象都使用了该思想
可与其它值对象进行相等性比较
不会对协作的对象造成副作用:只用于产生输出,而不会修改对象的状态成为无副作用函数。值对象的所有方法都必须是无副作用函数
当模型概念从不同的界限上下文中进行流动的同事,尽量使用值对象表示这些概念。好处是可以达到最小化集成,方便管理职责的属性数目,减少职责假设
聚合
由紧密关联的实体和值对象组合而成,协同操作实体和值对象,确保这些领域对象实现共同的业务逻辑时保障数据的一致性。
聚合是数据修改和持久化的基本单元,每个聚合对应一个仓储服务,实现数据的持久化
主要目的:避免由于复杂的数据模型缺少统一的业务规则控制,导致聚合、实体之间的数据不一致的问题,协调实体和值对象按照特定的规则控制完成业务逻辑。聚合之间以聚合根ID的方式接受外部请求,通过ID关联引用。外部对象必须通过聚合根才能访问聚合内部的实体
设计原则
1、一致性边界内不变性。聚合内部具有一套不变的业务规则(行为),各个实体和值对象安全统一的规则运行,实现数据的一致性修改,边界之外的任何对象都与聚合无关。这是聚合实现业务高内聚的原因
2、尽量设计小聚合。过大的聚合会导致对象的管理复杂性提升,出现并发冲突或DB乐观锁冲突,降低系统的可用性。小聚合能减少业务过大导致聚合重构的可能性,让领域模型更加适应业务变化
3、通过唯一ID引用其它聚合,而不能使用对象引用。否则会导致聚合边界不清晰、增加聚合之间的耦合度
4、单个聚合内部数据强一致性,边界之外的聚合最终一致性。一次事务只能修改一个聚合的状态,如若涉及到多个聚合,应当使用领域事件的方式进行(异步MQ),实现聚合的解耦。(这个原则可以实际应用中可打破)
领域服务
当某个操作不适合放在聚合或值对象的时候,便是使用领域服务,可存在单个原子操作处理多个领域对象。一般来说,1、执行一个显著的业务操作过程;2、对领域对象进行转换;3、多个领域对象作为输入进行计算,产生一个值对象 这三种情况的实现在领域服务中
使用领域服务应当避免产生贫血模型:即所有的业务逻辑都位于领域服务中,而不是实体或值对象中的现象
领域服务为什么是无状态的:领域服务是协调领域对象外层某个操作而处理实现处理业务逻辑功能的,本身是一个行为,所以是无状态的。状态应该由领域对象保存
0 条评论
下一页