架构之重构的 12 条军规

2023-11-11

【注】架构之重构的 12 条军规(上)发布以后,一些读者着急要下篇,所以在这里我把上下篇合并成一篇,让大家可以阅读完整版,不用分开看了。

对于开发者来说,架构设计是软件研发过程中最重要的一环,所谓没有图纸,就建不了房子。在遍地 App 的互联网时代,架构设计有了一些比较成熟的模式,开发者和架构师也可以经常借鉴。

但是,随着应用的不断发展,最初的架构往往面临着各种问题,比如无法满足客户的需求、无法实现应用的扩展、无法实现新的特性等等。在这种情况下,我们如何避免一些坑,尽量比较成功地实现架构的重构,是很多开发者和架构师亟需解决的问题。

在这里,跟大家分享一下 Uber 的工程主管 Raffi Krikorian 的 12 条规则,并附上一些解读,希望对大家有所启发。

1. 确定重构的目的和必要性

看起来这个规矩有些多余,但是请不要忽略。每一次架构的重构都是“伤筋动骨”,就像做手术一样,即使再成功,也会伤元气,所以决策者们首先要分析架构重构的理由和其他备选方案,明确重构的目的是为了满足业务需求,并且是不得不做的最佳方案,然后再考虑其他问题。 有时候,经过分析就会发现,也许还有其他解决方案,比如增加计算资源,或者重构的目的不是为了业务需求,那就没有必要做了。

检查清单:

  • 架构重构的原因是什么,是为了满足业务的需要还是只是觉得架构不好看?
  • 除了架构重构之外,还有其他备选方案吗?是否都分析过这些方案的利弊?

2. 定义“重构完成”的界限

如果确定要重构,那么要把目标明确下来,也就是重构的边界条件,怎么才算是“完成”了重构,目标要有数据量化,或者有能够测试的办法。这也是一个需求分析的过程,如果需求不明确,那么规格说明书没法写清楚,负责重构的团队也没有明确的目标,不能以重构的时间或者主观的判断为结束的依据。前几天和一朋友聊天,他最近在负责系统的性能优化,也要做一些重构的事情,开始的时候团队的目标不明确,大家不知道优化到什么程度,所以不敢下手。如果目标是提高 10%,那么可以从细节处着手;如果是提高 50%,那可能要搞大动作才能实现了。后来目标明确之后,团队才找到合适的办法。

检查清单:

  • 重构的目标可以量化,或者说可以测试吗?
  • 重构完成的标准是什么?得到业务部门或者领导的认可了吗?

3. 渐进式重构

现在软件研发最流行的就是快速迭代、持续交付、尽早反馈。这同样可以用在架构的重构上,重构过程的难度不亚于构建一个新产品,所以在设计重构的时候,要引入持续交付的流程,每一个重构步骤或者模块都要快速部署并得到反馈,以便评估重构的效果,及时作出策略调整。有的读者会说,我们的架构重构是釜底抽薪型的,没法渐进,只能一蹴而就。如果是这种情况,可以考虑在另外一套拷贝的系统中做重构,经过谨慎测试之后,将数据和业务迁移过去。

检查清单:

  • 能否把重构过程分成小的迭代,每一次改进都能尽快得到反馈?
  • 重构过程中的效果能够定期展示给业务部门或者领导吗?

3. 确定当前的架构状态

在启动重构之前,团队要对当前的架构状态有清晰的了解,也就是设定好基准,以便评估重构的效果。据我的经验,负责重构的架构师或者开发者,往往还没有搞清楚现有的架构设计,就开始重构了,结果经常出现这样的情况:重构到某个阶段,发现行不通,然后一拍脑袋说,哦,原来这块的架构是这个样的,是为了达到某某业务需求啊,这块不能动,得想别的办法。类似的例子在研发团队中时有发生,也提醒我们要慎重小心。记得有位哲人说过,了解别人很容易,了解自己很难。

检查清单:

  • 你了解当前的架构设计吗?它的设计初衷和之前的选型方案知道吗?
  • 你能给架构设定一个基准状态吗?

5. 不要忽略数据

数据的重要性不言而喻,业务都是以数据流为载体的,所以架构重构的本质就是对于数据流的重构。数据对重构的重要性主要体现在两个方面:在重构设计时,需要考虑业务数据的需求,重构之后的系统对于数据的存储、处理、分析等功能是否有影响;在重构过程中,考虑依靠数据甚至是实际的数据来验证重构的效果,提供评估的支持。

检查清单:

  • 业务数据的需求在重构设计中有体现吗?
  • 重构过程中能否通过实际数据来验证效果?

6. 管理好技术债务

技术债务在平常的软件研发过程中也是比较突出的问题,现在单独拿出来强调是希望提醒开发者们:架构重构往往是为了偿还技术债务,所以请不要在偿还技术债务的过程中制造技术债务了。技术债务就像信用卡一样,会有很高的利息率,就如同给团队留下了大量的帐务开销。组织应该培养一种保证设计质量的文化。应当鼓励重构、同时也应当鼓励持续设计以及其它有关代码质量的实践。在开发时间中应当专门抽出一部分以解决技术债务。如果没有合适的照料,那么真实世界中的代码会变得越来越复杂难懂。

检查清单:

  • 团队对技术债务有跟踪和备忘录机制吗?还是开发人员可以随意的产生债务?
  • 针对技术债务有定期的培训、回顾机制吗?

7. 远离那些虚荣的东西(例如使用“热门”的技术栈)

架构的重构过程应该是以目标为导向,换句话说“注重实效”。对于技术人来说,一个经常被轻视的问题在于,喜欢追逐新鲜的热门技术,这其实是个好事情,说明技术人勇于创新,不断接受新技术。但是对于架构的重构这样的关键性任务来说,是不是新技术并不重要,重要的是能不能实现重构的目标。对于新技术来说,虽然热度大,但是人才储备还不足,大家踩过的坑还不多,积累的失败教训和成功经验还不够,在这种情况下,建议大家不要头脑一热就上马新技术,应该客观冷静地评估新技术和成熟技术对架构重构的影响和效果,以数据和经验来说话,而不要追赶时髦。

检查清单:

  • 重构的技术选型是否有详实的数据和专家评估?
  • 选用的技术是否有良好的人才积累和足够的经验支持?你是不是实验小白鼠?
  • 在技术选型时,是否至少有两个方案待评估?有没有成熟的技术方案?

8. 做好准备面对压力

这条军规更像是对架构师们的心理建议,软件开发过程中,压力无处不在。对于架构重构来说,压力来源于多个方面:管理层、团队成员、同级部门等等。说白了,架构重构对个人来说往往是一件出力不讨好的事情。和做一个新产品能够取得很高的赞赏相比,重构的成绩往往并不受领导重视,而且出了问题还要承担很大的责任。从软件开发角度看,做新产品是从 0 到 1,而架构重构是从 -1 到 1,复杂性和难度通常更大。因此,重构的负责人要提前做好心理准备,舒缓压力的一个技巧是,设置好里程碑,将重构的成果量化,并且和业务的变化关联起来,定期向利益相关各方同步状态,得到大家的理解和支持。

检查清单:

  • 架构的重构是否得到了管理层(特别是最高管理层)的支持?他们是否对重构的时间、任务量有直接的认识?
  • 你的重构计划中是否包含了一些可以量化的成果?是否定期向管理层展示这些成果?

9. 了解业务

虽然看起来像是一句废话,但是我想 Raffi Krikorian 特意把这条提出来一定是有理由的。架构重构的最终目的是改进业务,所以对于业务的了解将有助于架构师和技术人确定重构目标的优先级和关键路径。比如,我们需要知道哪些关键业务的架构是不能碰的,哪些业务之间是互相关联的,哪些业务的架构是需要优先重构的…等等。除了了解业务本身,我们还需要了解“人”,表面上管理层是重构目标的裁决者,但实际上业务部门的人才是。技术人需要了解他们的业务需求,并将其转化为重构目标。通过这种方式,架构重构的意义才能得到具体的体现。

检查清单:

  • 是否与业务部门就架构重构所能实现的业务目标进行过充分的讨论和确认?
  • 是否对关键业务和优先重构的业务进行了确认?

10. 做好面对非技术因素的准备

恩…这又是一个不那么让人舒服的建议。不管你是否愿意相信,技术在架构重构(以及其他很关键的公司决策中)的影响因素中并不是最高的,我们还会涉及到商业利益、管理层偏好、大客户影响、办公室 zhengzhi、站队问题等等,对于架构师和技术人来说,这些因素往往不是他们所能掌控的。我们能做的就是,与利益相关者设定重构目标,然后,根据不同的影响因素,调整目标。请记住,不要死扛这个目标,当有人提出不同的意见时,要坦诚地和他们交流,并告知他们如何采纳意见,那么重构目标会有变化,然后让其他利益相关者也知道这些变化。非技术因素的影响是客观存在的,而且从商业层面来说也是合理的,所以对于技术人来说要学会适应。

检查清单:

  • 当非技术因素影响架构的重构时,你是否对目标做了调整并告知了利益相关各方?
  • 你是否准备以开放而不是抵制的心态来对待非技术因素的影响?

11. 对于代码质量有所掌握

这和上篇中所提到的“管理好技术债务”有异曲同工之处。架构的重构对代码质量要求很高,一方面是重构过程对 bug 的容忍性比新产品的研发更低,另一方面也决定了下一次重构的难易程度。关于代码质量的书籍和文章已经有很多,在这里只想提醒大家一点:代码审查是一个非常好的办法。代码审查是软件开发过程中的必要步骤,既可以帮助被审查者提到代码质量,又可以让审查者加深对产品的理解。不论团队多忙,一定要保证代码提交之前,是经过其他成员审核过的,短期来看会占用团队的时间,长期来看是事半功倍的好事。

检查清单:

  • 团队成员是否对代码质量有足够的重视?是否有奖惩措施?
  • 团队内部是否有代码质量的标准文档和审查流程?

12. 让团队做好准备

这是 Raffi Krikorian 列举的最后一条军规,是对之前所有建议的总结,我在这里不做解读了,请大家自我感觉吧。

结尾

关于架构的重构,Raffi Krikorian 给了很好的建议,不过到底有没有效果,还是要实践中检验。尽信书不如无书,来源于实践中的经验是最有价值的,为技术人所用才有意义。

转:https://www.infoq.cn/article/architect-12-rules-complete/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

架构之重构的 12 条军规 的相关文章

  • <转>企业应用架构 --- 分层

    系统架构师 基础到企业应用架构 分层 上篇 一 前言 大家好 接近一年的时间没有怎么书写博客了 一方面是工作上比较忙 同时生活上也步入正轨 事情比较繁多 目前总算是趋于稳定 可以有时间来完善以前没有写完的系列 也算是对自己这段时间工作和生活
  • 程序流程图是什么?基本流程图讲解

    程序流程图是什么 程序流程图是流程图的其中一种分类 又称程序框图 指用特定图形符号加上对应的文字描述表示程序中所需要的各项操作或判断的图示 程序流程图除了说明程序的流程顺序外 着重于说明程序的逻辑性 一 程序流程图特点 当程序流程中有较多循

随机推荐

  • 动态规划经典例题-国王的金矿问题

    金矿问题 问题概述 有一位国王拥有5座金矿 每座金矿的黄金储量不同 需要参与挖掘的工人人数也不同 例如有的金矿储量是500kg黄金 需 要5个工人来挖掘 有的金矿储量是200kg黄金 需要3个工人来挖 掘 如果参与挖矿的工人的总数是10 每
  • 转:FindBugs,第 2 部分: 编写自定义检测器

    FindBugs 第 2 部分 编写自定义检测器 如何编写自定义检测器以查找特定于应用程序的问题 FindBugs 是一种可以扩展和定制以满足自己团队独特要求的静态分析工具 在本系列的第 2 部分中 高级软件工程师 Chris Grinds
  • odoo12 用户(users) 权限管理界面分析

    起因 由于需要了解 odoo的权限管理 去看了下 odoo 是如何给用户赋权限的 发现好多不能理解 因此 打算从 user 的xml开始 看里面到底是什么意思 第一步 肯定查看user的xml 找user源码 odoo odoo addon
  • delphi xe 10.3 访问 linux 7 mysql 5.7.20

    下载 https cdn mysql com archives mysql 5 7 mysql 5 7 34 win32 zip 解压 并复制lib目录下的所有文件到 X Program Files x86 Embarcadero Stud
  • MySQL崩溃修复案例

    问题描述 研究MySQL源代码 调试并压测MySQL源代码时 MySQL崩溃了 问题是它竟然崩溃了 而且还损坏了InnoDB文件 还好是在调试环境下发生的 赶紧看看如何解决这个问题 经过一系列的查阅资料 验证 对比 MySQL源码调试跟踪
  • 单线程的Redis为什么这么快

    一 为什么Redis是单线程的 Redis 是基于内存的操作 而CPU 不是 Redis 的瓶颈 Redis 的瓶颈最有可能是机器内存的 大小或者网络带宽 同时 单线程的实现更加简单和经济 采用单线程可以使指令串行 不用额外 维护锁机制 避
  • java通过反射创建对象的两种方式

    我个人觉得我自己是个比较粗心的人 所以各位大佬发现有什么不对的地方还请留言告知 在java中 通过反射创建对象有两种方式 使用Class对象的newInstance 方法来创建对象 具体步骤是 1 获取类的Class对象 有三种方式可以获取
  • 深度学习系列:阿里DIN模型的原理和代码实现

    一 前言 今天介绍阿里巴巴的DIN网络 不得不说 阿里妈妈的大佬是真的多 经常都会更新非常多的创造性的东西 比如DIN中使用的自适应正则化技术以及Dice激活函数以及注意力机制的使用 并且值得注意的是DIN网络中使用的注意力机制还挺多的 哈
  • C语言中不定参数函数

    在我们平常调用函数的时候 会进行传参 调用的函数也会有参数去接收 数量和类型都是对应的 而不定参数函数是指对一个函数传参 参数的个数可以不确定 接下来 我就简单的叙述一下不定参数函数的原理及应用 在我们刚学C语言的时候 大多会首先接触pri
  • 可变长参数 VS C++11 可变长模板

    转 https blog csdn net zj510 article details 36633603 C 可变长参数 VS C 11 可变长模板 2014年07月03日 13 50 32 阅读数 10437 有些时候 我们定义一个函数
  • fine-tuning(微调)的理解

    fine tuning 介绍 什么情况下使用微调 微调指导事项 不同数据集下使用微调 涉及到的其他知识 学习率 learning rate 卷积神经网络的核心 迁移学习与微调 什么是迁移学习 为什么要迁移学习 详细解释 自己的理解 不知道对
  • 分库分表设计方案

    一 为什么要分库分表 随着业务的不断发展 数据量不断增加 因此数据操作 如增删改查的开销也会越来越大 原来基于单库单表的设计已经不能满足存储需求 数据库随时面临爆库风险 再加上物理服务器的资源有限 CPU 磁盘 内存 IO 等 最终数据库所
  • 爬虫之selenium

    目录 selenium介绍 基本使用 selenium用法 元素操作 等待元素被加载 元素各项属性 执行js代码 切换选项卡 浏览器前进后退 无界面浏览器 xpath的使用 简单介绍 selenium中使用 异常处理 登录获取cookie保
  • Android 图片压缩二:

    public Bitmap zoomBitmap Bitmap bitmap int width int height int w bitmap getWidth int h bitmap getHeight Matrix matrix n
  • Asp.Net Core&CAP实现分布式事务

    需要注意的是标题中的CAP不是指的CAP理论 而是园区大神杨晓东实现的框架 CAP框架基于本地消息表用最终一致性实现分布式事务 本地消息表 首先我们考虑一个场景 在将用户信息更改后 需要发送一条消息到消息队列 缓存或是写入到其他库中 这个过
  • STM32F103ZET6【HAL函开发】STM32CUBEMX------II2C实验

    SCL和SDA都要接上拉电阻 起始信号 SCL为高 SDA由高变为低 停止信号 SCL为高 SDA由低变为高 数据有效性 SCL为高电平时 SDA数据有效 此时SDA为高电平时 表示数据为 1 为低电平时 表示数据为 0 当SCL为低电平时
  • Linus命令大全

    Linus命令是Linux操作系统中的一些常用命令 下面是一些常用的Linus命令 ls 用于显示当前目录中的文件和目录 cd 用于切换当前目录 pwd 显示当前目录的路径 mkdir 创建新目录 rm 删除文件或目录 cp 复制文件或目录
  • MoveIt入门之——使用MoveIt配置助手生成MoveIt配置文件

    一 安装MoveIt assistant sudo apt get install ros kinetic moveit 如果报错说找不到软件包 可能是没有更新源 只要去roswiki上找安装教程 把源重新加入就可以了 二 打开配置助手 r
  • npm ERR! code EPERM npm ERR! syscall unlink npm ERR!错误解决方法

    npm ERR code EPERM npm ERR syscall unlink npm ERR 错误解决方法 1 问题描述 2 解决方法 1 问题描述 由于之前电脑系统的原因 电脑重置了一下 之前安装的环境都没了 然后在重新安装node
  • 架构之重构的 12 条军规

    注 架构之重构的 12 条军规 上 发布以后 一些读者着急要下篇 所以在这里我把上下篇合并成一篇 让大家可以阅读完整版 不用分开看了 对于开发者来说 架构设计是软件研发过程中最重要的一环 所谓没有图纸 就建不了房子 在遍地 App 的互联网