大道化简,重构的艺术

这个题目貌似很大,有成为标题党人的嫌疑。其实我想说的是一些小事,就是我小时候经常去小渠里抓鱼。而抓鱼的方式也很简单,就是拿砖块,泥巴把小渠的两头堵起来,然后把中间的水舀出去。

 

软件为什么要重构?那是因为你感觉不够好。之所以感觉不够好,原因可能会很多。我想,最严重的一个可能就是设计混乱。设计混乱牵扯的方面很多,有依赖上的,有调用上的。也有根本实现不了目的,或者很难扩展。有很多人重构时候干脆就是把代码重写一遍,这种方式固然是好,但是成本太高。有时候无法接受重新梳理一遍代码的工作周期。

 

如何渐进地进行重构不得不摆在我们面前,而我没有珍惜,等............

 

对于依赖关系错误的重构是最为复杂的。这个复杂表现在必须重新理顺依赖关系,然后得出解决的方案。而代码调用让人头疼的地方,我想主要在于,没有重用和过度重用两种。扩展上的问题需要重新梳理业务规则,才能制定方案。

 

毛病很多,头疼医头,脚疼医脚,还真是麻烦。其实最根本的方法还在于学会养生,修炼内功。但路总要一条一条走,饭要一口一口吃啊。遇到这么多复杂的问题,还需要化繁为简。这里的化繁为简在我看来和我小时候抓鱼差不多,需要能够对大量的工作进行截断,一个阶段一个阶段地进行重构。这样才能达成渐进的重构目的。

 

如何进行工作量的切断,方法很多,但是有个根本的思想在于理清依赖。比如,类B调用了类A,那么B就对A产生了依赖。现在需要对A进行调整,那么就有很大可能对B的正常运行产生影响。如何能隔离B和A,这就需要给A定义规范。这也就是对A进行抽象,提炼出接口IA,那么不管你A怎么变,你符合IA接口的话,就可以给B使用。IA就像我抓鱼时候筑的那条小坝,虽然很小,却很能解决问题。

 

为什么这样可以解决问题?这就在于,任何一个消费者不会需要知道生产者的一切东西。那么只要把消费者需要的东西拿到就可以。MVC,MVP,三层架构都是大坝,是水渠的两边。而大半框架都是进行水平的划分,垂直的划分一般是以业务来划分。所以,如果软件已经实现了水平的划分,重构起来要轻松很多。那样只需要对业务的垂直划分进行逐步的改造。而如果水平划分没有做,那就惨了,理清头绪都不是件容易的事情。

 

事实上,重构远没有上面描述的那么简单。比如,以前项目中一直使用ExtJS进行界面的开发,现在想减小JS的比重,因此想改用JQuery+HTML+CSS来替换Ext的控件,那改造起来也是很复杂的事情。一次性全部更新的代价很高,出错机会很大,并且不容易形成规范。需要像国家改革一样形成试点,逐步推广。从这里也可以看出,重构不一定是OO的重构,除非你达到了一切皆是OO的境界。

posted @ 2010-02-10 19:10 Birdshover 阅读(2255) 评论(7) 编辑 收藏

 回复 引用 查看   
#1楼2010-02-10 22:49 | Kurodo      
支持老谢一下
 回复 引用 查看   
#2楼2010-02-11 00:30 |       
重构的最高境界 就是推翻自己以往的作品。

几乎大部分人总是说:下一个项目一定XXX,一定用上XXX架构,一定引入XXX设计。

但是几乎没有什么人会说:上次的项目一定XXXXX。

只有对已有的成绩去否定再肯定,才能前进。不过似乎人都很懒,既然过去的东西都做出来了,何必再搞?不如着眼在新的项目。

于是,项目质量总是在一个玻璃天花板下徘徊。

 回复 引用 查看   
#3楼2010-02-11 03:23 | 诺贝尔      

重构的原因,在于需求的变化。需求没有变化,也就没有必要瞎折腾来重构,除非你真很蛋疼。

需求变化有两种原因,一,是真的变化了。二,对需求的认识深化了。

旧的需求,转化到新的需求,设计就要跟着变化。当然也不是所有情况都需要大变动,很多需求变化,没有涉及到“筋骨”,就可以保持设计的骨架,而添加新的内容。

一个优秀的设计,应该精良预示到这种简单的需求变化。

如果真的要改变,那哪些设计会比较容易更改呢?

类设计有两种观点,一是从自身出发,该类应该有哪些操作,就建立这些操作。二是从需求出发,别人需要该类有什么操作,他就应该提供这些操作。

我的看法是,从需求出发,建立的是概念切面,也就是接口。从自身出发,建立的是具体实现。当类调用其他类,使用的是接口,而当编写类自身代码时,又应该从自身出发。接口比类可能要小,也可能要大。而当接口比类要大,显然需要多个类才能支持完整的接口,这时候可能就需要建立简单的包装类。

接口往往是很稳定,但是,当需求变化的时候,设计变更的时候,变化的是什么?就是接口。

接口虽然变了,但是类还生存,并且,因为类是从自身出发的,有理由相信在新的接口面前也不需要变化。我们可以设计新的接口,并大量使用已有的实现在完成新的接口的支持,当然,免不了要添加新的类,和废置很多旧的类,因为这就是需求在变化了。




 回复 引用 查看   
#4楼2010-02-12 06:08 | 电机拖动      
鱼肉啊,几百年不见,你小子还是喜欢想啥说啥啊,哈哈

好,兄弟也来小凑个热闹
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

关于重构,既同意也反对

我很同意你说的“需要像国家改革一样形成试点,逐步推广”,整个符合你说的“成本”
但你既然提到了“成本”,为什么又不充分考虑“成本”呢?我不知道你小子现在做的是什么,是服务还是外包?如果是服务的话,那好说,相当于产品的升级,成本本来就是预算好的;那如果是外包呢?时间、人力、物力的预算几乎为0,咋搞?在我眼里,国内的外包行业,想要出现重构这么个事情,那简直比在大二以上的学生中找个处女还难!就算是那些什么一期、二期、三妻、四妾的,有boss愿意花钱重构?就算愿意花钱,但花不起那时间,反正程序能用就ok,大不了重新再弄个项目做而已。国内的外包行业目前是极度畸形!重构?项目开始时能用上个像样的框架就已经很不错了。再说服务性质的项目,那些就算你是一步一步来,总有一步,你需要跨得很大,比如存储,这东西绝对不是今天你改两下明天我改两下就能ok的,搞不好就因为存储的变动,整个项目就得开始弄下一个major version了……当然了,数据量小且数据类型也少的东西,这样变变也无妨,具体问题具体分析了

~~~~~~~~~~~~~~~~~~~~~~~~~~

喝了点酒,表达不是很清楚,有空慢慢讨论,哈哈

 回复 引用 查看   
#5楼2010-02-12 10:35 | 努力去偷懒      
做产品,这文章是很有价值,但如果在做业务系统,客户哪天心情不好,或者什么心血来潮的话,有或者那么几天比较特殊的,业务逻辑啊什么的就得改了。任何事物都有其存在的价值,虽然它有很多缺点,任何事情都有其两面性,没有完全的正确,也没有完全的错误,关键是你如何去满足你的需要,让你觉得合适就好。

所有项目,都不是完美的,因为人的思想会不断地进步,会不断地有想法,会不断的质疑之前的设计是否最合适,技术的更新换代,也会导致很多东西需要去改进,因此,以满足需求为出发点,以工作效率为基准,去衡量你该怎么去设计,怎么去实现。

 回复 引用 查看   
#6楼2010-02-18 21:52 | 深山老林      
重构意味着额外的成本增加。
跨度大的重构一般有两个前提条件:
1.TDD。
2.持续集成。
否则,跨度较大的经常重构会让测试人员哭死的。

 回复 引用 查看   
#7楼[楼主]2010-02-20 13:12 | Birdshover      
@电机拖动
恩,好久没见了,呵呵