代码规范(一)——java篇

1.

Result result=new Result();

result.setCode(201);

result.setStr(re);

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

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

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

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

StringUtils.startsWithIgnoreCase(CharSequence, CharSequence)

3. 

private String processDate(String str) throws Exception{

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

String def="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("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 !");

建议:

jdkthrow new IllegalArgumentException(...);

jdkthrow 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(final ApplicationContext applicationContext) {

    super.setApplicationContext(applicationContext);

    this.applicationContext = applicationContext;

}

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

 9. 

public class ImageVaditeAuthenticationViaFormAction

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

    this.credentialsBinder.bind(request, credentials);

  }

建议:Web层里,传递给Service层的东东,不应该有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);

 

有人说:对于多个参数是相同类型,比如都是string,采用构造方法构造比较容易出现调用时

参数错位的错误,而且也不太容易发现

 

解决方式:这样定义Constructor,每5个参数放在一行,

任何IDE的排版(都是一行有80/120/160个字符),都会保持整齐队形了。

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);

}

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格式,全部项目应该用统一的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应该足够用了,不用自建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 {

void loadPrivilegeItemList(String resourceNo, String loginId, HttpServletRequest request);

  HttpResult logon(HttpServletRequest request);

 

建议:

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

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

Service层里,不应该有Webapi

 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,"查询公司出现异常!", e);

 

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

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

建议:绝大多数情况,不需要catchpublic 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"));

建议:

org.apache.commons.lang3.CharEncoding.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 = new HashMap<>();

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(Object obj){

return obj.toString();

建议:删除这个函数。

 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) 适合于:正则表达式。

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>,面向对象编程,少用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(leftright)

 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"); 把类似的风格做成两样东东了,建议都用int风格。

建议:

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

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

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

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

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

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


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

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

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(String str) {

    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 {

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

建议:应该回避l

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

 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>

 */

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,用实例化的对象,最好用框架EHCacheMemcache……

 37. 推荐的Java测试组件

页面层:HtmlUnit。普通的页面和jsjQuery等),它都能搞定。

业务层:JUnit + Mockito/EasyMock

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

测试结果报表:Cobertura / JaCoCo

构建工具:Maven / Ant。在命令行上(不依赖于IDE),用一条的指令搞定全部构建的东东。

 

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

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

(2) 参考 张林 的http://qc.gyist.com/Wiki.jsp?page=SoftwareTesting

(3) 参考第37

(5) 假设某版本app900bug,有了“自动化测试”,能快速检查出来820个,

30个被测试组检查出来,10个在UAT环境出现,30个在生产环境出现,

还剩10个永远也不会发现。这是比较理想的情况。

 

假如没有“自动化测试”,820个就要分担给“测试组”、“UAT”和“生产环境”来暴露了。

这会极大的增加程序员返工的次数和沟通的次数。我们绝不想要这种状况。

这会极大的增加公司的经营成本。老板绝不想要这种状况!!!

原则:软件bug,越早发现,成本越低。

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

JUnit,简单易用,最好了。主流版本是:3.8.x4.xJUnit4,约束更少,功能更强大。

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 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

 

建议:扔掉getBean函数,用:

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

BeanFactory ApplicationContext的父接口。

 

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

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

A)潜在的内存泄露。

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

 

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

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

@Override

public void setApplicationContext

 

建议:经过上面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())) {//若无公司的默认密码,则默认为登录名

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行,凡是从缓存取数据的操作,应该建立个成员变量(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 {

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

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

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

 43. 自动化测试,包含了哪几块?

A)自动化单元测试。专门测试某层级的某类。这是最细粒度的。

B)自动化集成测试。

例如:某Web ServiceTC,顺便也把它的下面几层(Service层、Dao层)都测试到了。

C)冒烟测试

 44. 自动化测试,有哪些原则?

这里,简称为TCTestCase)。

ATC_Y不会依赖于TC_XTC_Z

B)跑任何的TC,只用1条指令。注意:只是1条,不是2条或N条。

1条,里面包含了启动相关的资源(DBWeb Server……)

C)在developerA电脑里能跑的300TC,移动到developerB电脑里的任何目录里,

也要跑对。像”C:/MyTempDir”之类的absolute path,绝不应该出现。

D)不依赖于外部资源和网络。

例如:用www.ip138.com得到本机的外网ip。如果那家网站垮了或被封了,就会影响TC

例如:利用了公司内网里某台DB和某些WebService。如果那些停了,就会影响TC

例如:源码里出现了多次192.168.1.xxx就是错误的。

既然“不依赖于外部资源”了,那就更加不会依赖于“虚拟机”了。

有网络的时候能跑对;拔掉网线的接头,也能跑对。

F)不应该弹出UI

如果必须要弹出UI才能检验正确性,也行,还必须在弹出后3秒再自动的关闭它。

然后接着继续跑后面的TC

45. TC需要的外部资源,如何模拟?

AMockito / EasyMock

用于模拟:接口,抽象类,普通类(非final的)

待续。

 

BEmbedded Tomcat

用于模拟Web SiteWeb 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();

}

 

 

CDbUnit + Derby / HsqlDB / H2  instead of  MySql / Oracle / SqlServer

经典用法:在每次TC之前(@Before里),清空table,并且导入某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(  )

 

建议:

为了避免硬编码,为了减少复杂性,尽量不要自己搞正则表达式。

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)

性能差些,是针对正则表达式搞替换的,而不是针对普通String

 

这里,应该用

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)用Java7switch( str )功能。

B)凡是常量,都应该以String[]/String[][]/enum的形式,做在Util里。

C)每个常量的意义,用本地语言(中文)尽量详细解释。例如:

/**

 * 很常用的表示状态的标志位。

只用一个byte/char表示状态,让解析更快。

 */

 public static final String OK = String.valueOf(1);

 49. 如何对程序打分(0--100)?

 

A)勉强跑起来的,能用的,通过测试组的检查。030

中国的99+%的公司里的大部分程序员,做到了这条就停止了。

 

B)自动化审核通过的(PMDFindBugsCheckStyle……),符合常见模式的。010

用自动化工具审核,然后修改。这条容易。

JavaEE里,通用的东东多,我们大多数都只做增删改查,需要的模式很少。这条也容易。

 

C)主要的功能,被自动化测试覆盖了的。0--15

例如:某项目有WebService层,Service层,Dao层。

由于时间紧,仅仅只搞了WebService层的自动化测试,

虽然不足,但基本上覆盖了主要的功能。这也行的。

 

D95+%的代码行,被自动化测试覆盖了的。015

听说,中国阿里系的软件项目,能达到这个程度。

 

E)工程总体代码行数,很少较少的。0--20

这个需要很多年的细致的知识积累,软件行业里,很少有人能达到。

例如:很多功能,在jdk/apache commons/spring里都有,我们简单的调用就行了。

 

转载于:https://my.oschina.net/xiaoyuHe/blog/417364

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值