大家所在项目组,一定遇到同类操作,但却有不同做法,尤其是祖传代码,一眼望去,可谓八仙过海各显神通。
大部分程序员也觉得团队开发应该保持编程习惯的一致性。但普遍理解的一致性都表现在较宏观层面,比如,数据库访问是叫DAO还是叫Mapper,Repository?
团队虽然也有一些统一标准,但落地到编码,也没人一直给你 CR,所以要求就不是那么严格了。所以,我们才能欣赏到在代码写法百家争鸣。还是具体看几个案例来体会下吧!
千奇百怪的命名
这段代码可以了解到目前的分发渠道:
- 网站
- 只在Kindle
- 全渠道
乍一看,你可能觉得没啥问题,可我就会好奇作者:
- WEBSITE 和 KINDLE_ONLY 分别表示什么?
- WEBSITE:作品只会在我们自己网站发布,KINDLE_ONLY:这部作品只会在 Kindle 的电子书商店里上架。
- 二者是不是都表示只能在单独一个渠道发布?
Yes
- 既然含义类似,为何不都叫 XXX 或 XXX_ONLY?
(⊙o⊙)…好像也是哦
所以,大家也看到了吧,类似含义的代码应该有一致的名称,就像很多团队都会把业务写到服务层,各种服务类类名也都是 XXXService。
不一致的名字,一般都表示不同含义。比如,对那些非业务入口的业务组件,它们的名字就会不同,会更符合其具体业务行为,如BookSender:将作品发到翻译引擎。
我料想,这段代码作者给枚举值命名时,只分别考虑了应该叫啥名,却忽略了这个枚举值在整体中的地位。
至此,重构途径就很明白了:
方案不一致
现在某系统要向另外一个系统发请求,需带一个时间戳,把这个时间戳按格式转成
String,主要做传输用,便于外部系统识别,也方便开发调试。
代码片段本身实现没问题,甚至还考虑到了 SimpleDateFormat 这个类非线程安全,所以,每次都创建一个新的 SimpleDateFormat 对象。
那我为什么还说它是有问题的呢?因为这种写法是 Java 8 之前的写法,而我们用的 Java 版本是 Java 8。
现在这是个Java8项目,完全可以使用 Java 8 的新日期时间API。所以项目也约定所有日期时间类型使用新API。
所以,这段代码本身实现没问题,但放在项目整体中,却没有和其它部分保持一致。
重构成使用新API即可:
一个项目应对同一个问题出现多个解决方案,没有统一约定,成员会根据自己的习惯随机选择方案,导致方案不一致。还比如判断字符串是否为空或空串,就有 Guava 和 Apache Commons Lang,都能做同样事情,所以,程序员也会根据自己熟悉程度选择其中之一来用,造成代码不一致。
这两个程序库是很多程序库的基础,经常因为引入了其它程序库,相应的依赖就出现在我们的代码中。所以,我们必须约定,哪种做法是我们在项目中的标准做法,以防出现各自为营。
代码中的不一致
在翻译引擎中创建作品的代码:
- 首先,根据要处理的作品 ID,获取其中已审核通过的作品
- 然后,发送一个 HTTP 请求在翻译引擎中创建出这个作品
看得出来什么问题吗?
这些代码不是一个层次的!首先是获取审核通过的作品,是个业务动作,接下来的三行其实是在做一件事,也就是发送创建作品的请求,这三行代码:
- 创建请求的参数
- 根据参数创建请求
- 最后把请求发送出去
三行代码合力完成发送创建作品的请求,而这件事整体才是个完整业务动作。
所以,这个函数有的是业务动作,有的是业务动作的细节。所以重构如下:
分清代码处于不同层次,基本功就是分离关注点。一旦分解出不同关注点,还可进一步调整代码的结构。
像前面拆分出来的这个方法,我们已经知道它的作用是发出一个请求去创建作品,本质上并不属于这个业务类的一部分。
所以,还可通过引入一个新模型,将这个部分调整出去: