最近一直在做系统架构上重构工作,理论不能不学习啊,只有在思想上把自己武装起来,才能减少我们工作上的错误。之前参加过或亲自操刀过多次的代码局部或模块重构,但这一次架构重构是范围波及最广,收获颇多。
什么是重构
重构是指在不修改代码外在行为的前提下,对代码做出的修改,以改进程序的内部结构,提高其可理解性,降低其修改成本。
这是来自马大神的《重构》一书对重构释义。重构可以改进软件设计;使软件更容易理解;使软件更容易维护;帮助找到软件Bugs;帮助提高编程效率。重构按对系统修改的粒度层次可以分为如下:
- 局部代码重构,操作与实施比较容易,《重构》一书中介绍了大量经典的方法。
- 模块级代码重构,可能涉及到模块之间的接口重构,操作与实施难度相对适中。
- 架构重构,是对整个系统架构层次的重构,牵系相当的广,操作与实施难度比较高。
重构风险
无论何种层次的重构,都必须要有一个可靠的测试环境,即自动化测试环境。因为频繁的代码修改可能会引入更多的缺陷,只有执行自动化测试并回归所有用例,才能保证及时发现这些缺陷,最大限度地降低重构的风险。
- 局部的不良代码,可以通过小范围的重构来优化。但是对于架构上重构,因为重构影响范围过大,在实践中仍然存在绪多的困难。
- 架构上大的重构,至少几十人的投入,更需要半年到一年的开发周期。在老软件不能停止维护的前提下,这对开发人力将产生巨大冲击。
- 新架构虽然先进,但历史经验表明,新软件的成熟与稳定需要时间。在沉重的交付压力下,风险需要做很多的预防控制。
为什么要重构
给老大说明重构的意义往往很难,尤其不是技术出身的管理者,即使是,也需要面临交付上的考虑。从技术上讲,为什么要重构:
- 不论如何先进的软件架构也不可能预见到几年甚至十几年后的需求,并预先设计
- 随着新功能的不断增加,以及新成员的加入,软件架构必然逐渐腐化
- 虽然强力的架构看护制度可以延缓架构腐化的速度,但不可能看护到实现细节
- 重构则提供了软件持续优化的机会,从而使软件更容易适应新的需求,同时及时地改进不合理的部分
重构与重写
对于一次重构来说区别不大,只是力度不同,重构侧得局部优化,也会重用现有的资产,重构的极端就是重写。他们的主要区别是重构强调的是持续的,随时的优化,而重写强调的是一次性的天翻地覆的改造。那我们如何判断是要重构还是重写?
- 重构是持续的,并不是等到极端恶心才开始优化,所以坚持持续的重构可以代价更小的达到优化的目的
- 若已经极端恶化的模块,重写也是一种解决方式,但要注意避免失控,须在设计、测试、管理、人员能力等多方面要做好准备
何时重构
何时重构,因项目因人员能力而异:
- 不同粒度层次的重构,重构的时机选择应该是不同的
- 不同粒度层次的重构,实施的节奏也必然不同的
- 关键技术需要提前原型验证,风险评估
- 对于模块级,架构级重构,通常在添加新功能或特性之前充分考虑,留出部分空档期来重构
- 制定重构计划,步步为营,切忌全面开花,导致风险不可控
同时在重构时,需要平衡重构与交付:
- 为了交付而不重构,是恶性循环,最终交付的压力会越来越大,质量会越来越差
- 对于模块级,架构级重构,应该是有计划地落入到迭代版本中
- 可以采用冬虫夏草的方式重构,逐步重构或替换,随时(至少每个迭代)可以保证系统的完整性
- 注意控制每次迭代重构的范围,要分析并划分合理的重构边界
重构人员
重构最终落实还是人员能力,对于参与的人员能力要求:
- 知道重构的意义,重构需要有个人强烈的意愿,才能有所突破
- 对现有的组件流程与实现非常地清楚
- 针对性强,能够熟练地运用各种重构方法
- 能够察觉出实现的问题,能提出改进(重构)建议(方案)
- 经验是基础,对构架本身的体系有较为深厚的理解和应用经验
- 不同层级的重构,需要不同的参与,不同阶段投入
重构中有哪些角色,他们职责是什么
- SA/SE(系统架构师,系统设计师):负责按照架构正确地设计与分解需求,能清楚系统中的痛点,以及各组件的主要问题
- SE/MDE(系统设计师,模块设计师):负责某个组件整体看护,设计组件内疗实现机制,系统约束等
- SWE(软件工程师):在软件架构的基础上,负责具体的功能实现。
- TE(测试工作师):补充用例,执行自动化测试,及时发现系统中的缺陷,并与SWE结队处理问题。
总之,重构要务实,务实就是尊重现实,基于现实情况分析与实施,不断地推进演化。架构重构不仅需要充分的设计,切实有效的重构操作方法也非常地重要。架构重构,抛开代码搞理论上的重构不行;充分利用代码,但又不能掉进“代码泥潭”。无论怎么重构,一定要构建夯实的测试防火墙,快速反馈重构中的问题。