代码规范(一)——java篇
為什么80%的碼農(nóng)都做不了架構(gòu)師?>>> ??
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=new?StringBuffer();
String[]?formatStr=snFormatStr.split(splitChar);
for(String?inStr:formatStr){
????//判斷以str開頭,不分大小寫
????if(inStr.matches("^[Ss][Tt][Rr].*")){
????????stringBuffer.append(processStr(inStr));
?
建議:StringBuffer改成StringBuilder。
倒數(shù)第二行用commons-lang3的,既能避免硬編碼,又避免了正則表達(dá)式。
StringUtils.startsWithIgnoreCase(CharSequence,?CharSequence)
3.?
private?String?processDate(String?str)?throws?Exception{
????String[]?strings=str.split(innerChar);
String?def="yyyyMMdd";
?
建議:凡是屬于?“無狀態(tài)的”?“通用的”功能,可以放在Util.java里。
如果確實需要硬編碼,放在Util.java里,讓它們只永遠(yuǎn)出現(xiàn)一次。
4.?
String?re="";
……
if(ar.length>1&&add!=""){
建議:org.apache.commons.lang3.StringUtils.EMPTY
重用常量,不要自己新創(chuàng)建。
5.?
import?org.slf4j.Logger;
import?org.slf4j.LoggerFactory;
?
if?(LOGGER.isDebugEnabled())?{
LOGGER.debug("Attempting?to?resolve?a?principal...");
建議:既然用了slf4j,里面就封裝了判斷log?level的功能。
LOGGER.isDebugEnabled()是多余的。
6.?
if?(attributes?==?null)?{
return?null;
……
if?(itemNo.length()!=3)?{
throw?new?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?關(guān)閉流出現(xiàn)異常?!?",e);
????}
}
建議:
org.apache.commons.io.IOUtils.closeQuietly(OutputStream)
org.apache.commons.io.IOUtils.closeQuietly(Writer)
8.?
public?void?setApplicationContext(final?ApplicationContext?applicationContext)?{
????super.setApplicationContext(applicationContext);
????this.applicationContext?=?applicationContext;
}
建議:既然父類已經(jīng)有了ApplicationContext,子類的就是無用的,可以刪除。
?9.?
public?class?ImageVaditeAuthenticationViaFormAction
??if?(this.credentialsBinder?!=?null?&&?this.credentialsBinder.supports(credentials.getClass()))?{
????this.credentialsBinder.bind(request,?credentials);
??}
建議:Web層里,傳遞給Service層的東東,不應(yīng)該有Servlet?API。
10.?
UserCacheVO?vo?=?new?UserCacheVO();
vo.setLoginIP(request.getRemoteAddr());
vo.setLoginTime(DateUtil.DateTimeToString(new?Date()));
vo.setResourceNo(resourceNo);
vo.setUserName(loginId);
vo.setUserSymbol(userSymbol);
建議:做成UserCacheVO?vo?=?new?UserCacheVO(w,x,y,z);
?
有人說:對于多個參數(shù)是相同類型,比如都是string,采用構(gòu)造方法構(gòu)造比較容易出現(xiàn)調(diào)用時
參數(shù)錯位的錯誤,而且也不太容易發(fā)現(xiàn)
?
解決方式:這樣定義Constructor,每5個參數(shù)放在一行,
任何IDE的排版(都是一行有80/120/160個字符),都會保持整齊隊形了。
11.??
建議:合并。每個package里,有幾個幾十個類是正常的。
com.gy.prvg.acl.constant里的多個常量類,合并為一個。Enum,也做在常量類里面。
?
(2014/?09/?22增補(bǔ))目前公司里還有個類似的狀況,工程師們喜歡狂建項目——
只有幾個類的十幾個類的,都能做個單獨(dú)的項目出來。
建議:一個工程有了2000--4000個類,可以考慮拆分。幾百個類的,先保持在一起。
好處:便于開發(fā),便于查找,便于檢錯,便于調(diào)試,便于維護(hù),便于測試。
?12.?
public?static?final?List<AccountType>?AllTypes()?{
List<AccountType>?types?=?new?ArrayList<AccountType>();
for?(AccountType?accountType?:?AccountType.values())?{
types.add(accountType);
}
return?types;
}
建議: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());
return?JSON.toJSONString(map);
?
建議:
可以用JSON.toJSONString(this);一句搞定。或者加上@JsonIgnore能屏蔽些field。
搞json格式,全部項目應(yīng)該用統(tǒng)一的jar。推薦:fastjson。
14.?
import?org.apache.log4j.FileAppender;
import?org.apache.log4j.Layout;
import?org.apache.log4j.helpers.CountingQuietWriter;
import?org.apache.log4j.helpers.LogLog;
import?org.apache.log4j.helpers.OptionConverter;
import?org.apache.log4j.spi.LoggingEvent;
?
public?class?AclLogFileAppender?extends?FileAppender
?
建議:org.apache.log4j.RollingFileAppender應(yīng)該足夠用了,不用自建class。
15.?
public?enum?RoleType?{
??PlatAdmin("平臺管理員"),
??CorpAdmin("公司管理員"),
??Normal("普通角色");
?
if?("財務(wù)視圖".equals(view.getViewName()))?{
view.setViewType("Finance");
}
if?("管理視圖".equals(view.getViewName()))?{
view.setViewType("Manage");
}
if?("參數(shù)視圖".equals(view.getViewName()))?{
view.setViewType("Param");
建議:用ASCII表里的英文字母或數(shù)字。
?16.?
public?interface?ILoginService?{
void?loadPrivilegeItemList(String?resourceNo,?String?loginId,?HttpServletRequest?request);
??HttpResult?logon(HttpServletRequest?request);
?
建議:
團(tuán)長能夠指揮士兵,士兵不能指揮團(tuán)長。
上層能調(diào)用下層,下層不能調(diào)用上層。
Service層里,不應(yīng)該有Web層api。
?17.?
if?(data.get("uri").indexOf(action.getItemContent())>=0)?{
?
建議:java.lang.String.contains(CharSequence)
?
?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;
?
stringBuilder.append(LoUtils.fill0InStr(calcDebitCount+"",?3,?0));
?
建議:org.apache.commons.lang3
StringUtils.?leftPad(java.lang.String?str,?int?size,?char?padChar)
StringUtils.?leftPad(java.lang.String?str,?int?size,?java.lang.String?padStr)
?
建議:
calcDebitCount+"",這種用法在不同的jdk和不同的編程語言之間都可能有毛病。例如:
assertEquals("1.23456789E7",?12345678.90?+?"");
assertEquals("1.23456789E7",?Double.toString(12345678.90));
assertEquals("1.23456789E7",?String?.valueOf(12345678.90));
這3個都變味了。所以,使用這些功能之前,要確保正確性。
19.?
try?{
??……
}?catch?(SystemException?se){
LOGGER.error("?Finding?listCorporation?is?error?!",se);
throw?new?SystemException(se.getErrorCode(),?se.getMessage());
}?catch?(Exception?e)?{
LOGGER.error("?Finding?listCorporation?is?error?!",e);
throw?new?SystemException(ErrorCode.ERROR_9004,"查詢公司出現(xiàn)異常!",?e);
?
每個項目里的每層的每個類里,都有這些catch,有實際意義嗎?
白白的增加了幾千幾萬行code。
建議:絕大多數(shù)情況,不需要catch。public?void?someMethod()?throws?Exception是最簡潔的。
只是在必要之處,例如:返回給頁面之前,才做catch。
?
附:java的checked?exception是個設(shè)計錯誤。
按照現(xiàn)代的程序理論:在任何地方,catch都是可有可無的,不應(yīng)該強(qiáng)迫搞catch。
Java5以前的Runnable??run(),就是強(qiáng)迫catch?{?},讓開發(fā)者感到臃腫。
Java5+的Callable,V?call()??throws?Exception;?catch?{?}?就是可有可無的,很清爽。
?20.?
userRole.setRoleName(URLDecoder.decode(userRole.getRoleName(),?"UTF-8"));
建議:
org.apache.commons.lang3.CharEncoding.UTF_8
凡是可能有編碼毛病之處,用POST方式,
把org.springframework.web.filter.CharacterEncodingFilter當(dāng)做過濾器,就實現(xiàn)了統(tǒng)管,
就不用在多處搞多個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?=?new?HashMap<>();
data.put("uri",?request.getRequestURI());
data.put("loginId",?SSOConstant.getLoginId(request));
data.put("resourceNo",?SSOConstant.getResourceNo(request));
?
建議:凡是常用的hardcode,都做成靜態(tài)常量。
24.?
CacheLoadUtil.getRelationMap().put(roleCode,?map);
建議:緩存的東東,不應(yīng)該在static?map的里面,而應(yīng)該在obj?map里面。
?25.?
public?static?String?objectToString(Object?obj){
return?obj.toString();
建議:刪除這個函數(shù)。
?26.?
public?static?String?replaceSpecialStr(Object?value){
if(null?!=?value?&&?!"".equals(value)){
return?value.toString().replaceAll("'",?"’").trim();
建議:
org.apache.commons.lang3.StringUtils.isNotEmpty(CharSequence)
java.lang.String.replaceAll(String,?String)?適合于:正則表達(dá)式。
java.lang.String.replace(CharSequence,?CharSequence)?更適合此處。
?27.?
public?static?String?nullConvert(String?value){
return?null==value?"":value;
建議:該報錯的時候,就報錯,用org.springframework.util.Assert.notNull(Object)
如果確實有用,用:org.apache.commons.lang3.StringUtils.defaultString(String)
28.?
void?modifyAuditStatus(Long[]?ids,?String?operType,?Map<String,String>?data)
建議:Long[]?ids改成:List<Long>,面向?qū)ο缶幊?#xff0c;少用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)?{
UserRole?ur?=?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");?把類似的風(fēng)格做成兩樣?xùn)|東了,建議都用int風(fēng)格。
建議:
用多參數(shù)的Constructor,把10行變成1行。
有人對此提出疑問:把10個參數(shù)放在Constructor里,太多了……
他說的,適合于啥情況呢?
OO設(shè)計,有幾條重要原則:
(A)迪米特法則——“最少知識原則”?!?不要和陌生人說話”。
(B)強(qiáng)內(nèi)聚,弱耦合。即:關(guān)系越少越好。
UserRole,里面所有的屬性都是“同類的傻傻的boolean/int/String/…”,是很簡單的容器,
不屬于OO設(shè)計范圍,就算Constructor里有200+個參數(shù),也是正確的。
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?=?'%';
把常用的拼接功能做成個靜態(tài)函數(shù):
public?static?void?wildcardSqlWord(String?str)?{
????return?Util.SQL_WILDCARD?+?str?+?Util.SQL_WILDCARD;
}
32.?
//?轉(zhuǎn)換用戶狀態(tài)
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;
//?轉(zhuǎn)換參數(shù)狀態(tài)
switch?(sys.getStatus())?{
case?"0":
sys.setStatus("Normal");//?正常
break;
case?"1":
sys.setStatus("Forbidden");//?禁止
break;
default:
sys.setStatus("Illegal");//?非法
break;
}
//?操作級別轉(zhuǎn)換
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(數(shù)字),就在enum里加入成員常量。例如:
public?enum?CmdCategory?implements?MyEnum?{
??/**
???*?<code>dummy?=?0;</code>
???*/
??dummy(0,?0),
??/**
???*?統(tǒng)一官網(wǎng)
???*/
??official(1,?10000),
??/**
???*?個人系統(tǒng)
???*/
??person(2,?20000),
??/**
???*?企業(yè)系統(tǒng)
???*/
??company(3,?30000),
33.?
private?CacheLoadUtil()?{
super();
}
public?class?StringUtil?{
private?StringUtil(){
super();
};
建議:
public?Util()?{?//?這里用了public,是為了覆蓋率的完美。
????throw?new?java.lang?.NoSuchMethodError();
}
34.?
String?sql?=?"?select?l.*?from?T_PVG_LEAF?l?join?T_PVG_ROLE_LEAF?rl?on?l.leafCode
建議:應(yīng)該回避”l”。
”l”長得很像數(shù)字1和i的大寫字母,java的語言規(guī)范中都回避,long?3用”3L”表示。
?35.?
if?(obj?==?null)?{
result?=?"PO00000000";
}else?{
result?=?LeafRelation.nextBriefCode(String.valueOf(obj));
}
建議:如果兩個長度都中等,可以合并為一行,用java的三元運(yùn)算符:
result?=?(null?==?obj)???x?:?y
?36.?
public?class?CacheLoadUtil?{
/**
?*?<p>以企業(yè)資源號為key?公司對象為value</p>
?*/
private?static?final?Map<String,?Corporation>?CORPS?=?new?HashMap<String,?Corporation>();
/**
?*?<p>以部門編號為key?部門對象為value</p>
?*/
private?static?final?Map<String,?Department>?DEPTS?=?new?HashMap<String,Department>();
/**
?*?<p>以角色代碼為key?角色對象為value</p>
?*/
private?static?final?Map<String,?Role>?ROLES?=?new?HashMap<String,Role>();
建議:緩存,不要搞static?Map,用實例化的對象,最好用框架EHCache、Memcache……
?37.?推薦的Java測試組件
頁面層:HtmlUnit。普通的頁面和js(jQuery等),它都能搞定。
業(yè)務(wù)層:JUnit?+?Mockito/EasyMock
持久層:JUnit?+?HsqlDB/H2/Derby?+?Spring?Context
測試結(jié)果報表:Cobertura?/?JaCoCo
構(gòu)建工具:Maven?/?Ant。在命令行上(不依賴于IDE),用一條的指令搞定全部構(gòu)建的東東。
?
38.?自動化測試的重要信息
(1)?想要在程序這條路上走幾十年,搞自動化測試是最正確的路線。
(2)?參考?張林?的http://qc.gyist.com/Wiki.jsp?page=SoftwareTesting
(3)?參考第37節(jié)
(5)?假設(shè)某版本app有900個bug,有了“自動化測試”,能快速檢查出來820個,
30個被測試組檢查出來,10個在UAT環(huán)境出現(xiàn),30個在生產(chǎn)環(huán)境出現(xiàn),
還剩10個永遠(yuǎn)也不會發(fā)現(xiàn)。這是比較理想的情況。
?
假如沒有“自動化測試”,820個就要分擔(dān)給“測試組”、“UAT”和“生產(chǎn)環(huán)境”來暴露了。
這會極大的增加程序員返工的次數(shù)和溝通的次數(shù)。我們絕不想要這種狀況。
這會極大的增加公司的經(jīng)營成本。老板絕不想要這種狀況!!!
原則:軟件bug,越早發(fā)現(xiàn),成本越低。
39.?有人問:為什么推薦JUnit4?為什么拋棄TestNG?
JUnit,簡單易用,最好了。主流版本是:3.8.x和4.x。JUnit4,約束更少,功能更強(qiáng)大。
Testng,本身過度復(fù)雜,在各大IDE上的版本都不同,
本身也有內(nèi)存泄露等毛病,新版本久不更新,應(yīng)該拋棄。
?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?implements?ApplicationContextAware?{
private?static?ApplicationContext?ctx;
private?SpringBeanUtil()?{
super();
}
public?static?<T>?T?getBean(String?id,?Class<T>?clazz)?{
if?(ctx?==?null)?{
throw?new?NullPointerException("ApplicationContext?is?null");
}
return?(T)?ctx.getBean(id);
}
@Override
public?void?setApplicationContext(ApplicationContext?applicationContext)
throws?BeansException?{
ctx?=?applicationContext;
}
}
建議:刪除Constructor,或者參考第33節(jié)
?
建議:扔掉getBean函數(shù),用:
org.springframework.beans.factory.BeanFactory.getBean(String,?Class<T>)?
BeanFactory?是ApplicationContext的父接口。
?
建議:Spring搞的都是OO,我們用Spring也應(yīng)該遵循OO。OO和靜態(tài)的東東是相排斥的。
把Spring的ctx做成靜態(tài)的引用,會有多種缺陷。例如:
(A)潛在的內(nèi)存泄露。
(B)清理對象的時候,總是不能清理static?ctx,這是災(zāi)難性的錯誤。
?
建議:getBean可能是作者的使用目的,是以static的方式訪問的。
可它的初始化,竟然是以實例的方式搞的!!!
@Override
public?void?setApplicationContext
?
建議:經(jīng)過上面4條建議,可以刪除掉SpringBeanUtil這個可憐的類了。
?41.?
public?String?resetPassword(String?loginId,?String?resourceNo,
Map<String,String>?data)?throws?SystemException?{
String?message?=?"";
String?userSymbol?=?CacheCommonUtil.getUserSymbol(loginId,?resourceNo);
User?user?=?CacheLoadUtil.getUsers().get(userSymbol);
SystemParam?dPassword?=?systemDao.selectSystemParamByKey(SystemParamConstants.PARAM_PWD_GROUP,user.getResourceNo());
try?{
if?(dPassword==null||StringUtil.isEmpty(dPassword.getParamValue()))?{//若無公司的默認(rèn)密碼,則默認(rèn)為登錄名
user.setPassword(CoderUtils.toHex(CoderUtils.encryptMD5(user.getLoginId())));
}else?{
user.setPassword(CoderUtils.toHex(CoderUtils.encryptMD5(dPassword.getParamValue())));
}
user.setUpdated(new?Date());
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行,凡是從緩存取數(shù)據(jù)的操作,應(yīng)該建立個成員變量(member?variable),
用Spring的標(biāo)準(zhǔn)set方式注入cacheManager對象,堅決拋棄靜態(tài)功能。
?
建議:CoderUtils,詞匯Coder明顯意義錯誤。
可以改成CodecUtils,標(biāo)準(zhǔn)依據(jù):org.apache.commons.codec.*
?
建議:加密用:org.apache.commons.codec.digest.DigestUtils?.md5Hex(byte[]?data)
?
建議:倒數(shù)第3行,密碼,不應(yīng)該以明文方式出現(xiàn)在log里。
42.?
public?class?SystemServiceImpl?implements?ISystemService?{
private?static?final?Logger?LOGGER?=?LoggerFactory.getLogger(SystemServiceImpl.class);
建議:實例范圍的類,就用實例范圍的Logger。
private?Logger?LOGGER?=?LoggerFactory.getLogger(getClass());
?43.?自動化測試,包含了哪幾塊?
(A)自動化單元測試。專門測試某層級的某類。這是最細(xì)粒度的。
(B)自動化集成測試。
例如:某Web?Service的TC,順便也把它的下面幾層(Service層、Dao層)都測試到了。
(C)冒煙測試
?44.?自動化測試,有哪些原則?
這里,簡稱為TC(TestCase)。
(A)TC_Y不會依賴于TC_X和TC_Z。
(B)跑任何的TC,只用1條指令。注意:只是1條,不是2條或N條。
這1條,里面包含了啟動相關(guān)的資源(DB,Web?Server……)
(C)在developerA電腦里能跑的300個TC,移動到developerB電腦里的任何目錄里,
也要跑對。像”C:/MyTempDir”之類的absolute?path,絕不應(yīng)該出現(xiàn)。
(D)不依賴于外部資源和網(wǎng)絡(luò)。
例如:用www.ip138.com得到本機(jī)的外網(wǎng)ip。如果那家網(wǎng)站垮了或被封了,就會影響TC。
例如:利用了公司內(nèi)網(wǎng)里某臺DB和某些WebService。如果那些停了,就會影響TC。
例如:源碼里出現(xiàn)了多次192.168.1.xxx就是錯誤的。
既然“不依賴于外部資源”了,那就更加不會依賴于“虛擬機(jī)”了。
有網(wǎng)絡(luò)的時候能跑對;拔掉網(wǎng)線的接頭,也能跑對。
(F)不應(yīng)該彈出UI。
如果必須要彈出UI才能檢驗正確性,也行,還必須在彈出后3秒再自動的關(guān)閉它。
然后接著繼續(xù)跑后面的TC。
45.?TC需要的外部資源,如何模擬?
(A)Mockito?/?EasyMock
用于模擬:接口,抽象類,普通類(非final的)
待續(xù)。
?
(B)Embedded?Tomcat
用于模擬Web?Site和Web?Service。
?
@BeforeClass
public?static?void?setUpClass()?throws?Exception?{
????tomcat?=?new?Tomcat();
????tomcat.setBaseDir(tomcat4junit);
????tomcat.addWebapp(new?File("web").getCanonicalPath());
????tomcat.setPort(PORT);
????tomcat.start();
}
@AfterClass
public?static?void?tearDownClass()?throws?Exception?{
????tomcat.stop();
????tomcat.destroy();
}
?
?
(C)DbUnit?+?Derby?/?HsqlDB?/?H2??instead?of??MySql?/?Oracle?/?SqlServer
經(jīng)典用法:在每次TC之前(@Before里),清空table,并且導(dǎo)入某xml文件到table里:
DatabaseOperation.CLEAN_INSERT.execute(dbConn2,?dataSet2);
?46.?
private?String?translateContract(String?contract,Declare?declare)?throws?Exception?{
?? Pattern?pattern?=?Pattern.compile("[$]\\{[^}]*\\}");
?? Matcher?matcher?=?pattern.matcher(contract);
?? StringBuffer?sb?=?new?StringBuffer();
?? While(?…?)
?
建議:
為了避免硬編碼,為了減少復(fù)雜性,盡量不要自己搞正則表達(dá)式。
用org.springframework.beans.factory.config.PlaceholderConfigurerSupport的常量。
final?String[]?arr?=?StringUtils.substringsBetween("abc${123}efg${678}www",
????????DEFAULT_PLACEHOLDER_PREFIX,?DEFAULT_PLACEHOLDER_SUFFIX);
assertEquals("123",?arr[0]);
assertEquals("678",?arr[1]);
至于替換的功能,參考:spring??PropertyPlaceholderConfigurer
?47.?
contract.setSerialno(UUID.randomUUID().toString().replaceAll("-",?""));
建議:
public?String?replaceAll(String?regex,?String?replacement)
性能差些,是針對正則表達(dá)式搞替換的,而不是針對普通String。
?
這里,應(yīng)該用
public?String?replace(CharSequence?target,?CharSequence?replacement)
?48.?
if(type.equals(Workflow.TASK_CLAIM)){
if(role.equals("S")){
appStatus?=?"1";
}else?if(role.equals("M1")){
dataStatus?=?"2";
appStatus?=?"4";
}else?if(role.equals("M2")){
dataStatus?=?"2";
appStatus?=?"7";
}else?if(role.equals("P")){
appStatus?=?"10";
}else?if(role.equals("PHK")){
appStatus?=?"13";
}else?if(role.equals("PHTQR")){
appStatus?=?"15";
}else?if(role.equals("PGZ")){
appStatus?=?"17";
}
}else?if(type.equals(Workflow.TASK_COMPLETE)){
if(role.equals("S")){
if(passValue){
dataStatus?=?"2";
appStatus?=?"3";
}else{
dataStatus?=?"0";
appStatus?=?"0";
}
}else?if(role.equals("M1")){
if(passValue){
dataStatus?=?"2";
appStatus?=?"6";
建議:
(A)用Java7的switch(?str?)功能。
(B)凡是常量,都應(yīng)該以String[]/String[][]/enum的形式,做在Util里。
(C)每個常量的意義,用本地語言(中文)盡量詳細(xì)解釋。例如:
/**
?*?很常用的表示狀態(tài)的標(biāo)志位。
*?只用一個byte/char表示狀態(tài),讓解析更快。
?*/
?public?static?final?String?OK?=?String.valueOf(1);
?49.?如何對程序打分(0--100)?
?
(A)勉強(qiáng)跑起來的,能用的,通過測試組的檢查。0—30
中國的99+%的公司里的大部分程序員,做到了這條就停止了。
?
(B)自動化審核通過的(PMD,FindBugs,CheckStyle……),符合常見模式的。0—10
用自動化工具審核,然后修改。這條容易。
JavaEE里,通用的東東多,我們大多數(shù)都只做增刪改查,需要的模式很少。這條也容易。
?
(C)主要的功能,被自動化測試覆蓋了的。0--15
例如:某項目有WebService層,Service層,Dao層。
由于時間緊,僅僅只搞了WebService層的自動化測試,
雖然不足,但基本上覆蓋了主要的功能。這也行的。
?
(D)95+%的代碼行,被自動化測試覆蓋了的。0—15
聽說,中國阿里系的軟件項目,能達(dá)到這個程度。
?
(E)工程總體代碼行數(shù),很少較少的。0--20
這個需要很多年的細(xì)致的知識積累,軟件行業(yè)里,很少有人能達(dá)到。
例如:很多功能,在jdk/apache?commons/spring里都有,我們簡單的調(diào)用就行了。
?
轉(zhuǎn)載于:https://my.oschina.net/xiaoyuHe/blog/417364
總結(jié)
以上是生活随笔為你收集整理的代码规范(一)——java篇的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我叫mt4开橙色幻兽技巧(汉典我字的基本
- 下一篇: **bootstrap常见常用样式总结