`
kim_miao
  • 浏览: 188693 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

编写可读代码的艺术-从命名和注释开始

阅读更多

什么样的代码才是真正好的、整洁的代码?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.站在读者的立场上思考。

     为普通读者意料之外的行为加上注释,用注释来总结代码块或精确地描述函数的行为,使读者不致迷失在细节中。

三.细节决定成败,表面并非肤浅
    对于上面的每一个细节如果都能做的很好,这就为写好代码,写好可读代码,写好整洁代码迈出了第一步。

参考资料:《编写可读代码的艺术》

分享到:
评论

相关推荐

    编写可读代码的艺术

    《O’Reilly精品图书系列:编写可读代码的艺术》关注编码的细节,总结了很多提高代码可读性的小技巧,看似都微不足道,但是对于整个软件系统的开发而言,它们与宏观的架构决策、设计思想、指导原则同样重要。...

    编写可读代码的艺术(The Art of Readable Code)

    《编写可读代码的艺术》是一本关于如何编写具有高可读性代码的书。本书的关键思想是代码应该写得容易理解。确切地说,使别人用最短的时间理解你的代码。  本书解释了这种思想,并且用不同语言的大量例子来讲解,...

    编写可读代码的艺术.[美]Dustin Boswell,Trevor Foucher(带详细书签)

    本书分成四部分:表面层次上的改进命名、注释以及审美——可以用于代码库每一行的小提示。简化循环和逻辑在程序中定义循环、逻辑和变量,从而使得代码更容易理解。重新组织你的代码在更高层次上组织大的代码块以及在...

    算法精解C描述

    本书中的代码尤为值得强调:所有实现都采用C语言编写,所有代码都优先用于教学目的,所有代码都在4种平台上经过完整测试,头文件记录了所有公共的接口,命名规则适用于全书所有的代码,所有的代码都包含大量注释……

    UML和模式应用(架构师必备).part06.rar

    10.6 如何为系统事件和操作命名 10.7 如何为涉及其他外部系统的SSD建模 10.8 SSD的哪些信息要放入词汇表中 10.9 示例:Monopoly SSD 10.10 过程:迭代和进化式SSD 10.11 历史和参考资料 第11章 操作契约 11.1...

    UML和模式应用(架构师必备).part01.rar

    10.6 如何为系统事件和操作命名 10.7 如何为涉及其他外部系统的SSD建模 10.8 SSD的哪些信息要放入词汇表中 10.9 示例:Monopoly SSD 10.10 过程:迭代和进化式SSD 10.11 历史和参考资料 第11章 操作契约 11.1...

    UML和模式应用(架构师必备).part07.rar

    10.6 如何为系统事件和操作命名 10.7 如何为涉及其他外部系统的SSD建模 10.8 SSD的哪些信息要放入词汇表中 10.9 示例:Monopoly SSD 10.10 过程:迭代和进化式SSD 10.11 历史和参考资料 第11章 操作契约 11.1...

    UML和模式应用(架构师必备).part02.rar

    10.6 如何为系统事件和操作命名 10.7 如何为涉及其他外部系统的SSD建模 10.8 SSD的哪些信息要放入词汇表中 10.9 示例:Monopoly SSD 10.10 过程:迭代和进化式SSD 10.11 历史和参考资料 第11章 操作契约 11.1...

    UML和模式应用(架构师必备).part03.rar

    10.6 如何为系统事件和操作命名 10.7 如何为涉及其他外部系统的SSD建模 10.8 SSD的哪些信息要放入词汇表中 10.9 示例:Monopoly SSD 10.10 过程:迭代和进化式SSD 10.11 历史和参考资料 第11章 操作契约 11.1...

    UML和模式应用(架构师必备).part04.rar

    10.6 如何为系统事件和操作命名 10.7 如何为涉及其他外部系统的SSD建模 10.8 SSD的哪些信息要放入词汇表中 10.9 示例:Monopoly SSD 10.10 过程:迭代和进化式SSD 10.11 历史和参考资料 第11章 操作契约 11.1...

    UML和模式应用(架构师必备).part08.rar

    10.6 如何为系统事件和操作命名 10.7 如何为涉及其他外部系统的SSD建模 10.8 SSD的哪些信息要放入词汇表中 10.9 示例:Monopoly SSD 10.10 过程:迭代和进化式SSD 10.11 历史和参考资料 第11章 操作契约 11.1...

    UML和模式应用(架构师必备).part05.rar

    10.6 如何为系统事件和操作命名 10.7 如何为涉及其他外部系统的SSD建模 10.8 SSD的哪些信息要放入词汇表中 10.9 示例:Monopoly SSD 10.10 过程:迭代和进化式SSD 10.11 历史和参考资料 第11章 操作契约 11.1...

    CSS网站布局实录 (第二版)PDF版

    2.10 代码注释 2.11 CSS开发环境与调试环境 第3章 CSS网页布局与定位 3.1 认识div 3.1.1 div是什么 3.1.2 如何使用div 3.1.3 理解div 3.1.4 并列与嵌套div结构 3.1.5 使用合适对象来布局 3.2 一列固定宽度 3.3 一列...

Global site tag (gtag.js) - Google Analytics