程序员你为什么这么累【续】:编码习惯之参数校验和国际化规范

导读:

今天我们说说参数校验和国际化,这些代码没有什么技术含量,却大量充斥在业务代码上,很可能业务代码只有几行,参数校验代码却有十几行,非常影响代码阅读,所以很有必要把这块的代码量减下去。

今天的目的主要是把之前例子里面的和业务无关的国际化参数隐藏掉,以及如何封装好校验函数。

今天累,少说话多贴代码,先看对比图,修改前:

service

修改后:

services

Controll的非业务代码如何去掉参考我的编码习惯 - Controller规范,下面说说去掉Local参数。

强调一下:业务代码里面不要出现和业务无关的东西,如local,MessageSource 。

去掉国际化参数还是使用的技术还是ThreadLocal。国际化信息可以放好几个地方,但建议不要放在每一个url上,除了比较low还容易出很多其他问题。这里演示的是放在cookie上面的例子:

UserUtil

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class UserUtil {
private final static ThreadLocal<String> tlUser = new ThreadLocal<String>();
private final static ThreadLocal<Locale> tlLocale = new ThreadLocal<Locale>() {
protected Locale initialValue() {
// 语言的默认值
return Locale.CHINESE;
};
};
public static final String KEY_LANG = "lang";
public static final String KEY_USER = "user";
public static void setUser(String userid) {
tlUser.set(userid);
// 把用户信息放到log4j
MDC.put(KEY_USER, userid);
}
public static String getUser() {
return tlUser.get();
}
public static void setLocale(String locale) {
setLocale(new Locale(locale));
}
public static void setLocale(Locale locale) {
tlLocale.set(locale);
}
public static Locale getLocale() {
return tlLocale.get();
}
public static void clearAllUserInfo() {
tlUser.remove();
tlLocale.remove();
MDC.remove(KEY_USER);
}
}

CheckUtil,这里需要得到用户的语言

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package plm.common.utils;
import org.springframework.context.MessageSource;
import plm.common.exceptions.CheckException;
public class CheckUtil {
private static MessageSource resources;
public static void setResources(MessageSource resources) {
CheckUtil.resources = resources;
}
public static void check(boolean condition, String msgKey, Object... args) {
if (!condition) {
fail(msgKey, args);
}
}
public static void notEmpty(String str, String msgKey, Object... args) {
if (str == null || str.isEmpty()) {
fail(msgKey, args);
}
}
public static void notNull(Object obj, String msgKey, Object... args) {
if (obj == null) {
fail(msgKey, args);
}
}
private static void fail(String msgKey, Object... args) {
throw new CheckException(resources.getMessage(msgKey, args, UserUtil.getLocale()));
}
}

这里有几个小技术点:

工具类里面使用spring的bean,使用了MethodInvokingFactoryBean的静态方法注入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- 国际化 -->
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>format</value>
<value>exceptions</value>
<value>windows</value>
</list>
</property>
</bean>
<bean
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod" value="plm.common.utils.CheckUtil.setResources" />
<!-- 这里配置参数 -->
<property name="arguments" ref="messageSource">
</property>
</bean>

server里面调用的使用没有出现类名

这里使用的jdk的import static 特性,可以在ide上配置,请自行google。

1
import static plm.common.utils.CheckUtil.*;

还有一小点注意,我建议参数非法的时候,把值打印出来,否则你又要浪费时间看是没有传呢还是传错了,时间就是这样一点点浪费的。

1
check(id > 0L, "id.error", id); // 当前非法的id也传入提示出去

另外有些项目用valid来校验,从我实际接触来看,用的不多,可能是有短木板吧。如果你的项目valid就能满足,那就更加好了,不需要看了。但是大部分场景,校验比例子复杂N多,提示也千变万化,所以我们还是自己调用函数校验。

做了这几步之后,代码会漂亮很多,记住,代码最主要的不是性能,而是可读性,有了可读性才有才维护性。而去掉无关的代码后的代码,和之前的代码对比一下,自己看吧。

还有人说代码要注释率到多少(我们公司有段时间工具扫描要求注释率到30%以上),依我看来,大部分业务代码这么简单,你把代码写成我例子那样,还需要什么注释?注释是画蛇添足。

如果您有任何想法或问题需要讨论或交流,可进入交流区发表您的想法或问题。
本文作者:晓风轻
原文链接:https://zhuanlan.zhihu.com/p/29129469
版权归作者所有,转载请注明出处