领域驱动设计简介
单一职责原则
点击查看详情
两顶帽子
: 为了实现新的功能,我们在原有代码的基础上,在不添加新功能的前提下调整原有程序结构,我们抽取出了 Strategy 这样一个接口和“不折扣”这个实现类;这时,原有程序变了吗?没有。但是程序结构却变了,增加了这样一个接口,称之为“可扩展点”。在这个可扩展点的基础上再实现各种折扣,既能满足“开放-封闭原则”来保证程序质量,又能够满足新的需求。当日后发生新的变更时,什么类型的折扣有变化就修改哪个实现类,添加新的折扣类型就增加新的实现类,维护成本得到降低
-
例如我们的初始需求如下
-
第一次需求变更为商品则扣
-
因为需要在付款这个方法中实现折扣,那么就需要分析付款与折扣的关系,付款发生改变时,折扣是否会发生改变,折扣发生改变时,付款是否会发生改变;简单理解就是,调用付款这个方法,给蔬菜付款或者给水果付款,它们的折扣是否会发生改变,答案是不会(付款的金额变化,折扣还是原来的则扣逻辑;折扣变化,需要进行折扣的付款金额还是原来的金额),
折扣不会随着付款的改变而改变
,付款也同样会发生改变;通过分析,付款和折扣是两个不同的事件,那么就不能写在同一个方法中,或者说不能写在同一个类中 -
另外在折扣中又分为限时折扣、限量折扣等,同过分析限时折扣与付款的关系,分析限量折扣与付款的关系;可以写一个接口编写不同的折扣方法,在实现类中实现折扣方法
-
同样第二次需求变更增加会员
-
第三次变更增加支付
数据库设计
点击查看详情
-
关系型数据库
-
在面向对象的开发中:根据需求文档,进行用例设计,根据用例设计领域模型,以领域模型作为核心进行数据库设计和程序设计
-
一对一的关系:一个过错行为对应一个申辩申请单,可将过错行为表的主键作为申辩申请单的外键,并将该字段升级为该表的主键
-
多对一的关系:平时我们查询通常是join关联查询,不过这么做查询性能差,解决方案是:先查询过错行为表,再根据外键查询关联的表
-
一对多的关系
-
多对多的关系
-
继承方案一:将所有字段写在一张表
-
继承方案二:将相同的字段提取出来,不同的字段作为一张表,
不同字段的表
的主键作为相同字段的表
的外键
-
继承方案三:将相同字段的表作为父类,不同字段的表作为子类
点击查看详情
-
非关系型数据库
-
将需要连接查询的数据在写入数据库前先进行join操作,查询的时候直接查询即可
领域模型
点击查看详情
-
服务
-
实体:例如某个实体类,它的属性可能随着时间不断变化,例如用户实体类:属性可以是name,也可以是username
-
值对象:例如真实世界中不会改变的地名等
-
区分:值对象,例如圆形是一种形状,红色是一种颜色,形状和颜色就是值对象,不会改变
-
贫血模型
-
充血模型
聚合
点击查看详情
-
聚合体现的是整体与部分的关系,当整体不存在时,部分也就没有意义了
-
如何判断是否是聚合关系,例如饭店和菜单,账单和账单明细,当饭店不存在时,菜单也就没有意义了,账单不存在时,账单明细也就没有意义了,这种依存关系就是聚合
-
饭店和菜单也可以设计成不是聚合关系,当饭店删除时,菜单依然存在,
-
整体则作为聚合根,是外部访问
部分
的唯一入口;当聚合内部发生改变时,与聚合外部无关 -
账单与账单明细的聚合案例
-
在只有crud是适合采用聚合,而在统计汇总时则直接使用sql查询即可
-
聚合的设计实现,通过
仓库
来实现对数据库的访问
-
在工厂中装配仓库所需的对象,之后返回给仓库
界限上下文
点击查看详情
-
问题子域
-
限界上下文
事件风暴
点击查看详情
- 参考
事件风暴会议
:提前邀请Project的所有相关人(包括开发,测试,产品,业务分析,UI/UX等),一起讨论事件Event
:已经发生的事实,如用户已注册,用户已登录,用户已发送等决策命令Command
:产生这个事实的的动作,如注册用户、登录用户、发送信息发起命令的参与者User/Actor
:如用户1在注册账号,用户2在登陆账号读模型Read Model
:某个Actor做出决策命令Command的前提是需要看到某些信息,如发送信息时需要看到对方的信息
聚合Aggregate
:某个Actor在某个聚合调用某种Command产生了某个Event,也就是整个流程结束外部系统External System和规则Policy
:Event不一定由前面所说的某个Actor触发Command而产生,也可能是由外部系统或者某种规则自动触发Command而产生
- 例如
用户选餐
是否是一个领域事件,答案是否
,因为用户选餐只是一个查询操作,并没有数据保存到数据库中;在ddd中查询操作则采用其他方式
微服务拆分
点击查看详情
-
微服务间高内聚低耦合
:例如用户下单
的微服务要查询用户信息,并不是直接查询,而是调用用户注册
这个微服务的接口,同样也不是直接调用,而是去注册中心调用名称叫用户注册
的微服务的接口 -
主题域和拆分域
:在用户下单这个问题域中,用户信息来源于用户注册这个限界上下文,菜单信息来源于饭店管理这个限界上下文,那么用户下单作为主题域,用户注册和饭店管理作为支撑域
-
同样在饭店接单这个问题域中,用户信息来源于用户注册上下文,订单信息来源于用户下单上下文
-
在用户下单上下文中下单成功后,饭店接单上下文如何知道用户下单了呢,需要通过
消息队列
将用户下单的消息发送给饭店接单上下文
-
数据库设计参考
-
落实到微服务设计 -> 落实到数据库设计 -> 落实到贫血模型与充血模型的设计
-
如何跟踪订单状态,同样是使用消息队列的方式,将消息传递给下一个微服务
-
例如多个团队开发微服务,其他团队要求你提供接口时,应该怎么做
-
当其他团队要求你变更接口,为了不影响其他业务,应该在要变更接口的基础上修改,若实在要新增一个接口才去新增
-
防腐层
:一个上下文通过一些适配和转换与另一个上下文交互
-
例如feigen接口就是防腐层
-
NewSQL
:就是在传统关系型数据库上集成了 noSQL 强大的可扩展性 -
数据库选择
整洁架构
点击查看详情
-
技术中台
-
例如在以往的架构中我们使用hibernate2进行开发,后来我们又需要用hibernate3进行升级,但是hibernate2与业务代码高度耦合,这时重构系统就非常麻烦,解决方案就是将hibernate2独立出来,并为它写一个实现类,我们使用实现类的方法即可,之后进行系统升级的时候,只需为hibernate3写一个实现类;这样的重构方式就能将影响降到最低
-
核心
:将底层架构与业务代码解耦
-
主动适配器又称北向适配器,用户通过浏览器等不同方式发送请求,通过北向适配器调用应用层,被动适配器又称南向适配器,即业务领域层完成业务处理后,将数据持久化到数据库
中台
点击查看详情
- 什么是中台
-
如何提升团队交付产品的速度:将产品拆分成一个个微服务,不同的团队开发不同的微服务,每个团队负责各自的微服务,从开发到部署和维护
-
这个开发方式就是大前端+技术中台
-
大前端
-
这就需要团队中的每个成员都懂前端、后端、数据库、大数据等,但这样显然是不可能的;这个问题该怎么解决呢?那就由专门的底层架构团队来编写
技术中台
,其他开发团队则将更多的精力投入到业务中去
-
技术中台搭建
-
简易技术中台
实现技术中台
点击查看详情
-
所有增删改操作采用领域驱动设计,查询操作直接采用sql语句;中台设计为单dao和单controller
-
单controller使用OrmController,设计流程如下:
-
单dao设计使用xml配置,不建议使用注解
-
查询功能设计
-
传统ddd架构:展现层即前端ui,应用层即MVC层,领域层即service
-
通用仓库与通用工厂的设计
ddd案例
点击查看详情
-
用户故事是理解业务,使能故事是一个好的技术中台
-
案例
-
事件溯源
-
例如我们要实现
用户下单
的需求,只需要理清楚用户下单要处理的业务,至于下单完成后要做的事情不需要管了
-
领域事件的设计实现
-
总结