编码规范集锦

来源:互联网 发布:linux 倒序查看文件 编辑:程序博客网 时间:2024/06/08 17:34

1.      

Result result=new Result();

result.setCode(201);

result.setStr(re);

result.setMessage("获取id成功");

 

建议:对常用的功能,可以:新增Constructor,把4行code用1行搞定。

Result result=new Result(code, str, msg);

 

2.      

StringBuffer stringBuffer=newStringBuffer();

String[]formatStr=snFormatStr.split(splitChar);

for(String inStr:formatStr){

   //判断以str开头,不分大小写

   if(inStr.matches("^[Ss][Tt][Rr].*")){

       stringBuffer.append(processStr(inStr));

 

建议:StringBuffer改成StringBuilder。

倒数第二行用commons-lang3的,既能避免硬编码,又避免了写正则表达式。

StringUtils.startsWithIgnoreCase(CharSequence,CharSequence)

 

 

3.      

private String processDate(String str)throws Exception{

   String[] strings=str.split(innerChar);

Stringdef="yyyyMMdd";

 

建议:凡是属于 “无状态的” “通用的”功能,可以放在Util.java里。

如果确实需要硬编码,放在Util.java里,让它们只永远出现一次。

 

4.      

String re="";

……

if(ar.length>1&&add!=""){

 

建议:org.apache.commons.lang3.StringUtils.EMPTY

重用常量,不要自己新创建。

 

5.      

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

 

if (LOGGER.isDebugEnabled()) {

         LOGGER.debug("Attemptingto resolve a principal...");

建议:既然用了slf4j,里面就封装了判断log level的功能。

LOGGER.isDebugEnabled()是多余的。

 

6.      

if (attributes == null) {

return null;

……

if (itemNo.length()!=3) {

         thrownew RuntimeException("ItemCode has exceed 3 bits !");

 

建议:

jdk,throw new IllegalArgumentException(...);

jdk,throw new IllegalStateException(...);

org.springframework.util.Assert.isTrue(boolean,String)

org.springframework.util.Assert.state(boolean,String)

 

7.      

if (null != sos) {

   try {

       sos.close();

    }catch (IOException e) {

             LOGGER.error("handleRequest 关闭流出现异常! ",e);

    }

}

建议:

org.apache.commons.io.IOUtils.closeQuietly(OutputStream)

org.apache.commons.io.IOUtils.closeQuietly(Writer)

8.      

public void setApplicationContext(finalApplicationContext applicationContext) {

   super.setApplicationContext(applicationContext);

   this.applicationContext = applicationContext;

}

建议:既然父类已经有了ApplicationContext,子类的就是无用的,可以删除。

 

9.      

public classImageVaditeAuthenticationViaFormAction

  if(this.credentialsBinder != null &&this.credentialsBinder.supports(credentials.getClass())) {

   this.credentialsBinder.bind(request, credentials);

  }

建议:Web层里,传递给Service层的东东,不应该有ServletAPI。

10.              

UserCacheVO vo = new UserCacheVO();

vo.setLoginIP(request.getRemoteAddr());

vo.setLoginTime(DateUtil.DateTimeToString(newDate()));

vo.setResourceNo(resourceNo);

vo.setUserName(loginId);

vo.setUserSymbol(userSymbol);

建议:做成UserCacheVO vo =new UserCacheVO(w,x,y,z);

 

11.              

建议:合并。每个package里,有几个几十个类是正常的。

com.gy.prvg.acl.constant里的多个常量类,合并为一个。Enum,也做在常量类里面。

 

2014/09/22增补)目前公司里还有个类似的状况,工程师们喜欢狂建项目——

只有几个类的十几个类的,都能做个单独的项目出来。

建议:一个工程有了2000--4000个类,可以考虑拆分。几百个类的,先保持在一起。

好处:便于开发,便于查找,便于检错,便于调试,便于维护,便于测试。

 

 

 

 

12.              

public static final List<AccountType>AllTypes() {

         List<AccountType>types = new ArrayList<AccountType>();

         for(AccountType accountType : AccountType.values()) {

                   types.add(accountType);

         }

         returntypes;

}

建议:List<TimeUnit>list = java.util.Arrays.asList(TimeUnit.values()); 一句话搞定。

 

13.              

@Override

public String toString() {

         Map<String,Object> map = new HashMap<String, Object>();

         map.put("loginId",loginId);

         map.put("resourceNo",resourceNo);

         map.put("deptNo",deptNo);

         map.put("userName",userName);

         map.put("userCode",userCode);

         map.put("cardId",cardId);

         map.put("phone",phone);

         map.put("email",email);

         map.put("status",status);

         map.put("roleType",roleType);

         map.put("corpName",getCorpName());

         map.put("deptNo",getDeptName());

         returnJSON.toJSONString(map);

 

建议:

可以用JSON.toJSONString(this);一句搞定。或者加上@JsonIgnore能屏蔽些field。

搞json格式,全部项目应该用统一的jar。推荐:fastjson。

 

14.              

import org.apache.log4j.FileAppender;

import org.apache.log4j.Layout;

importorg.apache.log4j.helpers.CountingQuietWriter;

import org.apache.log4j.helpers.LogLog;

importorg.apache.log4j.helpers.OptionConverter;

import org.apache.log4j.spi.LoggingEvent;

 

public class AclLogFileAppender extendsFileAppender

 

建议:org.apache.log4j.RollingFileAppender应该足够用了,不用自建class。

 

15.              

public enum RoleType {

 PlatAdmin("平台管理员"),

 CorpAdmin("公司管理员"),

 Normal("普通角色");

 

if ("财务视图".equals(view.getViewName())) {

         view.setViewType("Finance");

}

if ("管理视图".equals(view.getViewName())) {

         view.setViewType("Manage");

}

if ("参数视图".equals(view.getViewName())) {

         view.setViewType("Param");

建议:用ASCII表里的英文字母或数字。

 

16.              

public interface ILoginService {

         voidloadPrivilegeItemList(String resourceNo, String loginId, HttpServletRequestrequest);

 HttpResult logon(HttpServletRequest request);

 

建议:

团长能够指挥士兵,士兵不能指挥团长。

上层能调用下层,下层不能调用上层。

Service层里,不应该有Web层api。

 

17.              

if(data.get("uri").indexOf(action.getItemContent())>=0) {

 

建议:java.lang.String.contains(CharSequence)

org.apache.commons.lang3.CharEncoding.UTF_8

 

18.              

int len = roleCode.length() - 3;

int maxNo =Integer.valueOf(roleCode.substring(len));

String leafNo = String.valueOf(maxNo + 1);

leafNo = (leafNo.length() == 3) ? leafNo :(leafNo.length() == 2 ? "0" + leafNo : "00" + leafNo);

code = roleCode.substring(0, len) + leafNo;

 

建议:

org.apache.commons.lang3.StringUtils.leftPad(String,int, char)

org.apache.commons.lang3.StringUtils.leftPad(String,int, String)

 

19.              

try {

  ……

} catch (SystemException se){

         LOGGER.error("Finding listCorporation is error !",se);

         thrownew SystemException(se.getErrorCode(), se.getMessage());

} catch (Exception e) {

         LOGGER.error("Finding listCorporation is error !",e);

         thrownew SystemException(ErrorCode.ERROR_9004,"查询公司出现异常!", e);

 

每个项目里的每层的每个类里,都有这些catch,有实际意义吗?

白白的增加了几千几万行code。

建议:绝大多数情况,不需要catch。public void someMethod() throws Exception是最简洁的。

只是在必要之处,例如:返回给页面之前,才做catch。

 

附:javachecked exception是个设计错误。

按照现代的程序理论:在任何地方,catch都是可有可无的,不应该强迫搞catch

Java5以前的Runnable run(),就是强迫catch { },让开发者感到臃肿。

Java5+CallableV call() throws Exception; catch { } 就是可有可无的,很清爽。

 

20.              

userRole.setRoleName(URLDecoder.decode(userRole.getRoleName(),"UTF-8"));

 

建议:凡是可能有编码毛病之处,用POST方式,

把org.springframework.web.filter.CharacterEncodingFilter当做过滤器,就实现了统管,

就不用在多处搞多个URLDecoder.decode()了。

 

 

21.              

int index =StringUtil.isEmpty(pageLeafCode) ? 0 : pageLeafCode.indexOf("[");

if (index > 0) {

         pageLeafCode= pageLeafCode.substring(index + 1,pageLeafCode.length() - 1);

 

建议:org.apache.commons.lang3.StringUtils.substringAfter(String,String)

 

 

22.              

public String toString() {

         return"Leaf [leafId=" + leafId + ", leafName=" + leafName

                            +", leafCode=" + leafCode + ", nodeCode=" + nodeCode

                            +", leafType=" + leafType + ", leafContent=" + leafContent

                            +", description=" + description + ", subSystemId="

                            +subSystemId + "]";

 

建议:在基类里定义toString()一次就行了。

org.apache.commons.lang3.builder.ToStringBuilder.reflectionToString(

this, ToStringStyle.SHORT_PREFIX_STYLE);

 

23.              

Map<String,String> data = newHashMap<>();

data.put("uri",request.getRequestURI());

data.put("loginId",SSOConstant.getLoginId(request));

data.put("resourceNo",SSOConstant.getResourceNo(request));

 

建议:凡是常用的hardcode,都做成静态常量。

 

24.              

CacheLoadUtil.getRelationMap().put(roleCode,map);

建议:缓存的东东,不应该在static map的里面,而应该在obj map里面。

 

 

25.              

public static String objectToString(Objectobj){

         returnobj.toString();

建议:删除这个函数。

 

26.              

public static StringreplaceSpecialStr(Object value){

         if(null!= value && !"".equals(value)){

                   returnvalue.toString().replaceAll("'", "’").trim();

建议:

org.apache.commons.lang3.StringUtils.isNotEmpty(CharSequence)

java.lang.String.replaceAll(String, String)适合于:正则表达式。

java.lang.String.replace(CharSequence,CharSequence) 更适合此处。

 

 

27.              

public static String nullConvert(Stringvalue){

         returnnull==value?"":value;

建议:该报错的时候,就报错,用org.springframework.util.Assert.notNull(Object)

如果确实有用,用:org.apache.commons.lang3.StringUtils.defaultString(String)

 

28.              

void modifyAuditStatus(Long[] ids, StringoperType, Map<String,String> data)

建议:Long[] ids改成:List<Long>,面向对象编程,少用array,多用List。

 

29.              

Map<String, List<Role>> map =new HashMap<String,List<Role>>();

map.put("leftRoles", leftRoles);

map.put("rightRoles",rightRoles);

建议:既然只放两个,可以用:org.apache.commons.lang3.tuple.Pair.of(left,right)

 

 

30.              

for (String loginId : addUsers) {

         UserRoleur = new UserRole();

         ur.setCreated(now);

         ur.setCreatedBy(operator);

         ur.setIsActive('0');

         ur.setLoginId(loginId);

         ur.setResourceNo(resourceNo);

         ur.setRoleCode(roleCode);

         ur.setStatus("1");

         ur.setUpdated(now);

         ur.setUpdatedBy(operator);

建议:

ur.setIsActive('0');ur.setStatus("1"); 把类似的风格做成两样东东了,建议都用int风格。

 

建议:

用多参数的Constructor,把10行变成1行。

 

 

有人对此提出疑问:把10个参数放在Constructor里,太多了……

他说的,适合于啥情况呢?

OO设计,有几条重要原则:

(A)迪米特法则——“最少知识原则”。“不要和陌生人说话”。

(B)强内聚,弱耦合。即:关系越少越好。

 

UserRole,里面所有的属性都是“同类的傻傻的boolean/int/String/…”,是很简单的容器,

不属于OO设计范围,就算Constructor里有200+个参数,也是正确的。

 

下图,如果用了3个参数的Result(x, y, z); 将会大量缩减代码行数。

 

 

31.              

if(StringUtil.isNotEmpty(viewVO.getViewName())) {

         viewVO.setViewName("%"+ viewVO.getViewName() + "%");

         where.append("and viewName LIKE :viewName ");

}

if(StringUtil.isNotEmpty(viewVO.getViewType())) {

         viewVO.setViewType("%"+ viewVO.getViewType() + "%");

         where.append("and viewType LIKE :viewType ");

}

if(StringUtil.isNotEmpty(viewVO.getCreatedBy())) {

         viewVO.setCreatedBy("%"+ viewVO.getCreatedBy() + "%");

         where.append("and createdBy LIKE :createdBy ");

}

建议:

把"%"改成'%'

public static final char SQL_WILDCARD ='%';

把常用的拼接功能做成个静态函数:

public static void wildcardSqlWord(Stringstr) {

   return Util.SQL_WILDCARD + str + Util.SQL_WILDCARD;

}

 

 

32.              

// 转换用户状态

switch (u.getStatus()) {

case "0":

         u.setStatus("New");//新建

         break;

case "1":

         u.setStatus("Normal");//正常

         break;

case "2":

         u.setStatus("Forbidden");//禁用

         break;

default:

         u.setStatus("Illegal");//非法

         break;

// 转换参数状态

switch (sys.getStatus()) {

case "0":

         sys.setStatus("Normal");//正常

         break;

case "1":

         sys.setStatus("Forbidden");//禁止

         break;

default:

         sys.setStatus("Illegal");//非法

         break;

}

// 操作级别转换

switch (sys.getOperationGrade()) {

case "0":

         sys.setOperationGrade("无");

         break;

case "1":

         sys.setOperationGrade("查询");

         break;

case "2":

         sys.setOperationGrade("修改");

         break;

case "3":

         sys.setOperationGrade("删除");

         break;

case "4":

         sys.setOperationGrade("全部");

         break;

default:

         sys.setOperationGrade("Illegal");

         break;

 

 

建议:

在default后面,不要写break。

switch(x)里,尽量不用String,而用enum。

如果确实需要switch(数字),就在enum里加入成员常量。例如:

public enum CmdCategory implements MyEnum {

  /**

   *<code>dummy = 0;</code>

   */

 dummy(0, 0),

  /**

   * 统一官网

   */

 official(1, 10000),

  /**

   * 个人系统

   */

 person(2, 20000),

  /**

   * 企业系统

   */

 company(3, 30000),

 

 

33.              

private CacheLoadUtil() {

         super();

}

public class StringUtil {

         privateStringUtil(){

                   super();

         };

建议:

public Util() { // 这里用了public,是为了覆盖率的完美。

   throw new java.lang .NoSuchMethodError();

}

 

34.              

String sql = " select l.* fromT_PVG_LEAF l join T_PVG_ROLE_LEAF rl on l.leafCode

建议:应该回避”l”。

”l”长得很像数字1和i的大写字母,java的语言规范中都回避,long 3用”3L”表示。

 

 

35.              

if (obj == null) {

         result= "PO00000000";

}else {

         result= LeafRelation.nextBriefCode(String.valueOf(obj));

}

建议:如果两个长度都中等,可以合并为一行,用java的三元运算符:

result = (null == obj) ? x : y

 

 

36.              

public class CacheLoadUtil {

         /**

          * <p>以企业资源号为key 公司对象为value</p>

          */

         privatestatic final Map<String, Corporation> CORPS = new HashMap<String,Corporation>();

         /**

          * <p>以部门编号为key 部门对象为value</p>

          */

         privatestatic final Map<String, Department> DEPTS = newHashMap<String,Department>();

         /**

          * <p>以角色代码为key 角色对象为value</p>

          */

         privatestatic final Map<String, Role> ROLES = new HashMap<String,Role>();

建议:缓存,不要搞static Map,用实例化的对象,最好用框架EHCache、Memcache……

 

37.             推荐的Java测试组件

页面层:HtmlUnit

业务层:Mockito/EasyMock +JUnit

持久层:HsqlDB/H2/Derby +JUnit + Spring Context

测试结果报表:Cobertura /JaCoCo

 

 

38.             自动化测试的重要信息

(1)       想要在程序这条路上走几十年,搞自动化测试是最正确的路线。

(2)       ……

(3)       ……

待续。

 

 

39.             有人问:为什么推荐JUnit4?为什么抛弃TestNG?

JUnit,简单易用,最好了。JUnit4,约束更少,功能更强大。

Testng,本身过度复杂,在各大IDE上的版本都不同,

本身也有内存泄露等毛病,新版本久不更新,应该抛弃。

 

 

40.              

public static final Map<String,Corporation> getCorps() throws SystemException {

         if(CORPS.isEmpty()) {

                   List<Corporation>cps = SpringBeanUtil.getBean(AclConstants.CORP_SERVICE,CorporationServiceImpl.class).queryCorporationAll();

…………

 

public class SpringBeanUtil implementsApplicationContextAware {

         privatestatic ApplicationContext ctx;

         privateSpringBeanUtil() {

                   super();

         }

         publicstatic <T> T getBean(String id, Class<T> clazz) {

                   if(ctx == null) {

                            thrownew NullPointerException("ApplicationContext is null");

                   }

                   return(T) ctx.getBean(id);

         }

         @Override

         publicvoid setApplicationContext(ApplicationContext applicationContext)

                            throwsBeansException {

                   ctx= applicationContext;

         }

}

建议:删除Constructor,或者参考第33节

 

建议:扔掉getBean函数,用:

org.springframework.beans.factory.BeanFactory.getBean(String,Class<T>)

BeanFactory 是ApplicationContext的父接口。

 

建议:Spring搞的都是OO,我们用Spring也应该遵循OO。OO和静态的东东是相排斥的。

把Spring的ctx做成静态的引用,会有多种缺陷。例如:

(A)潜在的内存泄露。

(B)清理对象的时候,总是不能清理static ctx,这是灾难性的错误。

 

建议:getBean可能是作者的使用目的,是以static的方式访问的。

可它的初始化,竟然是以实例的方式搞的!!!

         @Override

         publicvoid setApplicationContext

 

建议:经过上面4条建议,可以删除掉SpringBeanUtil这个可怜的类了。

 

41.              

public String resetPassword(String loginId,String resourceNo,

                   Map<String,String>data) throws SystemException {

         Stringmessage = "";

         StringuserSymbol = CacheCommonUtil.getUserSymbol(loginId, resourceNo);

         Useruser = CacheLoadUtil.getUsers().get(userSymbol);

         SystemParamdPassword =systemDao.selectSystemParamByKey(SystemParamConstants.PARAM_PWD_GROUP,user.getResourceNo());

         try{

                   if(dPassword==null||StringUtil.isEmpty(dPassword.getParamValue())) {//若无公司的默认密码,则默认为登录名

                            user.setPassword(CoderUtils.toHex(CoderUtils.encryptMD5(user.getLoginId())));

                   }else{

         user.setPassword(CoderUtils.toHex(CoderUtils.encryptMD5(dPassword.getParamValue())));

                   }

                   user.setUpdated(newDate());

                   user.setUpdatedBy(data.get("loginId"));

                   userDao.update(user);

                   CacheLoadUtil.getUsers().put(userSymbol,user);

                   //增加操作日志

                   SystemLogUtil.addSystemLog(data,FuncType.SYSTEM_SETTING,AclConstants.SYS_RESET_PASSWORD, "密码******", "密码******");

                   message= "success";

建议:第4行,凡是从缓存取数据的操作,应该建立个成员变量(member variable),

用Spring的标准set方式注入cacheManager对象,坚决抛弃静态功能。

 

建议:CoderUtils,词汇Coder明显意义错误。

可以改成CodecUtils,标准依据:org.apache.commons.codec.*

 

建议:加密用:org.apache.commons.codec.digest.DigestUtils.md5Hex(byte[] data)

 

建议:倒数第3行,密码,不应该以明文方式出现在log里。

 

 

42.              

public class SystemServiceImpl implements ISystemService{

         privatestatic final Logger LOGGER = LoggerFactory.getLogger(SystemServiceImpl.class);

建议:实例范围的类,就用实例范围的Logger。

private Logger LOGGER =LoggerFactory.getLogger(getClass());

 

0 0
原创粉丝点击