`
yidongkaifa
  • 浏览: 4038545 次
文章分类
社区版块
存档分类
最新评论

代码整洁之道——命名与函数

 
阅读更多
  • 有意义的命名
做有意义的区分
  • 不要以数字系列命名 没有提供导向作者意图的线索。如
    public void copyChars(char a1[], char a2[])

如果将参数名改成source和destination,就会像样许多。

  • 不要使用有相同意义的名字如ProductInfo和ProductData类,很难区分两者的区别。

使用读得出来的可搜索的名称

    • 尽量不要使用单字母名称和数字常量 如果要搜索一个数字或一个字母往往很难。长名字胜于短名字。
  • 函数
短小
  • 短小再短小 函数不应该有100行那么长,20行封顶最佳。
  • 代码块和缩进 if语句、else语句、while语句等,其中的代码应该只有一行,就是一个函数调用语句。这样既保持了代码的短小,也使函数更易于阅读和理解。

只做一件事

  • 如果函数只是做了该函数下的同一抽象层上的步骤,则函数只做了一件事
  • 或者看函数能否再拆出一个函数,该函数是其下一抽象层的实现。
  • 每个函数一个抽象层级 这是让代码读起来像是自顶向下的段落的有效方法。

函数参数

  • 最理想的参数数量是0,越多越不好 从测试的角度看,参数的增加将使测试用例指数性增长。
  • 一元函数的普遍形式 有两个极普遍的理由要向一个函数传单个参数。1,询问形式:想询问关于那个参数的问题,如boolean fileExits("Myfile")这样的; 2,转换形式:想要操作该参数,将其转换成什么,再输出之,如InputStream fileOpen("Myfile")这样的,把string类型的文件名转换为InputStream类型的返回值。
  • 二元函数 二元函数普遍比一元函数难懂。有些情况下使用二元函数是更好的,如定义一个点Point p = new Point(0, 0)。但对于如assertEquals(expected, actual)这样的二元函数,因为它没有自然顺序所以经常会搞错两者的位置。因此,我们应该尽量利用一些机制将其转换成一元函数。例如,写成expected.assertEquals(actual)。
  • 三个及以上参数 此时你应该想想其中一些参数是不是可以封装成类了。
  • 函数的名字 要给函数其个好名字,能够较好地解释函数的意图,以及参数的顺序和意义。对于一元函数和其参数应当使用非常良好的动词/名词对的形式。如write(name)就相当令人认同。更好的名称是writeField(name),它可以告诉人们"name"是一个"field"。 此外,我们还可以利用函数的关键字形式,即把参数名称加入到函数名中,如assertEquals改成assertExpectedEqualsActual(expected, actual)会好一些,减轻了记忆的负担。
  • 避免使用输出参数 如果函数要修改某种状态,应去修改所属对象的状态。

使用异常替代返回错误码

  • 返回错误代码往往是在if语句中使用的,这可能会导致更深层次的嵌套结构。当返回错误代码是,就是要求调用这立刻处理错误。例如:
    if (deletPage(page) == E_OK) {
        if (registry.deleteReference(page.name) == E_OK) { 
            if (...) {}
            else{}
       } else {
            logger.log();
       }
    }
    另一方面,如果使用异常替代返回错误值,错误处理就能从主代码中分离出来。
    try{
        ......
    } 
    catch (Exception e){
        logger.log();
    }
  • 抽离try/catch代码块 try/catch代码往往会搞乱了代码结构,最好把它们从主体代码中抽离出来,另外形成函数。
    public void delete(Page page) {
        try {
            deletePageAndAllReferences(page);
        }
        catch (Exception e) {
            logError(e);
        }
    }
    
    private void deletePageAndAllreference(Page page) throws Exception {
        deletePage(page);
        registry.deleteReference(page.name);
    }
    
    private void logError (Exception e) {
        logger.log(e.getMessage());
    }
    上例中,我们将try/catch代码块独立放到了delete函数中,然后又在try里调用正常流程的代码,在catch里调用处理错误的函数,这样美妙的区隔,delete函数就可以很容易理解并且忽略掉了,代码也更容易管理和修改。
  • 错误处理就是一件事 错误处理函数不应该再做其他事,这就意味着,如果try在某个函数中存在,它就应该是该函数的第一个单词,而catch代码块后面也不该再有其他内容,即“前无古人,后无来者”。
总结:大师级的程序员把系统当成故事来讲,而不是程序来写。永远别忘记,真正的目标在于讲述系统的故事,而你的代码(或函数)必须干净利落地拼装到一起,帮助你讲故事~~
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics