代码迁移之重构

        因公司整体架构都在趋于微服务化,部分历史遗留的.Net WebAPI项目需要迁移到新的架构上,而在业务代码迁移的过程中,经常会遇到代码不精炼,冗余,结构混乱,难读懂,难维护,难扩展等各种代码的坏味道,而这些坏味道往往会造成了实际开发过程中种种问题,看不懂代码、牵一发而动全身的改动等等。这里总结下迁移代码过程中碰到3种比较常见的代码坏味道与一些最佳实践,与大家共勉。

案例1:重复代码

重复代码的坏处不言而喻,增加了代码长度,使得代码不易变化扩散,不利于扩展,同时增加了代码阅读难度。

业务背景:因为不同的业务有不同的自定义业务异常,业务处理过程中往往会出现以下代码

 

 

这段代码中大家可能已经能够看出一些代码的坏味道,两个方法中异常的处理的代码是一样的,所以我们要用提炼函数的重构方法来对这段代码进行重构。重构后我们把异常处理提炼到统一的公共方法中。

 

       其实在重复代码的检测上,我们可以借助一些外部工具,比如Visual Studio专业版自带的代码克隆检测功能,它可以帮助我们查找重复代码。通过分析菜单选择分析代码克隆的解决方案,VS会自动分析解决方案中的重复代码,这样我们能够快速定位重复代码。如下图:

 

案例2:Switch语句(Swtich Statements)

Switch语句可能是开发过程中最为常见的分支语句了,而分支语句过多会导致代码可读性差,也不利于后期代码的维护与扩展。

业务背景:根据用户不同的等级会有不同倍数的积分策略。代码如下:

 

代码分支语句虽然不算多,但如果业务变化出现了更高的等级,是否一直需要增加不同的Case?而在增加不同的策略分支时,其实也在某种程度上违背了开放封闭的原则。

所以需需简化条件表达式,用字典Strategy方式取代条件表达式(取代Switch分支语句的通用重构技巧),代码如下:

 

       把等级对应的倍数提炼到字典中,不仅精炼了代码,同时也巧妙得抛弃了Switch语句。这里是为了演示,所以把字典的映射关系放到当前的方法体中,如果考虑到封闭性,我们完全可以把字典映射放到其他地方进行维护,当业务变化,积分倍数或者等级有所变动,我们只需要维护一个字典就可以,而不需要修改核心算法的代码。

        当然这里仅仅给大家讲解了业务代码迁移过程中遇到的一个简单的例子,可能有一些业务场景的算法会比较复杂,每个分支对应的算法可能都不同,如果用分支语句的话,你会发现某一个或者某些算法改动,都会影响到整个方法体中的业务逻辑,所以这个时候我们得考虑分装变化点,将变化分装到某个类中,而这时“以多态取代条件表达式”就能够派上用场,在结合字典策略模式,可以达到封装变化、易于扩展的面向对象的设计。由于篇幅限制,这里就不在举例,可以参考:https://lostechies.com/seanchambers/2009/08/11/refactoring-day-11-switch-to-strategy/

示例3:异曲同工的类

        异曲同工可以理解为类似,也就是说两个类有很多属性都是一样的,而这样的类往往因为业务分工到不同的开发人员手中,彼此不知道已经有类似的类的定义,或者某些开发人员压根没有这方面的意识,导致了这个问题。

业务背景:插入数据的实体类与对外接口的入参实体。代码如下:

 

两个类出现了大量的相同属性,可以用提炼子类(Extract Subclass)的方式进行重构,重构如下:

 

       此示例虽然简单,但在业务开发过程中进程会碰到很多类似的情况,在实际的开发过程中可能还会遇到一个类经过好几手,程序员A增加一个属性或功能,程序员B同样也做了一些修改,慢慢你会发现类臃肿不堪,没有了一个清楚的抽象,职责不单一,类也越来越复杂。所以我们学会类的提炼与抽象,当然它必须遵循一定的原则,比如单一职责。

PS:由于对外接口的入参命名有些奇怪(历史遗留问题),遂把名字改掉。其实还有一点很多时候开发人员偷懒会把对应数据库字段的实体类直接用作对外参数实体类暴露给接口调用方,这种做法会把多余的属性暴露给外界,个人觉得是一种不好的做法。

 

        在代码迁移过程中,也遇到了一些其他代码坏味道,比较常见的是过长的方法,笔者曾今在开发过程中遇到过一个上千行代码的方法体,每次涉及到修改都非常头大,这是一个相当糟糕的做法,如果你要重构一个一望无际的方法体,我建议需要谨慎,具体的最佳实践可以参考Martin Fowler大师的《重构》这本书,这本书里还有大量的重构的最佳实践可供参考。

       还有就是以个人经历与实践来看在快速迭代开发过程中需要有统一的代码规范,以便约束开发人员,防止随心所欲的写代码,在此基础上还可以定期进行代码review,这样也可以很好的避免代码出现“大坑”。

       当然,重构不仅仅是我以上说的几个示例(仅仅是抛砖引玉),它包含的东西太多,需要不停的学习与积累,这样才能够写出优雅的代码,同时也能提高你对语言的认知。

 

posted on 2017-08-26 14:07  iloveve  阅读(773)  评论(0)    收藏  举报

导航