文档章节

(6) 基于领域分析设计的架构规范 - 关于重构与落地

不知道自己什么不知道
 不知道自己什么不知道
发布于 07/09 15:08
字数 2253
阅读 723
收藏 9

本系列目录:

  1. 改变与优势
  2. 领域分析基础
  3. 读写隔离
  4. 充血模型之实体
  5. 充血模型之Service
  6. 关于重构与落地

不论大家是否认可我在这里提到的这一套小规范,既然你能看到这里,还是由衷表示感谢。核心内容已经介绍得差不多了,接下来还是看两个很实际得话题。

DDD落地之殇

DDD这类架构真正落地困难,我觉得,有几个原因:

  1. 规范多,尤其是充血模型,需要对业务有更清晰的认识
  2. 代码结构相比无状态扁平化开发,层次深,模块划分更严格,所以,至少从文件数上来说,是更多的(代码行数倒是不一定多)
  3. DDD并不是一个“刚性”需求,如果不按这个规范来做,系统一样可以跑起来,所以,很多规范处在一个“模糊”的界定上,让开发人员无法确定到底该如何规划代码。

正因为如此,即使团队技术Leader了解DDD,却在项目一开始的时候,由于考虑到DDD的规范过多,不便于协作,为了快速开发迭代,往往继续沿用最通用的写法。而一旦到了中期,业务复杂度上来了,当觉得领域分析有用武之地的时候,低头一看,系统的复杂度已经到了难以轻松驾驭的程度,更别说来一个180度的大转变了。

真的,这很现实,就是一个恶性循环。

所以,我们需要找到一个破冰的办法:

  • Leader足够强,团队成员实力不错,也给予Leader充分信任,那么在一开始就采用DDD
  • 在一开始依旧采用非DDD架构模式,但利用迭代的方式,将代码逐渐变成DDD

这两者没有绝对好坏,虽说第一种不常见,但依旧是我挺期待和欣赏的做法。

而可能更实用的是第二种,但新的问题又来了,如何逐步迭代改进成DDD,从哪里入手?

从现有代码迭代改进

我们不强求一步到位,但求一步步做出一些恰当地整理

以下给出一个循序渐进的参考方案:

1. 读写隔离

这个过程几乎不与业务挂钩,我们将OrderService,ProductService中的查询方法剥离出来,放在诸如OrderFinder,ProductFinder之中,具体编码细则规范参见之前的章节。 整个过程,一般来说,只要编译能通过,代码就不会有什么问题。

2. 提取Factory

在查询方法被剥离之后,就只剩下增/改/删了,其中又是最特别的,前面在讲工厂的时候提到过,所以将一个实体的创建行为提取到一个XXXFactory中,也不困难,稍微留意一下,也不容易引发业务问题。特别是在一个已经相对复杂的系统中,如果没法一下子分析透彻聚合根的归属问题,那么可以每一个实体都加一个Factory,之后再逐步合并,虽说工作量稍大一点,但对于已经有点棘手的项目来说,也算是一个快刀斩乱麻的办法。

3. 提取{Action}Service

也就是提取我们前文所提到的,跨多个聚合的一个事务操作 到一个独立的Service中。 或者还可以将要求降低一点,只要觉得代码量特别大(我个人觉得150行以上就很大了,何况有些还带了私有方法)的一个方法,都迁移到一个独立的Service中,并采用前文提到的{具体操作}+Service的命名方式,一个Service只负责一个复杂的方法。虽说不会非常精确,但重构后的效果还是会很明显的。

4. 建立领域聚合体系

经果上面几步操作,我相信你的代码里,曾经那些OrderService,UserService,已经只剩下相对简单的一些改/删操作了,其实,某种程度上,他们已经逐步出现了领域聚合对象的样子了。所以,如果你做到这一步,暂时停止了,也已经值得庆祝了!

那么如果还要继续前进一步呢?小项目还好,对于大项目,会有些难了。我相信这时候OrderUser很有可能是被POJO/DTO存在的,为了保证平滑过度,我们肯定只能新建领域模型,那么可能会要采用诸如OrderDomain来表示了。然后再将之前OrderService里的方法迁移过来。

但如果你用的是Spring或者类似Spring的IOC框架,会有一个很现实的问题。由于实体是被ORM框架new出来的对象,是脱离IOC容器管控的,所以如果你要在一个实体中使用一些IOC容器里的组件,可能得要自己去通过IOC容器的上下文来手动获取,比如通过ApplicationContext来获取,而不能通过@Autowired来自动注入了。

目前我在工作中,借用版本迭代的机会,逐步执行第一步第二步,确实也是由于项目太大太杂,即使这两步走起来工作量也不小,还要和同事协调好这种新做法沟通协作问题,确实这也是挺现实的一个问题~

关于版本迭代

唯一不变的就是变化。

我们经常得要“笑着”对着甲方或老板说:“我们会拥抱变换”,呵呵~ 很苦,但得要面对啊。

所以,假如我们有一个领域实体为订单明细,大家可以很容猜到,它也是属于订单聚合中的一部分,而非聚合根。订单明细的变动,都来源于订单的操作,比如订单编辑,order.modify()

某一日,产品需求发生变化,说:

  • 我们的订单明细要单独展示一个管理页面,而不只是像以前那样,只能从某一个订单点击查看“详情”才能看到
  • 同时,我们要能对订单明细进行修改,并且将这些明细的订单绑定关系进行修改

这时,你会很明确的发现,曾经的订单明细已经开始“昂首抬头做主人”了,不再“寄人篱下”了,因为它的查看入口不再附属再其他实体上,而且我们还得精确找到某一个明细进行修改。 独立修改

产品既然这样设计,意味着订单明细在整个业务系统中的身份已经发生变化,它的独立性也将越来越强,未来很多功能很有可能将围绕它而展开。所以,订单明细将成为一个独立的聚合,进而我们会做出一些变化:

  1. 订单明细将有自己的 OrderDetailFactory
  2. 订单明细将逐步建立自己的方法,出现如 orderDetail.modify()
  3. 曾经订单聚合中的一些操作,要迁移到新的Service中,因为他们是不同的聚合了,有些操作已经属于跨聚合操作

其中第(3)步,是难度最大的,因为要改动以前的代码,甚至要动到业务,不仅有开发难度,还有测试难度。

但是很遗憾的是,任何重构都是这样的。不论用什么框架,到一定阶段,我们都会面对这个问题。不在开发期间进行优化,那技术债务,只会变成成千上万的BUG来给我们上课。有的时候我们总吐槽自己又拿到的一个前人的项目,说代码多么烂。但是反思下来,现在自己手头的代码,重构过吗?是不是也会成为未来人的笑柄呢?

其实这个未来人可能很近,可能就是一个月后的你自己。(神情复杂的笑容)

关于下一阶段的内容

目前我更多的以单计应用的架构为例,还未提及太多分布式相关的内容。

分布式是一个双刃剑,与这个架构的协调,我还在梳理中,等好了,我会第一时间发出来。

其实我不在乎阅读量有多大~ 我把这个当作一个我自己的工作记录,就好了~ 谢谢大家~

© 著作权归作者所有

不知道自己什么不知道
粉丝 27
博文 6
码字总数 11878
作品 0
长沙
高级程序员
私信 提问
加载中

评论(12)

花轮君
花轮君
开完到现在越来越觉得设计模式很重要,写的落地,准备在下个需求中尝试下
不知道自己什么不知道
不知道自己什么不知道 博主
谢谢支持,有什么疑问可以随时提出~
我是光哥
我是光哥
比较实际能落地的一种方式,给个赞!
不知道自己什么不知道
不知道自己什么不知道 博主
谢谢支持,虽然确实任重道远,但确实可以试试~
Y
Y292450104
读写隔离的方式的确可以很好的核心系统的复杂性
不知道自己什么不知道
不知道自己什么不知道 博主
是的,而且这个实现并不难,可以随时在现有项目里进行重构
红酒花生
红酒花生
看了标题准备跑的,但是又想看看到底怎么个做法,挺好的文章,待我完全吸收之后,再与你沟通。
不知道自己什么不知道
不知道自己什么不知道 博主
谢谢,我相信跑了一大部分人,哈哈
砒霜鹤顶红
砒霜鹤顶红
很难将整个系统构想成一个抽象模型,需要引入新的复杂性来处理现有复杂性。
不知道自己什么不知道
不知道自己什么不知道 博主
确实,所以我在最后这一篇里也给出了一些基于现有模式的重构建议,如果愿意尝试的话,可以分几个步骤来做,不需要一蹴而就。
brucewang41
brucewang41
写得真好
不知道自己什么不知道
不知道自己什么不知道 博主
谢谢支持😆
腾讯技术工程 |QQ相册后台存储架构重构与跨IDC容灾实践

作者简介:xianmau,2015 年加入腾讯 TEG 架构平台部,一直负责 QQ 相册平台的维护和建设,主导相册上传架构重构和容灾优化等工作。主要研究方向为口语对话系统、分布式系统架构设计和优化,...

腾讯技术
2018/02/01
0
0
SOA架构设计经验分享—架构、职责、数据一致性

阅读目录: 1.背景介绍 2.SOA的架构层次 3.SOA化的重构 4.运用DDD+GRASP进行分析和设计(防止主观的判断导致错误的假设) 5.SOA分布式下的数据一致性 6.总结 1.背景介绍 最近一段时间都在做系...

王清培
2015/05/07
0
0
互联网公司的架构设计要怎么落地?| 技术头条

作者 | 张辉清 责编 | 胡巍巍 你做架构设计了吗?你认为要不要做架构设计?你的公司有没有做架构设计?互联网公司的架构设计又要怎么做? 我不知道你是怎么想的,在我得到的答复中,大部分人...

CSDN资讯
02/14
0
0
QQ 相册后台存储架构重构与跨 IDC 容灾实践

欢迎大家前往云加社区,获取更多腾讯海量技术实践干货哦~ 作者简介:xianmau,2015 年加入腾讯 TEG 架构平台部,一直负责 QQ 相册平台的维护和建设,主导相册上传架构重构和容灾优化等工作。...

云加社区
2017/12/26
0
0
谈程序的腐化

写代码如同打扫屋子,有句话叫一屋不扫何以扫天下。如果单个的一个模块代码都不能管好,如何成就一个完善的软件系统?今天我们来说说,一个代码模块的代码是如何一步步腐化变质,到最后程序员...

keyu88888
2017/05/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Linux输入法fcitx的安装问题

Fcitx 总共要安装的包如下 fcitxfcitx-binfcitx-config-commonfcitx-config-gtk | fcitx-config-gtk2fcitx-datafcitx-frontend-allfcitx-frontend-gtk2fcitx-frontend-gtk3......

CHONGCHEN
43分钟前
3
0
网络基础

前言: 最近整理一些以前的学习笔记(有部分缺失,会有些乱,日后再补)。 过去都是存储在本地,此次传到网络留待备用。 计算机网络的功能: 1.数据通信; 2.资源共享; 3.增加数据可靠性; 4....

迷失De挣扎
43分钟前
3
0
spring boot升级到spring cloud

1、先升级spring boot 版本到2.1.3 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.1.3.RELEAS......

moon888
46分钟前
10
0
从蓝鲸视角谈DevOps

DevOps源于Development和Operations的组合 常见的定义 DevOps是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。透过自动化“软件交付”和“架构变...

嘉为科技
49分钟前
1
0
微服务设计 笔记

微服务设计 一、微服务架构理论 1.六边形架构 1)六边形架构(Hexagonal Architecture),又称为端口和适配器架构风格;使用适配器与外界进行交互,外界通过应用层API与内部进行交互。 2)经典...

啃不动地大坚果
58分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部