下载本文示例代码
本文转自csdn,文中内容不代表本站观点,仅提供参考。 重构是一个“永恒的话题”,只要开发在持续,那么重构就会一直伴随着我们。
但是,“重构”本身并不是一个很容易做到的事情。并不是读了本《重构:改善既有代码的设计》就会重构了。
这半年多来,各大技术站点都在热炒SOA、AJAX、敏捷,却鲜有文章谈论“重构”。事实上,目前国内软件行业的还是非常匮乏经验丰富的构架师和高级研发人员,而“重构”则是这两类技术人员必须修炼的基本功课。
但是,在国内搞开发,能够实践“重构”的机会并不是很多。很多人扎根进项目繁琐的需求变更中,而无暇顾及“回头整理整理思绪,整理整理代码”。特别是在“平台泛滥”的项目实施中,大量的实施人员都在考虑“如何在现有的平台和框架下实现功能”,很少考虑“代码结构是否有改善的空间”。
俺这几年大部分时间都是跟产品研发打交道,所以幸运的属于那一小部分“比较容易有机会实践重构”的人群。当然,比起在TW公司的那些哥们来说,比他们还也有些不幸,毕竟能够向TW那样“非常崇尚敏捷”的公司不多。
比上不足,比下有余,自然有一番自己的体会。前段时间又玩了一把“重构”,是重构一个命令行处理类的,把一些心得说一说。
单纯的修改代码与重构不一样的
单纯的修改代码,与重构是有很大差别的。可能你对某个Component并不很熟悉,但是通过Debug和Track,还是能够比较容易的“Edit Code”或者“Fix Bug”。但是这跟重构的差距还是很远。
举个例子:来到CDC这边快一年了,经历了两个“maintenance version”的开发和目前正在进行的“major version”的研发。之前的两个“maintenance version”只是Fix Bug,而且并没有多少参考资料,基本上只能依靠自己的Debug和Track手段来分析、跟踪、定位Bug,然后修正它。那段时间我们都在嘲弄自己“阅读代码基本靠猜,修改代码基本靠蒙”。可想而知,那时候,在旧有的代码中定位Bug和修改Bug尚且是一个非常困难的事情,根本没有“重构”的可能性。——但是我们还是很成功的修改很多Bug,这也意味着修改了很多代码。对我们来说,唯一的收获就是对旧有的代码结构有所了解了,间接的吸收了国外那些senior architecture的设计思想。
但是,在进行两个“maintenance version”的开发的过程中,我们没有任何的“重构”行为。
重构的基本前提:理解原有的设计意图
重构的基本前提就是你必须对“旧有的代码结构比较熟悉”。当然,如果能够了解最初的设计思路,就更容易去重构现有的代码结构了。但很多情况下,我们只能通过阅读代码来“推测”原作者的设计意图。
比如最近正在重构的一个命令行类。这个命令行类用于维护Application的Upload、Deploy等等十几个复杂的操作。
大致的类方法结构如下(真实的类比这更为复杂):
(主函数) main(String[])
(处理任务函数) task(String[])
(执行任务) :.action()
(执行某个任务) :.deploy(Application, XiNode)
(执行某个任务)········
(退出) :.exit(String, int, int)
(初始化) :.init()
(解析参数) :.parse(String[])
(打印帮助) :.usage()
(打印某个任务帮助) :.usageDeploy()
(打印某个任务帮助)········
(验证输入参数) :.validate()
很明显,这个旧有的代码类带有这非常明显的“面向过程”的思维模式,当然,这是很多“命令行”类的通病。在最初构建命令行类的时候,任务比较少,代码行数和方法也就比较少,复杂的设计可能反而影响代码的构建效率,这样“流水式”的设计可能更容易实现和维护。
为了更容易说明问题,画了一张简易的“思维图”来诠释原始作者的设计意图(这个设计意图仅是依据阅读代码而分析出来)。
如果你能够理解旧有代码中作者的基本设计意图,那么你就基本上可以开发重构了。当然,可能会存在某些细小的地方,在你阅读代码的时候遗漏掉(毕竟没有完整的设计文档),但是这对“重构”的影响不是很大,把握注关键的一些设计意图,其他的可以在重构过程中慢慢体会和学习。
重构的欲望与方向:让现有的代码实现更容易扩展
如果你是一个拥抱Agile的开发人员,“重构”肯定会紧紧围绕在你的思维中。而作为开发人员,也应该时刻有重构的欲望。
事实上,上面那个命令行类,已经很成熟了。在经过几年的补充之后,已经需要支持十几个任务了。我们姑且用ApplicationManage来代替这个命令行类的名称。很多年以后,这个类成为一个非常“臃肿”的类,一个2000多行的类。
这个类的命令模式大致这样,每个任务都有自己特定的一些参数:
ApplicationManager –upload –domain AAA –archive user ······
ApplicationManager –deploy –domain AAA –app appname ······
如果这个时候,你需要新增一个任务,比如我们需要达到这样的效果:
ApplicationManager –newtask –domain AAA –file tesfile ······
这个时候,你必须修改ApplicationManage很多地方的代码:按照原有的代码逻辑和结构在不同的地方增加代码:
我需要在解析输入参数的地方,增加对几个新的参数的解析。
我需要在校验的地方,增加对新参数的解析
我需要增加对新Usage的支持代码
我需要增加对新任务处理的支持代码
新增一个新任务的支持,代码是并没有任何难度,也不复杂,但是我却要在一个类的很多处来回修改,要知道,这是一个2000行的类啊。——这就是“代码的坏味道”。
是的,如果这个时候,当你面对这么“难以忍受”的修改代码的时候,就需要萌发了“重构”的欲望。我们无须为“重构”寻找很多冠冕堂皇的理由,只此一条就足够了:觉得有更好的实现结构可以让我们扩展起来更容易。
重构的抉择:进行还是放弃?
当你想重构的时候,你就一定能够重构吗?这是需要进行时间成本、风险估算的问题。
ApplicationManager经过几年的发展,已经相当稳定。而Feature Freeze是时间是不允许被更改的。即使旧有的代码比较“臃肿”,但是经过时间检验的稳定性、正确性是无法被推翻的。结局只有一个:只能在旧有代码上添砖加瓦,来新增一个新任务的处理。
重构的计划就这么被迫放弃吗?
当然不应该放弃。可被用来修炼重构的机会本身就不多,“猎物就在眼前,怎能轻易放弃呢?”
是的,我不能把“重构”的代码提交到svn中,但是我可以在sandbox中进行啊。“重构,不一定非要在真实项目代码中”。事实上,在真实项目代码中重构是“非常危险”的行为,除非你有足够的时间和完整的设计思路,或者你的项目经理已经批准你进行比较大范围的代码修改。否则最好是在“sandbox”中实践和预研你的想法吧。
客户并不关心代码的实现好坏,只关心“功能、效率、稳定性”。有人会站出来把“扩展性”补充进来,是的,客户也关心“扩展性”,但是客户关注的“扩展性”只是外围的扩展,而真正很多内部实现的代码结构是“对客户透明的”,客户也不是关心那部分对其毫无“意义”的内部代码实现。
记住这个吧:没有人可以阻止你在“sandbox”放入你的想法和你的实践,除了你自己。——当然,你必须协调调好你的时间、你的工作。
晚上9点钟,当坐在家中电脑前的时候,谁还能阻止我们把自己的想法在“sandbox”中实践呢?灵感有时候是来自寂静的深夜!—— 但是,切忌不要过度熬夜,华为那个俺本家兄弟(姓胡)的命运值得俺们所有开发人员“警醒”。
共3页。 1 2 3 :
本文转自csdn,文中内容不代表本站观点,仅提供参考。 重构是一个“永恒的话题”,只要开发在持续,那么重构就会一直伴随着我们。
但是,“重构”本身并不是一个很容易做到的事情。并不是读了本《重构:改善既有代码的设计》就会重构了。
这半年多来,各大技术站点都在热炒SOA、AJAX、敏捷,却鲜有文章谈论“重构”。事实上,目前国内软件行业的还是非常匮乏经验丰富的构架师和高级研发人员,而“重构”则是这两类技术人员必须修炼的基本功课。
但是,在国内搞开发,能够实践“重构”的机会并不是很多。很多人扎根进项目繁琐的需求变更中,而无暇顾及“回头整理整理思绪,整理整理代码”。特别是在“平台泛滥”的项目实施中,大量的实施人员都在考虑“如何在现有的平台和框架下实现功能”,很少考虑“代码结构是否有改善的空间”。
俺这几年大部分时间都是跟产品研发打交道,所以幸运的属于那一小部分“比较容易有机会实践重构”的人群。当然,比起在TW公司的那些哥们来说,比他们还也有些不幸,毕竟能够向TW那样“非常崇尚敏捷”的公司不多。
比上不足,比下有余,自然有一番自己的体会。前段时间又玩了一把“重构”,是重构一个命令行处理类的,把一些心得说一说。
单纯的修改代码与重构不一样的
单纯的修改代码,与重构是有很大差别的。可能你对某个Component并不很熟悉,但是通过Debug和Track,还是能够比较容易的“Edit Code”或者“Fix Bug”。但是这跟重构的差距还是很远。
举个例子:来到CDC这边快一年了,经历了两个“maintenance version”的开发和目前正在进行的“major version”的研发。之前的两个“maintenance version”只是Fix Bug,而且并没有多少参考资料,基本上只能依靠自己的Debug和Track手段来分析、跟踪、定位Bug,然后修正它。那段时间我们都在嘲弄自己“阅读代码基本靠猜,修改代码基本靠蒙”。可想而知,那时候,在旧有的代码中定位Bug和修改Bug尚且是一个非常困难的事情,根本没有“重构”的可能性。——但是我们还是很成功的修改很多Bug,这也意味着修改了很多代码。对我们来说,唯一的收获就是对旧有的代码结构有所了解了,间接的吸收了国外那些senior architecture的设计思想。
但是,在进行两个“maintenance version”的开发的过程中,我们没有任何的“重构”行为。
重构的基本前提:理解原有的设计意图
重构的基本前提就是你必须对“旧有的代码结构比较熟悉”。当然,如果能够了解最初的设计思路,就更容易去重构现有的代码结构了。但很多情况下,我们只能通过阅读代码来“推测”原作者的设计意图。
比如最近正在重构的一个命令行类。这个命令行类用于维护Application的Upload、Deploy等等十几个复杂的操作。
大致的类方法结构如下(真实的类比这更为复杂):
(主函数) main(String[])
(处理任务函数) task(String[])
(执行任务) :.action()
(执行某个任务) :.deploy(Application, XiNode)
(执行某个任务)········
(退出) :.exit(String, int, int)
(初始化) :.init()
(解析参数) :.parse(String[])
(打印帮助) :.usage()
(打印某个任务帮助) :.usageDeploy()
(打印某个任务帮助)········
(验证输入参数) :.validate()
很明显,这个旧有的代码类带有这非常明显的“面向过程”的思维模式,当然,这是很多“命令行”类的通病。在最初构建命令行类的时候,任务比较少,代码行数和方法也就比较少,复杂的设计可能反而影响代码的构建效率,这样“流水式”的设计可能更容易实现和维护。
为了更容易说明问题,画了一张简易的“思维图”来诠释原始作者的设计意图(这个设计意图仅是依据阅读代码而分析出来)。
如果你能够理解旧有代码中作者的基本设计意图,那么你就基本上可以开发重构了。当然,可能会存在某些细小的地方,在你阅读代码的时候遗漏掉(毕竟没有完整的设计文档),但是这对“重构”的影响不是很大,把握注关键的一些设计意图,其他的可以在重构过程中慢慢体会和学习。
重构的欲望与方向:让现有的代码实现更容易扩展
如果你是一个拥抱Agile的开发人员,“重构”肯定会紧紧围绕在你的思维中。而作为开发人员,也应该时刻有重构的欲望。
事实上,上面那个命令行类,已经很成熟了。在经过几年的补充之后,已经需要支持十几个任务了。我们姑且用ApplicationManage来代替这个命令行类的名称。很多年以后,这个类成为一个非常“臃肿”的类,一个2000多行的类。
这个类的命令模式大致这样,每个任务都有自己特定的一些参数:
ApplicationManager –upload –domain AAA –archive user ······
ApplicationManager –deploy –domain AAA –app appname ······
如果这个时候,你需要新增一个任务,比如我们需要达到这样的效果:
ApplicationManager –newtask –domain AAA –file tesfile ······
这个时候,你必须修改ApplicationManage很多地方的代码:按照原有的代码逻辑和结构在不同的地方增加代码:
我需要在解析输入参数的地方,增加对几个新的参数的解析。
我需要在校验的地方,增加对新参数的解析
我需要增加对新Usage的支持代码
我需要增加对新任务处理的支持代码
新增一个新任务的支持,代码是并没有任何难度,也不复杂,但是我却要在一个类的很多处来回修改,要知道,这是一个2000行的类啊。——这就是“代码的坏味道”。
是的,如果这个时候,当你面对这么“难以忍受”的修改代码的时候,就需要萌发了“重构”的欲望。我们无须为“重构”寻找很多冠冕堂皇的理由,只此一条就足够了:觉得有更好的实现结构可以让我们扩展起来更容易。
重构的抉择:进行还是放弃?
当你想重构的时候,你就一定能够重构吗?这是需要进行时间成本、风险估算的问题。
ApplicationManager经过几年的发展,已经相当稳定。而Feature Freeze是时间是不允许被更改的。即使旧有的代码比较“臃肿”,但是经过时间检验的稳定性、正确性是无法被推翻的。结局只有一个:只能在旧有代码上添砖加瓦,来新增一个新任务的处理。
重构的计划就这么被迫放弃吗?
当然不应该放弃。可被用来修炼重构的机会本身就不多,“猎物就在眼前,怎能轻易放弃呢?”
是的,我不能把“重构”的代码提交到svn中,但是我可以在sandbox中进行啊。“重构,不一定非要在真实项目代码中”。事实上,在真实项目代码中重构是“非常危险”的行为,除非你有足够的时间和完整的设计思路,或者你的项目经理已经批准你进行比较大范围的代码修改。否则最好是在“sandbox”中实践和预研你的想法吧。
客户并不关心代码的实现好坏,只关心“功能、效率、稳定性”。有人会站出来把“扩展性”补充进来,是的,客户也关心“扩展性”,但是客户关注的“扩展性”只是外围的扩展,而真正很多内部实现的代码结构是“对客户透明的”,客户也不是关心那部分对其毫无“意义”的内部代码实现。
记住这个吧:没有人可以阻止你在“sandbox”放入你的想法和你的实践,除了你自己。——当然,你必须协调调好你的时间、你的工作。
晚上9点钟,当坐在家中电脑前的时候,谁还能阻止我们把自己的想法在“sandbox”中实践呢?灵感有时候是来自寂静的深夜!—— 但是,切忌不要过度熬夜,华为那个俺本家兄弟(姓胡)的命运值得俺们所有开发人员“警醒”。
共3页。 1 2 3 :
下载本文示例代码
重构的修炼:从重构命令行操作的实践来谈重构的修炼:从重构命令行操作的实践来谈重构的修炼:从重构命令行操作的实践来谈重构的修炼:从重构命令行操作的实践来谈重构的修炼:从重构命令行操作的实践来谈重构的修炼:从重构命令行操作的实践来谈重构的修炼:从重构命令行操作的实践来谈重构的修炼:从重构命令行操作的实践来谈重构的修炼:从重构命令行操作的实践来谈重构的修炼:从重构命令行操作的实践来谈重构的修炼:从重构命令行操作的实践来谈重构的修炼:从重构命令行操作的实践来谈重构的修炼:从重构命令行操作的实践来谈重构的修炼:从重构命令行操作的实践来谈重构的修炼:从重构命令行操作的实践来谈