什么样的代码才是真正好的、整洁的代码?iteye.com上的文章很多:
Grady Booch,《面向对象分析与设计》作者:
引用
• 整洁的代码是简单、直接的;
• 整洁的代码,读起来像是一篇写得很好的散文;
• 整洁的代码永远不会掩盖设计者的意图,而是具有少量的抽象和清晰的控制行。
Dave Thomas,OTI公司创始人,Eclipse战略教父:
引用
• 整洁的代码可以被除了原作者之外的其他开发者阅读和改善;
• 具备单元测试和验收测试;
• 有一个有意义的名字;
• 使用一种方式来做一件事情;
• 最少的依赖,并明确定义;
• 提供了一个清晰的、最小的API;
• 应该根据语言特性,在代码中单独显示必要的信息,而不是所有的信息。
从他们的归纳中,可以看出真正好的代码都有一个共性,可读性。在《编写可读代码的艺术》这本书中,作者是这样定义可读性的:“代码的写法应当使用别人理解所需的时间最小化”。在这本书的指导下,从命名和注释开始在自己这几年写的代码中找出一些例子。希望自己以后在这些细节上引以为戒。
一.把信息封装到名字中,无论是类,方法或变量的命名
1.选择专业的词,尽量避免模糊或意义太广 。
public List<UserIp> select(String userId){ }
如果改成这样是不是更明确:
public List<UserIp> queryUserIps(String userId){ }
2.避免泛泛的名字
避免像tmp,i,j ,k这样泛泛的名字,比较常见循环中的 i,j,k.
for (int j = 0; j < actionLogs.size(); j++) { ActionLog actionLog = actionLogs.get(j); }
如果改成这样:
for (int index = 0; index < actionLogs.size(); j++) { ActionLog actionLog = actionLogs.get(index); }
3.用具体的名字代替抽象的名字
在给变量,函数或者其它元素命名时,要把它描述的更具体而不是更抽象。
/** * 刷新IP库 */ public void refreshData() ;
如果改成这样:
/** * 刷新IP库 */ public void refreshIpData() ;
4.使用前缀或后缀来给名字附带更多信息
对于像带单位的值均可以用后缀来附加更多信息
常见的打印日志的代码:
long startTime = System.currentTimeMillis(); if (logger.isInfoEnabled()) { logger.info((System.currentTimeMillis() - startTime) + "ms,success!"); }
如果改成这样:
long startMs = System.currentTimeMillis(); if (logger.isInfoEnabled()) { logger.info((System.currentTimeMillis() - startMs ) + "ms,success!"); }
5.决定名字的长度
(1)在小的作用域里可以使用短的名字,丢掉没用的词。
public static StrategyType convertToStrategyType(StrategyTypeDO strategyTypeDO) { }
如果改成这样:
public static StrategyType toStrategyType(StrategyTypeDO strategyTypeDO) { }
6.给boolean命名
通常来讲,加上is,has,can 或should这样的词,可以把布尔值变得更明确。
如代码:
boolean first = true; if(subConditions!=null&&subConditions.size()>0){ for (FactorCondition condition : subConditions) { String template = generateCode(condition); sbf.append((first ? "" : " || ") + "( " + template + " )"); if (first) { first = false; } } }
若改为:
boolean isFirst = true; if(subConditions!=null&&subConditions.size()>0){ for (FactorCondition condition : subConditions) { String template = generateCode(condition); sbf.append((isFirst ? "" : " || ") + "( " + template + " )"); if (isFirst) { isFirst = false; } } }
7.与使用者的期望相匹配
方法的名称要符合用户的期望,我们通常期望get()方法是轻量的方法。
public double getFPSecurityModelScore(Event event) { //这里省略 }
若改为:
public double computeFPSecurityModelScore(Event event) { //这里省略 }
二.代码风格与注释
一致的风格要比“正确”的风格更重要,对于一个团队乃至一个公司,要采用一致的格式化模板。对于注释,一定不要为注释而注释,许多时候好代码>坏代码+注释,当你觉得要写很多注释时,也从侧面反映出你的代码或设计不太美妙。注释的目的就是尽量帮助读者了解和作者一样多。
1.不要为了注释而注释
/** * Getter method for property <tt>groupName</tt>. * * @return property value of groupName */ public String getGroupName() { return groupName; } /** * Setter method for property <tt>groupName</tt>. * * @param groupName value to be assigned to property groupName */ public void setGroupName(String groupName) { this.groupName = groupName; }
当然,上面的的注释是由模板生成的,确有为了注释而注释之嫌。
2.注释要记录你的思想.
包括为什么代码写成这样而不哪样的内在理由。对于代码的缺陷或需要优化的地方可给予注释,对于常量,可记录常量背后的故事,为什么是这个值,如:
/** * The load factor used when none specified in constructor. */ static final float DEFAULT_LOAD_FACTOR = 0.75f;
3.站在读者的立场上思考。
为普通读者意料之外的行为加上注释,用注释来总结代码块或精确地描述函数的行为,使读者不致迷失在细节中。
三.细节决定成败,表面并非肤浅
对于上面的每一个细节如果都能做的很好,这就为写好代码,写好可读代码,写好整洁代码迈出了第一步。
参考资料:《编写可读代码的艺术》