ITEYE中的读书笔记:重构其实就是持续改进
前段时间同事参加ITEYE的试读有奖, 没想到得了个奖,拿到一本书。由于同事的推荐我也认真读了一下试读章节,一下就入迷了,于是直接买了一本(当时还不知道他参加试读有奖活动)。上个月ITEYE又举行这个活动,我也一起参加,当时写下了这篇读书笔记。
今天无意中看到,把自己写的读书笔记又仔细看了一遍,居然无法想像是出自自己的手中,心中有些感慨,于是转到这里收藏之!
试读活动页面:http://webmaster.iteye.com/blog/2092746
==========实用主义===========
不知什么时候国内的技术人士开始流行大话技术了,不少《大话XXX》的书出现在世面上,这些书中最早也是比较经典的一本应该算是《大话设计模式》了,不得不说用这种方式来说技术问题,让不少人更容易理解,这种方式传递的应该是一种思想:实用!
从《大话重构》试读的两章中可以看出这本书应该也是本着这样的思想,正如书中所说关于重构的书籍很多,各公司的技术大佬们看的时候“激情洋溢、热血澎湃",但是到了实践中”却无所适从,经过一番苦苦挣扎之后,从此作罢“,所以看任何书都应该本着实用的角度去看,有用的我们就拿来,如果是没用就舍弃,等到有用的时候再拿出来用。
最近我们的团队在推敏捷开发,我们是一个小团队,总共也就10来个人,还分成了三个组,个别成员还是身兼多职,所以很多好的敏捷开发实践、理论、方法在我们的团队中并不实用,我们坚持”持续改进“,坚持实用主义,对我们有用的我们拿来尝试,尝试过效果不好的,就要果断舍弃,寻求更好的方法。
对于重构,我们还没有大范围的开展这项工作,但是这个计划已经提上了日程,不久的将来就会遇到这些问题,我想对于这本书或任何书应该持同样的态度:实用主义。
正如武侠大师金庸所说的“无招胜有招”,如此多的重构方法不是要让你去生搬硬套,而是应该对其进行深刻理解以后,最终变成你自己的重构方法。我们在实际工作中不要过于介意我们用了什么重构方法,哪次重构是用的哪个方法,只要是合适的设计就OK。但是,在无招胜有招之前,我们必须要有招,即学会了、理解了各个招式,在实际工作中你才能想起这些招式,去运用这些招式。
==========过度设计===========
第二章中讲的例子很好,开始的时候,本着看看这书中用什么样的重构方式的态度来看,当我随着笔者重构的思路走下去的时候,发现一个简单的例子居然用上了接口,这里不得不说接口让程序的扩展性,但是对程序的可阅读性、可维护性却大大降低。
很多时候阅读代码看到参数什么的都是接口,文档中也讲到什么地方用什么接口,可是应该用接口的哪一个实现却没有说,这让程序员们情何以堪。读到最后才发现原来笔者用了一个反面教材,原来这里是想说明什么是过度设计。
就这一章中的例子来说简单的业务应该不需要这么复杂的设计,如果真的需要,那么就必须要说明接口的各种实现,并且要在这个接口的说明中编写。我觉得在公司内部WIKI中可以这样来做:
创建建口的时候除了要说明这个接口之外,还要说明这个接口目前有哪些实现,每一种实现分别在什么情况下使用。这样无论是新程序员还是老程序员一看就能明白这个接口的用法了。
=========小步大步==========
小步还是大步是个问题。
大步往往是推倒重来,很少有人有这个勇气和这个能力。我见过一个50多岁老程序员,经常有勇气推倒重来,人家可以说是共和国高考恢复后第一批大学生,而且是数学专业,功底不是一般人能比的了得,随着一次次的重构,对业务、需求了解的深入,设计思路会逐渐的成熟更加科学,重来对他来说不是难事。
而对于大多数人和很多从其它程序员中接手过来的程序员让他们来重构的风险可想而知,推倒重来也好,小步快跑也好,都要做到很细小的细节,没有对需求的充分的认识,小步也好,大步也好都有风险,相比之下小步可能更容易控制一些。所以小步还是大步,视情况而定,大步的重构需要做好充分的准备。
如果没有底气,不如敏捷一点,定一个大目标,分解成若干个小目标,做成一个一个小迭代,每个小迭代完成后分析一下目标是否需要修正。(曾经听过一个管理高手说过一句话,计划做的好不是高手,计划改的好才是高手)
以前的一个领导的做法我觉得可以借鉴,重构前要先明确目标,是提升代码规范性,还是提升性能,还是提升扩展性。
例如:想要提升代码规范性,这一目标可能会涉及到全部代码,这领导把规范性问题总结了一下一共有若干个点,例如:
1、数据库命名规范
2、页面命名规范
3、变量命名规范
4、业务处理规范
.....
每一种规范例举几个反例,例举几个正例。
这样一来有了最终目标,有了阶段目标,而且目标清晰,有条理,无论谁来做都很清楚明白。下来就开始划分阶段,第一阶段开始数据库命名规范调整。完成以后全面测试,然后再进行下一阶段的任务。
而我所在的团队正在采取这种办法,目前所做的手术还没有遇到过提升扩展性、重构为插件式结构之类的大小术,都是以提升性能为主,之所以没有做提升扩展性之类的重构是因为目前的程序还没有达到性能的需求,这个时候做那样的重构先不说对性能有没有损失,性能优化达到目标后是不是还需要再重构扩展性都不知道。
所以我们订下了最终目标:每线程每秒钟处理7笔业务。(我们的产品涉及到多线程处理)
有了最终目标,那先要了解目前的情况,经过测试我们知道当时的情况是平均每秒钟处理4笔业务,
我们把这个目标的达成分解为:
1、单线程每秒钟处理10笔业务。
2、实现多线程处理业务。
3、多线程环境下每笔业务处理平均耗时达到100毫秒以内。
4、多线程情况下达到与CPU颗数的最佳匹配。
5、网络通讯环境下达到每秒钟处理7笔业务。
目前我们进行到了第5步。但是最开始的时候并不是这样。
1、单线程每秒钟处理10笔业务。
2、实现多线程处理业务。
3、每线程每秒钟处理7笔业务。
之所以现在的目标分解比原来多了是因为我们每进行一步的时候发现了很多问题需要去解决,随着测试的深入对于多线程的理解也更加深刻,每一个目标达成后我们都会讨论下一个要解决什么问题,从而调整目标。
虽然我们没有规范的文档,甚至代码都不规范,但是我们正一步一步向着更好的方向前进。
===================
重构的目的很简单,就是为了让产品更好,更强,但是具体下来怎么才算更好、更强,谁也说不出个标准。
只要能证明比以前好,就要用,无论是技术层面的规范、代码、需求、过程,还是管理方面的绩效考核、激励方式、文档、制度,都要遵循一个规律:世界上唯一不变的就是变化!
而敏捷开发就是应对变化最好的办法:持续改进。而重构也是一样,不变是等死,变也许死得更快,也许不一定死。借一句古话:千里之行始于足下,无论怎样重构,都是一步一个脚印走出来,想要走的稳,每一步都要扎扎实实。