侧边栏壁纸
博主头像
Curllen博主等级

早上的云霞好美~

  • 累计撰写 12 篇文章
  • 累计创建 18 个标签
  • 累计收到 2 条评论

目 录CONTENT

文章目录

Java之浅谈重构

Curllen
2019-01-08 / 0 评论 / 0 点赞 / 1,216 阅读 / 0 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2020-05-06,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

在Coding上,重构是一个不可避免的问题,本文结合个人经历和同事对话,对重构做一个总结

前两天,在公司论坛看到一个问题:

重构代码的好坏有什么评价标准吗?

我们为什么要重构代码?

在回答上面那位同学的问题前,也许更应该思考一个问题:我们为什么要重构代码以及选择开始重构代码的时机?

重构代码的原因有以下几个:

①代码风格的统一

随着IT行业越来越完善,在代码规范上,各个公司的态度越来越趋于一致:要有自己的Style Check,这是保证代码健壮性、可阅读性的有力保障措施,所以当一份超大圈复杂度,臃肿不堪的代码呈现在眼前时,重构这个概念自然就出来了,clear code也是代码重构的一个重要意义。

②业务需要

如果现有系统已经不能满足业务场景需要,那似乎可以行的通的道路就只有重构一条。我现在所经手的一个项目,主要就是因为这个原因开始了重构之路,前前后后花了4700余万,并且还在持续迭代中。

选择重构的时机:

是不是一份看起来有坏味道代码在眼前时我们就需要选择重构?答案当然是否定的!重构的代价是很大的,没有谁可以随随便便拍板说:这个代码不行不好看,我们要重构!

选择重构的时机应当是:从长期看,当后续代码改动较大,后续改动过程中的带来的维护成本大于重构成本时,此时就需要重构,即到了选择重构的时机。一句话总结就是长远收益大于当前重构成本,如果代码后续的改动不大,自然没必要去重构。


重构代码有什么评价标准?

就现在业内而言,实际上对于重构后代码并没有统一的评价标准,当然,就Style而言,大型公司都有自己的检测工具,通过检测后能够作为评价的一部分依据。

其他维度上,可以给自己提一些疑问:重构后,开发者测试( LLT/ DT)是不是真的更好做了?模块间的耦合是不是更少了?接口传递的信息有没有更精简?一个好的重构,相关部分的 LLT,打桩应该会更少,数据应该会更好构造。如果这些效果达到了,至少说明还是有些重构效果,如果只是应付了些圈复杂度等指标,一般情况下,不会有啥改善。


如何重构(对函数的拆分)?

重构分为单人开发项目和团队开发项目,如果是单人项目,就不要搞这么多微服务。多个服务整合到一个单体应用里面拉到。毕竟,微服务是跟组织架构匹配的。一个人就是一个组织,最好就负责一个应用(服务)。
重构是分颗粒度的,包含架构的重构、类和代码块的重构。可以先从小的类、代码块重构开始。等到熟悉整个架构,则可以介入架构的重构。千万不要随意去动你不熟悉的代码。

函数到底多大才应该拆分?

首先,我们应该明确什么样的函数需要拆分这个问题,是因为它是巨函数吗?那巨函数到底要多少行代码为标准呢?是1000行,100行,还是10行,甚至5行?这是一个没有正确答案的问题。那我们拆分函数的原则是什么呢?事实上,这便是 Unix的设计哲学: SRP,单一职责原则。 Do One thing, Do it Well.这样便不会需要依据多少行作为拆分函数的依据。但是,依据 SRP原则拆分函数,往往得到小函数。怎么拆分函数函数拆分遵循什么实现模式呢? Kent Beck建议使用 Compose Method的实现模式分解巨函数; Martin Flower也建议应用 Extract Method的重构手法提炼函数,两种方法殊途同归,是一种分解巨函数的有效方法。 Extract Method最重要的就是识别出代码中的抽象层次,并梳理出主干并按照自顶向下的规则实现函数的。我的经验依据几条简单的规则:

  • 实现对称性

正如 Bob大叔提到的那样,程序就像是一系列的段落,每一段落都描述了当前抽象层次的逻辑,并引用下一抽象层次的段落。

  • 过度防御式编程

过度的防御式编程,常常导致无谓的前置条件判断。事实上,错误处理需要划分信任边界,边界处校验是必须的,这个应该可以达成共识。但信任边界内,往往是没有必要的做过多的校验。否则,不仅代码可读性下降,其次导致性能下降。另外,错误处理有时应该借助于设计。我推荐大家阅读
“预防大于治疗”https://www.jianshu.com/p/718fe24c3a35,
这篇文章内包含了很多错误处理的哲学和方法。

  • 拆分函数的可读性

拆分函数后,可能存在很多小函数。虽然每个小函数都很小,但总感觉只见树木,不见森林的感觉。之所以有这个问题,我个人觉得有如下原因。很多人特别习惯于大函数,非常不习惯于回调,接口,抽象等编程思维。事实上,抽象往往是软件设计的魅力所在,也是组合式设计的重要源泉;缺失领域模型的牵引,函数虽然变小了,但终究失去载体,造成缺失领域概念来归纳和整理相关函数;没有将函数名取好。我特别建议多和周围的同事多交流,多查字典,必然会得到一个很好的领域名称;需要刻意训练重构技能,这个只能靠自己了,没有捷径。

  • 收发自如

重构是一项实践性的工程技术,通过合理地应用一系列重构手法,安全地、小步地、高效地完成代码修改。在重构过程中,应遵从最基本的重构原则:等价替换,过程可逆,随时终止,断点续传。如果我们发现自己不能随时终止,断点续传,建议大家下来做一些小练习,提高重构技能,然后在真实项目中锻炼成长。

  • 重构过程

任何优秀的程序员,都会对设计的坏味道保持敏感的嗅觉。当出现违背简单设计四个基本原则的坏味道时,则编排一系列安全的、小步的重构手法,高效地完成代码修改,使其设计逐渐靠近简单设计的四个基本原则,做到以始为终。因此,支撑重构背后的价值观和原则是最重要的。如果没有软件设计的正确价值观和良好设计原则,则会导致重构本身也是一种高成本、低收益的活动。这会导致重构既有的代码从一种风格到另一种风格,或将他人的风格重构为自己的风格,其本质并没有改善设计本身。因此,重构的基础是软件设计,价值观和原则是实践重构最本质的基础。


如何锻炼重构技能?

想提高重构或任何其他技能的方法都是一样的:

1、多练手,在实践中总结和提高,注意不是仅仅重复劳动层面的,也不是应付了事层面的,公司很多人写了很多年代码还是那个水平,就是按这两种思路做事的后果。正确的是要在练的过程中应用书上学到的新知识,要自我严格要求,做到自己能做到的最好,这样经过几次反复(做到最好->发现存在的问题->继续改进到自己认为的最好->再发现问题->再解决)就会对一些知识有深刻的认识。

2、多跟高手一起练手,自己闷头干往往进展很慢,因为很多好东西你都不一定知道,跟高手一起工作,向高手学习,甚至先模仿高手的做法然后出现问题再想办法改进,能少走很多弯路。

0

评论区