在工作6年的时间里遇过不少项目重构、项目重写的情况。有从PHP重写到Java,前后端一起重写;有App用 Ionic 重写,也有过同技术栈的老系统重构成新系统,更多的情况是老系统代码混乱,设计较差,业务变化时无法很好的扩展,使得代码在维护和改动时,开发成本剧增。
我认为一个软件的生命周期正常不应该低于3年,如果业务飞速发展,架构设计不够,只能撑2年也还行,这种是例外情况,毕竟业务飞速发展的情况下,软件设计的时候无法预想到更多的扩展情形,这需要非常有业务和技术经验才能做得好系统架构设计。
业务飞速发展也不是重构系统的借口,做好的话就可以避免重构的情况,要做的就是写代码的时候一直在不停的重构……
为什么要重构(Why)?
首先要理解重构和重写的区别,重构不是单纯的指重新开发,重新写代码,而是改进代码与设计。
直白的说重构就是改善现状,使得系统在扩展需求和写代码的时候更快更好、更合理。专业的定义:重构是一种对软件内部结构的改善,目的是在不改变软件的可见行为的情况下,使其更易理解,修改成本更低。
重构的目的是改善代码质量,以便不至于让代码腐化到无可救药的地步。(程序员不愿意去维护的老代码,看到就口吐芬芳…)。项目需求在每日迭代演进,代码不停的堆砌。如果没有人为代码的质量负责,代码总是会往坏味道的方向走,味道变了,发出恶臭后(混乱),项目的维护成本就慢慢的高过重新开发一套新代码的成本,这时候要想再去重构,可能就做不到,做不好,不如重新开发一个新系统。 这时候可能就是重写了。
任何优秀的代码和架构,不是在着手写的时候就可以做好的,都是慢慢迭代出来的。我们无法100%预检未来的需求,也没有足够的精力、时间、资源为遥远的未来买单,这也是避免过度设计。特别是创业公司,应该以最快、最低成本的研发达到业务需求。所以,随着系统的演讲,我们再进行重构代码。
当我们真正遇到问题时,就应该着手重构,而不是说先这样,日后再改(重构),慢慢的就改不动了。重构代码其实对一个程序员的编码能力提升有很大的帮助的。有句话是这么说的:初级工程师在维护代码,高级工程师在设计代码,资深工程师在重构代码。 (这里的级别不是职称,就是个能力的概念)。
到底重构什么(What)?
重构分为大型重构和小型重构。大型重构指的是对顶层代码的设计的重构,包括:系统、模块、代码结构、类与类之间的关系等的重构,重构的手段有:分层、模块化、解耦、抽象可复用组件等。
小型重构指的是对代码细节的重构,主要是针对类、函数、变量等代码级别的重构,比如规范命名、规范注释、消除超大类或函数、提取重复代码等等。
不管是大型重构和小型重构,都需要用到设计思想、原则和模式。
何时重构(When)?
把一个系统当做我们的健康身体,我们不能等到代码烂到一定的程度(身体出现问题)之后才去重构(锻炼、改善饮食、不熬夜)。当身体出现大问题,就不能像健康的身体那样能承受日常生活的压力,日久就会加剧,而锻炼和端正作息的行为的目的就是让身体恢复到健康,这时候的目的就降了一个级别了。以前你身体也健康,也有理想去实现,现在理想变成梦想,理想变成了身体健康。所以,我们需要一开始就要保证身体健康,才能继续的去为了生活、未来目标、理想奋斗。重构就是身体健康的保证。
项目代码拉倒一定程度后,开发效率低,招了很多人,天天加班,出活率低,线上bug频发,领导发飙,管理束手无策,工程师抱怨不断,查bug难。这时候再重构也是比较晚的了,可能也无法解决问题。
和健康生活保障健康一样,日常就需要锻炼、不熬夜、按时吃饭。平时如果不注重代码质量,堆砌烂代码,实在维护不了了就大刀阔斧地重构,甚至重写代码,也不是一种可持续、可演进的方式。
何时重构的答案就是持续重构,日常迭代需求,修改代码的时候,顺手把不符合规范、不好的设计重构一下,这是最好的时机,因为之前的代码可能预想不到此时的业务需求,写得不够,当前需求完善的时候就应该改进该处代码,保证日后的可扩展性、易读性、健壮性等。
项目团队中要把单元测试、Code Review 作为开发的一部分,把持续重构作为开发的一部分,成为一种习惯,对项目、对自己都会很有好处。
该如何重构(How)?
大型重构时,需要提前做好重构计划,然后按阶段来进行。每个阶段完成一小部分代码的重构,比如一次最多动一个微服务,做好测试覆盖,上新版本,保留旧版本预后等。控制重构的影响范围,兼容业务和老代码,必要的时候都会写一些类似适配器的过渡代码。
大规模高层次的重构需要有组织和计划,也要有经验和熟悉业务的资深同事来主导。小规模低层次的重构因为影响范围小,改动耗时短,随时有时间都推荐去做,避免堆积后期改不动了。
重构这件事,需要团队中的资深工程师和项目leader负起责任。对代码放任不管时,有人堆砌了烂代码,日后也会更多的烂代码。
保持代码质量最后的方法是打造一种好的技术氛围,以此来驱动大家主动去关注代码质量。
参考资料 《设计模式之美》