vlambda博客
学习文章列表

代码规范实战吐槽(1)

这边工作的一个新功能,需要跨模块调用其他服务,项目采用的是Client远程调用方式。想必大家都不陌生吧,那么 故事就这么开始了:


1、首先搜索找到了XXClient接口,如图:

看似没什么问题,但如果仔细点则会发现返回值ZmResult包装对象有警告(Eclipse默认会有警告,Idea默认不会提示,也可能是我无意中修改过配置,查看警告:

代码规范实战吐槽(1)

Q1: 那为什么会有警告呢?换句话说:如果不指定泛型,可能有什么问题?

A1: 若不指定泛型,接口调用方可以使用任意泛型类型来接收其返回值,并且编译期不会报错,最多只会有警告。等等!这不挺好吗?

抱歉,使用错误的泛型类型接收,程序运行时会报类型转换错误。

PS开发人员很可能无意地使用错误的类型接收返回值,而接口返回指定明确的泛型类型则可以在编译期避免这一问题。

代码规范实战吐槽(1)

(使用错误的泛型类型接收,不会报错,仅有一条警告)



2、如果我们需要调用该接口,则需要知道接口的返回值是什么。因此,我们通过搜索path ("getOnLinePass"),找到对应的Controller

代码规范实战吐槽(1)

打开Controller,发现其返回值还是没有指定泛型,因此我们找到return对象申明的类型,wocao,是List<JSONObject>,也就是说数据的字段都隐藏在JSONObject中,这里Controller方法的代码比较短,能一眼看出来方法return的地方,但倘若代码逻辑稍长,或者是嵌套直接返回的另一方法的返回值,那么找返回信息的酸爽直接翻倍。

Q2方法不指定返回值的泛型类型有什么问题?

A2不指定泛型类型,就可能会产生下图的问题,错误地返回了完全不同类型的结果,但是编译不报错。但是调用方一旦遇到这个问题,则会产生同样的类型转换问题。而这一切,若加上泛型类型,则均可以在编译期完全避免。

代码规范实战吐槽(1)

PS不要把不指定泛型当做返回任意类型的工具,如果业务必须返回多种数据类型,请返回Object、Map、JSONObject、JSONArray等具体类型,指明方法返回值泛型类型,并且添加注释说明本方法可能返回的不同数据格式。


3、看来,还得继续挖,打开Service,发现返回值为List<JSONObject>,是直接返回Mapper返回值。


4、打开Mapper,映入眼帘的是一大段SQL,所以我们终于找到了返回值,至于查看具体返回了哪些字段的阅读性不用提。

(真的是一大段,图中的SQL经过删减,"......"也是后来加上去的)


5、你以为就这么完了吗?回到我的出发点:调用查询优惠券接口并得到相应的优惠券信息。现在拿到字段了,但是这些字段的含义是什么,SQL中并没有注释,也不合适添加注释在SQL中。So,咱们查看下查询的表对应的Entity实体对象,再核对查询返回的字段对应的实体类中注释含义(万幸的是咱们实体类是工具生成的,属性都自带注释)。不就再看一个对象属性吗?很遗憾,这个SQL是多表关联查询……


6、当然我们还得复制SQL中返回的字段名,然后在调用方vo.get("paramName")取出数据(更别提什么属性类型错误;什么接口修改返回值字段名,但调用方没改了)。


到这里,差不多就结束了,回顾一下原本的工作的两种情况。

正常情况下,只需要注入XXClient接口,调用方法并使用指定的返回值类型接收,vo.getParam()就能得到想要的数据。

而这一次调用XXClient接口却让我差点放弃,并写出了这篇文章。



最后,强烈推荐《阿里巴巴Java开发手册》,以及《Effect Java》。