最近正在重构我的项目,并且正在看《重构》,在实际的同时总结了一些点,或者能给你一些重构或者写代码上的一些思考。
我始终认为代码构造是一个因人而异的事件,很多时候咱们其实判断一个代码的好坏往往是通过主观判断,比方同样是实现一个性能,100 行的代码并非肯定比 50 行的差;咱们没有一个正当的标杆去评判。
然而,最近我的想法变了,发现有些代码肯定是毒药,早点发现他们,往往会对于咱们当前需要的批改有莫大的帮忙。
命名
如果把整个我的项目代码比作是屋宇建造,命名就是砖头,命名的好坏间接决定了你代码 50% 的可读性。绝大部分的状况下,读者应该能够通过你函数的命名,间接理解到你这个函数的性能。
要求
- 命名要形容 具体用意 而非含糊的操作
- 性能命名不要呈现技术名词
- 整个我的项目对立命名
命名要形容具体用意
不好的比方:process、modify…
通常咱们须要应用一个 动词 + 宾语 ,比方 modifyUsername,processFile
而一个类 (对象) 的命名,通常应用名词
性能命名不要呈现技术名词
不好的比方:UserRoleMap
显然 Map 是一个技术名词,而这个对象的类型其实往往曾经能够分明的标识这个是个 map 类型。
这里想要示意的是一个用户角色名称的映射关系,集体习惯会通常命名为:UserRoleMapping 了解为映射关系
整个我的项目对立命名
最好在我的项目建设数据库的时候就对立命名,特地是针对一些专有名词的命名,能够建设一个表格。
并且很多英语单词的十分讲究的,小技巧:当你应用翻译软件翻译成一个英文单词之后,将这个英文单词再放到搜索引擎外面再去搜一遍,或者搜寻对应图片,就能晓得这个单词是否真的是你想要的
函数
管制函数长度
书本上有一句话常常被人提到就是:写的代码越少,bug 越少,所以要缩小函数长度
这句话我是不认可的 ,有的时候代码极具的缩小,可能会带来一些意外的操作,因为长度的缩小有些时候并不是 等值替换 特地是 python 这种常常能够一行搞定的状况。
然而我认可要管制函数长度,函数长度越短,性能点越集中,浏览代码速度越快。很多函数我看一眼命名就晓得要实现的性能是什么,而后测试的时候,只有输入没问题,则这个函数就能够间接跳过不看,如果函数长,那么我必须一行行的去看到底是哪一个中央呈现了问题。
不同的语言不同,函数长度管制限度不同,比方 python 往往就会短一些,java 就会长一些,因为 golang 常常还会写一些 if err != nil
会更加拖长一些。
PS:集体个别会尽量管制在 35 以内,但未严格执行 lint。
不足封装
管制函数长度之后很容易导致的一个问题就是不足封装。你必定会奇怪了,我都把原来一个 200 行函数拆成 5 个函数了,为什么你还说不足封装呢?
案例:
function test() {a = testA()
b = a.testB()
c = b.testC()
...
// 或者写为
c = a.testB().testC()
}
我也常常会写这样的代码,然而其实暗藏一些细节,才是封装的精华。提供一个常常在重构应用的思路:
将一个函数分为三段:前置条件查看,根本逻辑解决,后置返回值解决
我往往将一个函数分好之后,就会发现,函数中的几个调用尽管起源不同,然而都是在做同一个事件,职责雷同,暗藏其中的细节会对函数有更好的封装。
管制函数参数长度
之前在 java 的 阿里标准外面提到 函数的参数数量的管制,超过肯定数量就须要封装成一个类,这个没有问题,很多人也都能做到。
然而,千万不要成心把 所有的参数封装为一个对象,特地是业务属性原本就是不同的,有的时候封装成两个对象会更加复用或更加满足职责繁多的要求。
管制嵌套
Cyclomatic complexity CC 复杂度用来形容代码编写的一些复杂度,常常应用 else 或者 for 的嵌套会导致复杂度异样的高。
其实管制嵌套的实质,我常常遵循的就是上面这句话:
让你的主逻辑放弃一条直线,能不必 else 就不必,不超过 3 层嵌套
在 golang 中我会应用 gocyclo 工具类检测函数复杂度。
DRY !!!
Don’t Repeat Yourself
不要写反复代码 ,这个准则说说容易,其实做起来真的很难,因为我本人也常常陷入这个泥潭外面。
然而也不晓得是共性还是兽性,实现一个相似性能,想到的第一个反馈相对是拷贝 (CV 程序员无疑)。
所以我看完《程序员修炼之道》总结了以下计划供你参考:
- 如果你还在 feat 分支开发,反复吧,没事的
- 如果你发现一个代码反复三次,立即抽离成函数,别犹豫
- 在你提交 PR 或者进行 CR(code review) 的时候,重构反复的局部,别灰心
- 应用 lint 工具来查看反复代码
- 有时候,构造也是反复,认真点
因为在理论状况我在实际的时候,往往刚刚抽离实现,就发现业务逻辑须要被更改,导致代码又拆开来的状况,或者须要提供额定的参数。
协同工作的时候肯定要 Code Review,因为大多数状况反复代码不肯定是同一个人写的,特地是一些工具类。DRY 通常是重构中最容易发现的问题,也最容易被批改,也最容易被程序员犯错。
四个根本准则
少裸露细节
无论是函数还是类,能公有就公有,能不被里面看到就不被,很多时候,裸露的越多,调用的越多,就会有越多的谬误。
繁多职责
这也是和函数的命名无关,如果一个函数它只做一件事,那么就做好它命名的这件事,不要做多,职责繁多不便浏览也不便排查问题,也不会产生过多的依赖。
动静拆散
将代码中肯定不会变动的局部和常常会被变动的局部进行拆散,特地是一些类和变量的申明,能够将变动的局部抽离独自编写。
开闭准则
开闭准则,对扩大凋谢,对批改敞开。第一次我晓得这个准则的时候很不了解。直到一直写代码的过程中,我慢慢的明确了:
- 批改敞开:既然你不让批改,那么你依赖的就是接口,而非实现,接口的参数办法名不变,你就不会批改,你就更不会犯错。
- 扩大开发:如果你想进行性能扩大,那么两头的实现能够被扭转,通过不同的实现来扩大。
最初的正告
这是血与泪的教训~ 如果你以后的并不是在业务的开发过程中,而是在一个曾经残缺的上线或运行的业务上进行重构,请务必增加有必要的单元测试。重构最根本的要求就是保障已有的业务失常运行,而能保障这件事的绝不是程序员口中的“我这样改和原来一样”。
因为大多数重构都是没有 KPI 的,那谁也不想因为重构而背锅。
总结
重构的基本思路:
- 发现坏滋味 * 第三章
- 抽离 / 合并 / 删除 代码
- 从新测试
参考
https://zh.m.wikipedia.org/zh-hans/SOLID_(%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E8%AE%BE%E8%AE%A1)
https://book.douban.com/subject/30468597/
https://book.douban.com/subject/34986245/