软件重构

重构这个话题是老生常谈的了,无论对于C、java亦或Python程序员来讲,只要项目有一定的代码量,重构就是无可避免的。正好这段时间我正在给一个android应用项目(下文统称项目X)做重构,这个项目原本是由一个完全不会写代码的人写的,可以说项目没有任何可读性,逻辑也没有很清晰。本文我会结合自己的实践和一些参考资料谈谈我对重构的一些理解。

什么是重构?
重构是在保证不改变外部行为的前提下,对内部结构进行改变,使之易于修改和理解。
——————Martin Fowler

换句话说,重构就是保证我们的程序对于外部使用者来说是一致的,但是内部的代码做了优化。

为什么要重构?
这个问题其实很简单,就是代码写的不好。当然了,代码写的不好也是不可避免的,再nb的程序员写出来的再nb的项目也会有可优化的地方,Linus Torvalds写的项目会不会一点问题都没有?不会。有时候可能一个变量含义不清,一个函数的功能不明确,类定义有部分耦合,Linus Torvalds不是神,这些或大或小的问题总会出现的。

需要重构的情况和解决方法?
下面就简单说说那些情况下我们就需要重构代码了,你也可以对照着这些情况重新审查自己的代码是不是有类似问题。

违反了基本的代码规范
基本的代码规范包括但是不限于如下:

命名采用驼峰式,命名是有意义的,而非类似temp、data之类,private和protected命名前加m,静态变量加s,静态常量全部大写等等,这里不过多写了
魔鬼数字,将魔鬼数字定义为静态常量,并给他详细的注释,这个习惯一定要保持
可能有人说这些不属于重构范围,因为代码逻辑根本没改,但是,一个坏的变量命名和一个好的变量命名给维护的程序员的感觉是完全不同的,好的命名根本不需要注释就能知道这个变量是做什么的。

重复的代码
这个我觉得是一个最显而易见的问题,一旦你发现有段代码是复制粘贴到另一个类中的时候你就应该想想,怎么样能够复用这段代码,Don’t Repeat Yourself!

怎么样能复用同段代码,最简单的就是抽出来作为一个公共静态方法,但是很多时候这些方法不应该是静态的,这时候可以建一个helper或者delegate之类的类,两边都用这个代理函数去处理同一个逻辑。当然,我这边只是一个例子,并没有包含大多数情况。

而如果两个函数基本类似,仅仅是其中的一些变量不同,那就把这两个函数合并,通过重载的方式,以函数参数来区分。

冗长的子程序
比如在java里面,一旦你发现有个函数特别长,那肯定是不正常的(这里说的有点绝对,不过基本上是这样)。在google针对java的代码规范里有这么两条:

保证函数的功能单一性
一个函数的代码不要超过X行(这边的数字每个公司可能不一样),我所在公司规定是不超过一个屏幕,大概30行左右。
依照这个规范来讲,函数太长应该这两点都不会符合。

解决方法就是分拆函数,把过长的函数分拆为几个函数,每个函数的功能保证单一性,并为之取一个功能明确的函数名。如果几个函数都是逻辑类似的,你也可以单独拎出来作为一个类处理。

我在给X项目做重构的时候就遇到一个上传任务单这种函数,其实每个任务单表在后台会包含若干表,由于X项目没有接口层,所以客户端都是直接与后台数据库接触的,这样,上传任务单的一个功能就可以分拆为几个功能:上传任务单的人员信息,上传任务单的环境信息,上传任务单的参数信息等等,分拆为若干函数之后整合为整个上传任务单函数(这个函数里仅仅包含分拆的几个函数),这样每个函数的行数保证了不超过一屏幕。事实上,这样分拆的好处不仅如此,因为其他的上传功能也会交叉的有上述分拆函数,所以也解决了代码复用问题。

循环过长,嵌套太深
我认为没有程序员会喜欢看超多的if else,动辄十几个大括号的嵌套可能会让你很有成就感,事实上,这样的代码不可读且不好维护,此时的你成就感爆棚,一个月后呢?一年之后呢?我觉得,好的代码应该是一年之后你再次看到自己写的代码的时候,虽然不知道是自己写的,但也同样容易修改维护。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章