1. 程式人生 > >我的編碼習慣 - 參數校驗和國際化規範

我的編碼習慣 - 參數校驗和國際化規範

sage 畫蛇添足 for factor 演示 false lis clas undle

原文出處:曉風輕

導讀:程序員你為什麽這麽累?

今天我們說說參數校驗和國際化,這些代碼沒有什麽技術含量,卻大量充斥在業務代碼上,很可能業務代碼只有幾行,參數校驗代碼卻有十幾行,非常影響代碼閱讀,所以很有必要把這塊的代碼量減下去。

今天的目的主要是把之前例子裏面的和業務無關的國際化參數隱藏掉,以及如何封裝好校驗函數。

先看對比圖,修改前:

技術分享

service中:

技術分享

修改後:

技術分享

service中:

技術分享

Controll的非業務代碼如何去掉參考我的編碼習慣 - Controller規範,下面說說去掉Local參數。

強調一下:業務代碼裏面不要出現和業務無關的東西,如local,MessageSource 。

去掉國際化參數還是使用的技術還是ThreadLocal。國際化信息可以放好幾個地方,但建議不要放在每一個url上,除了比較low還容易出很多其他問題。這裏演示的是放在cookie上面的例子:

技術分享

UserUtil

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,這裏需要得到用戶的語言

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的靜態方法註入:

<!-- 國際化 -->
<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。

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

還有一小點註意,我建議參數非法的時候,把值打印出來,否則你又要浪費時間看是沒有傳呢還是傳錯了,時間就是這樣一點點浪費的。

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

另外有些項目用valid來校驗,從我實際接觸來看,用的不多,可能是有短木板吧。如果你的項目valid就能滿足,那就更加好了,不需要看了。但是大部分場景,校驗比例子復雜N多,提示也千變萬化,所以我們還是自己調用函數校驗。

做了這幾步之後,代碼會漂亮很多,記住,代碼最主要的不是性能,而是可讀性,有了可讀性才有可維護性。而去掉無關的代碼後的代碼,和之前的代碼對比一下,自己看吧。

還有人說代碼要註釋率到多少(我們公司有段時間工具掃描要求註釋率到30%以上),依我看來,大部分業務代碼這麽簡單,你把代碼寫成我例子那樣,還需要什麽註釋?註釋是畫蛇添足。

我的編碼習慣 - 參數校驗和國際化規範