

重构
▐ 什么是重构?
重构(refactoring) 对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。
-
【软件结构的调整】 通过提取、改名和移动等手段、调整代码的结构。这种调整往往是大量且微小的,一步步小的修改来达成大的修改目标。这一点对于很重要,如果上来就就行了一个大幅度的修改,导致软件处于不可运行的状态,这种就不是重构了,会破坏持续重构的节奏。 -
【 不改变软件行为 】 代码结构改变以后,对外提供的功能保持不变。即不改变软件本身的行为,甚至原有的 Bu g 依然存在。另外提一下重构和性能优化的关系,重构的后的软件性能可能会变好,也可能会变差。重构本身不是为了性能优化,而是为了让代码更容易理解和修改。
▐ 重构有什么价值?
-
【软件架构】重构可以持续改进软件的设计 。软件的设计不是不是一蹴而就的,即便是设计良好的软件,也会因为时间的推移,功能的变化而不断腐坏,而重构可以改善这个过程。 -
【工程质量】重构可以提升软件的可维护性 。通过重构,可以使代码更易读、更易理解,并且更容易维护。清晰的代码结构和命名约定有助于新成员更快地加入项目,并使得未来的修改更为简单。 -
【研发效率】重构可以提升我们的研发效率 。通过重构,调整的代码的结构,让同一个功能的代码更加内聚,提升代码的扩展性,无论是新需求开发还是定位 Bug 就会变得更加简单。
▐ 我的工程需要重构吗?
-
开发阶段 -
代码复杂,新功能难以扩展,只能修修补补,或者干脆复制一份代码来改。 -
开发功能一小时,定位 Bug 一整天。团队的大量人力消耗在线上问题的排查上。 -
测试阶段 -
开发修复一个 Bug,验证通过后又出现另外一个 Bug。 -
测试手段有限,只能靠手工的黑盒测试。没有单侧,代码也无法单侧,代码质量只能靠集成测试来保证。 -
发布阶段 -
功能发布后,会有一些测试阶段没有发现的问题流到用户手上。
▐ 重构会面对哪些挑战?
-
重构会占用团队人力,耽误业务需求的研发。这点很容易和业务团队 battle。 -
重构的时间一般窗口短,如何在较短的时间内完成重构。
-
重构会改动代码的结构,如何保障不影响现有的功能,不引入新的问题。 -
重构的模块可以在多个业务场域使用,如果保障移动/改动 API 对其他业务不构成影响。 -
重构的过程中业务还在不断的迭代,老架构的新功能如何不遗漏的加入新架构,如果做代码/功能的同步。
-
如何着手开始重构。目前工程的代码规模大(单个类动辄几千行),业务复杂度高(各种逻辑分支、各种实验开关),从哪里开始下手,怎么下手。 -
如果保障重构的落地。重构的研发周期和灰度放量是一个充满各种不确定性的事情, 一番轰轰烈烈的重构最后因为业务指标/性能指标不达标而不了了之的情况很常见 ,如何避免这种情况,让新架构顺利落地。 -
如何保障新架构的可持续性。新架构落地后,如何保障新架构能持续维护,避免“ 一锤子买卖,有人写,没人维护 ” 。这是重构后另外一个重要的命题。
-
【自动化】 通过自动化重构(IDE 安全重构),提高重构效率,减少人工挪动代码引起的风险。 -
【系统化】 通过系统化的方法,系统性的分析现有的架构设计,有那些功能模块,代码耦合的点在哪里,如何拆解。现有的架构设计有什么问题,什么样的架构能解决当前的问题。 -
【工程化】 通过架构守护、静态扫描、单元测试等手段,保障重构中的安全性和重构后架构不劣化。

▐ 架构的坏味道
-
扩展性差 : 软件系统增加新功能,每次更改都会带动一连串的其他更改。 -
系统脆弱 : 软件系统容易受到更改的影响,哪怕是一个微小的更改,也可以会引发线上问题。 -
模块耦合 : 模块之间的依赖关系过多,一个模块的改变影响了其他多个模块, -
混沌架构 : 缺乏明确的架构设计,代码看起来像一团混乱无组织的泥团。 -
滥用设计模式 : 不必要或者不适当的使用设计模式,导致代码更加复杂和难以理解。 -
不必要的复杂性 : 在业务尚未需要的时候引入过于高级的技术或者框架,增加了理解成本。
-
ArchUnit :是一个免费、简单且可扩展的库,它可以用Java单元测试框架来检查Java代码的架构,包括检 查包和类、层和片之间的依赖关系 ,可以作为“ 架构的守护门禁 ” 。 Android Studio的Dependencies依赖分析
▐ 选择合适的架构
单体化架构
架构相对简单,前期便于小团队协作,能够快速进行迭代开发。
架构对业务功能缺乏管控和约束,业务功能之间会彼此依赖,耦合度高。 架构可扩展性差,随着业务复杂度的上升,功能耦合的问题进一步加剧,新功能扩展困难,影响研发效率。
组件化架构
不同组件间一般有明确的依赖边界, 高内聚低耦合 , 提升了组件复用度。 不同组件之间不再相互干扰,提升了研发效率。 不同组件间可以独立编译调试,集成及编译调试效率高。
组件化架构相比单体架构更加复杂,对基础设施也有一定要求,需要引入路由 注入等框架解决组件依赖以及通信,集成复杂度高,依赖集成打包平台等基建。
上述的组件化架构是针对一个 APP 来说的,我们日常开发更多的时候是面对一个或者几个业务模块,这个时候我们可以借鉴组件化框架“ 高内聚低耦合 ”的精髓,实现一套变种的组件化架构。代码可以在一个模块里,用包来划分功能,每个包里面的代码实现“ 高内聚低耦合 ”。
插件化架构
-
支持业务插件进行动态加载,能满足独立的业务快速交付给用户。 -
可以有效的减少包大小,促进拉新和用增转化。
-
插件化架构需要引入插件管理机制。 -
插件化架构需要引入插件管理平台,支持插件的版本管理,动态下载等机制。集成管理的复杂度更高。
容器化架构
-
跨平台,一码多端,能够有效的降低开发和测试成本。 -
支持动态化,提升业务迭代效率。 -
H5、ReactNative 或者 Flutter 支持与原生开发混编,支持团队逐步改造现有系统。
-
跨平台技术的性能及体验通常比原生要差, 有体验的问题 。 -
跨平台技术需要开发人员掌握特定的跨平台技术框架与语言, 有学习门槛 。 -
跨平台技术涉及对本地的硬件能力访问时,同需要使用原生的代码来开发, 有适配成本 。

▐ 代码的坏味道
▐ 编码规范与静态扫描


▐ 设计原则与设计模式

团队介绍
本文分享自微信公众号 - 大淘宝技术(AlibabaMTT)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。