Go技巧 - 面对遗留Go代码,如何优化?
虽然 Go
语言的诞生时间不长,但由于语言特性、人员水平、框架选型等因素,存在各种“遗留代码”需要开发人员维护。尽管内心有各种不乐意,但如果该系统有足够的价值,我们还是不得不面对这个挑战。
那么面对遗留Go
代码,我们该如何优化呢?
梳理现状,明确目标
首先,我们要对代码优化有一个提纲挈领的把控。代码优化就是一个项目,我们要梳理清楚输入与输出:
输入重点包括:梳理程序代码现状,以及预期投入到改造的人力。
而输出则关注预期改造后的收益。注意,这里的收益最好能有所区分:例如 不同改造方案、不同人力投入带来的收益会有所差异;同时,改造收益也要从各参与方的视角出发,如提升开发效能(开发人员)、提高项目的稳定性(管理人员)等。
控制风险,小步迭代
我们这里谈论的代码优化,虽然从改造内容来说,并不亚于一次规模较大的重构或重写。
但是,在团队内提出一个重构或重写的专项工作,第一时间给周围人的感觉是:高风险、长周期。一旦这个项目涉及到多方人员,往往推进难度极大。
而代码优化这个说法会显得更轻量,容易得到多方的支持;也同时提醒我们,整个改造过程要控制风险、小步迭代、适时回滚。改造中会有不少的阵痛期,也是开发人员快速成长的机会。
而当改造完成后,整个项目焕然一新,完全就是一次成功的大型重构。
第一步:解决外部依赖代码
作为改造的第一步,我们应先清晰地隔离外部依赖的问题。
这一点,关键就是做好标准化Go Module
的改造,移除历史遗留的glide
、vendor
等依赖方式。在陈旧的项目里,开发者会发现各种奇怪的问题。所幸,Go
作为一门编译型语言,能提前发现很多语法不兼容的问题,减少风险。
完成了Go Module
的改造后,项目对外部依赖库有了明确、清晰的管理方式。
第二步:明确分层逻辑
分层是项目内代码的“躯干”,是开发者理解代码的核心切入点。
分层方式有多种,很难统一标准;而且,在一个团队中,我们最好能根据团队成员、历史代码、组织情况灵活调整。无论如何选择,都应在团队内对分层逻辑保持一致,并进行改造。分层逻辑对代码的改造较大,我推荐按如下的方式进行:
- 先独立遗留代码:将遗留代码独立到一个专门的路径,如
legacy
,和标准的代码隔离 - 用目录保证分层:分层后的代码用目录进行“物理隔离”
- 逐步并有序地迁移:改造的过程一定要有章法,如
legacy
下的代码只删不增,分层下的代码符合规范
这一阶段会花费大量的时间在迁移的过程,但决定成败的在于分层设计,前期必须做好充足的准备与可行性验证,才能保证最后交付出的价值。
第三步:梳理context
和error
在明确了分层逻辑后,有2个Go
专有的特性非常值得开发者关注:
context
上下文,传递一些公共变量(如用户)和超时等控制逻辑,核心数据流是 上层->下层error
错误,传递异常信息,核心数据流是 下层->上层
梳理清楚这两个变量的使用方式,能帮助我们串联起各分层的逻辑,也为后续的拓展能力做好储备,如基于context
的trace
传递,基于error
的错误码封装。
第四步:工具库升级
完成了分层与context
/error
的梳理,基本的代码框架已经形成,但最大的收益点仍没有达到:提效。我们要不断地替换或引入一些成熟的工具库,来提升研发效能。
在这一阶段,我们会不断遇到问题,但不要灰心、在半途选择放弃,这将是你成长最快的一个机会。
小结
我经历过大大小小近10个Go
语言项目的大型重构,遇到过各种疑难杂症,也算是从摸爬滚打的经验里积累出一点心得。
目前,技术问题基本可以通过搜索引擎解决,更困难的是将这个代码优化的过程落地到组织中,逐步推进。这是一个深入融入到公司的机会。
编程思考 - 基础团队为何推动技术迭代难
在中大型公司里,往往会建立一个基础团队,负责通用的、公共的技术,例如多语言工具库、各类基础平台。
对基础团队来说,由于不直接面向一线业务,也就无法直接根据业务收益来评估自身的价值;而基础团队的价值更多地是要从提效来体现,也就是降低各业务团队在通用能力上的投入。
提效,最常见的方法是引入一个更高效的技术、去替代相对低效的老技术,比如用git替代svn,用docker来替代vm。但是,即便新技术得到广泛认可,在各业务团队中依然很难推进。最常见的问题有两个:
- 改造成本
- 稳定性风险
这两个问题有很多解决思路,不过并不是今天讨论的重点。让我们先抛开技术视角,如果你是业务团队的负责人,你会考虑:
- 改造有时间、人力成本,为什么不安排去做几个业务需求、提升产品效果?
- 稳定性有风险,为什么不维持现状?
- 既然推动新技术可能影响到业务价值,那是否可以不做?或者延期再做?
面对可能存在损失时,人们倾向于保守的态度。所以一旦涉及到业务方的技术迭代,单靠基础团队推动是极难的。
也许你会疑惑:业务团队不考虑提效吗?我的想法是:业务当然会考虑提效,但业务的提效点并不只能基础团队的技术,从业务团队内部做提效会更快捷、更可控。
工作生活 - 试着给孩子“戴高帽”
在中国式教育中,我们常常以批评、责备等方式来督促孩子,但效果常常适得其反。这时,不妨尝试着给孩子“戴高帽”,多夸奖孩子。
“戴高帽”并不意味着无脑地赞扬,而是希望家长们在有负面情绪时,先抑制住自己当前的情绪,尝试着去感受并理解孩子。真心夸奖往往需要先调整到正面的情绪,就督促着我们去努力发掘孩子行为背后的含义。
调整情绪,主动地去理解孩子,这才是“戴高帽”最重要的意义。面对生活、工作中的其它负面情绪时,我们也可以用这种方式进行应对,也许会有意想不到的收获。
Github: https://github.com/Junedayday/code_reading
Blog: http://junes.tech/
Bilibili: https://space.bilibili.com/293775192
公众号: golangcoding