美文网首页
函数(clean code 学习笔记)

函数(clean code 学习笔记)

作者: HelenYin | 来源:发表于2020-02-25 15:11 被阅读0次

    短小

    • 代码块和缩进
      ifelsewhile,其中的代码块应该只有一行。该行大抵是一个函数调用语句。这样不但能保持函数的短小,而且,因为块内调用的函数拥有比较说明性的名称,从而增加了文档上的价值。
      所以函数的缩进层不应该多余一层或者两层。

    bad


    good


    只做一件事情

    • 函数应该做一件事情,做好一件事情,只做一件事情。
      要判断函数是否不止做了一件事,就是看是否能拆除一个函数。
    • 每个函数一个抽象层级
      函数中混杂不同抽象层级,往往让人迷惑,读者可能我发判断某个表达式是基础概念还是细节,一旦细节与基础概念混杂,更多的细节就会在函数中纠结起来。
    自顶向下读代码

    我们想让代码拥有自顶向下的阅读顺序。我们想要让每个函数后面都跟着位于下一抽象层级的函数。

    switch 语句

    使用描述性的名称

    好名称的价值怎么好评都不为过
    别害怕长名称,长而具有描述性的名称,要比短而令人费解的名称好。
    长而具有描述性的名称,要比描述性的长注释好。
    命名方式保持一致。

    函数参数

    最理想的参数数量是零,其次是1,再其次是2,应尽量避免3。有足够特殊的理由才能用三个以上参数。

    一元函数的普遍形式
    1. 操作该参数,将其转化为其他的什么东西在输出。例如: InputStream fileOpen('MyFile')String类型的文件名转换为InputStream类型的返回值。
    2. 事件(event),这种形式有输入参数而无输出参数。程序将函数看作是一个事件,使用该参数修改系统状态。
      尽量避免不遵循这两个形式一元函数。
    标致参数

    不要向函数参数传入布尔值,这样做等于大声宣布本函数不止做了一件事。
    例如: render(Boolean isSuite),应该把该函数一分为二renderForSuiterenderForSingleTest

    二元函数

    有两个参数的函数比一元函数难懂。但是当两个参数正好是单个值的有序组成部分二元参数就正好,比如new Point(0,0)
    应该尽量利用一些机制将二元函数转为一元函数。

    参数对象

    如果一个函数看来需要两个或三个参数,就说明其中一些参数可以封装成类

    可变参数

    String.format("%s worked $.2f hours", names, hours)
    如果可变参数像上例这样,就和类型为list的单个参数没有区别。这样一来String.format实则是二元参数。

    void dyad(String name, Integer ...args)
    
    动词与关键字

    对于一元函数和参数,应该形成一个非常良好的动词/名词对形式,例如 write(name)writeField(name)这个名称更好,告诉我们name是一个field

    无副作用


    这段代码的副作用在Session.initialize()。原本checkPassword是用来检查密码的,该名称并没有按时他会初始化这次会话,所以当某个误信函数名称的使用者,想要检查用户的有效性,就有抹除当前会话的风险。
    这一副作用是时序性耦合,也就是说checkPassword只能在特定时刻调用。

    “指令”与“询问”规则

    函数要么做什么事,要么回答什么,但是两者不能混用

    public boolean set(String attribute, String value)
    

    调用:

    if (set("username", "helen")){}
    

    这样意义不明确,应该改为

    if (attributeExit("username")) {
      setAttribute("username", "helen");
    }
    

    上面就是“指令”与“询问”规则。

    使用异常替代错误返回码

    当我们直接返回错误码时,可能因为需要马上处理错误码,导致更深层次的嵌套,当错误码返回时要求调用者马上处理错误



    如果使用异常替代返回错误码,错误代码就能从主路径代码中分离出来


    抽离try/catch 代码块

    最好把try catch的主体部分的代码抽离出来。比如上面的事例可以改为

    public void delete (Page page) {
      try {
        deletePageAndAllReference(page);
      }
      catch (Exception e) {
        logError(e); 
      }
    }
    private void deletePageAndAllReference(Page page) {
      delete(page);
      registry.deleteReference(page.name);
      configKeys.deleteKey(page.name.makeKey());
    }
    private void logError(Excetion e) {
      logger.log(e.getMessage());
    }
    

    这样delete函数只与错误处理有关,deletePageAndAllReference函数只与删除一个页面有关。

    错误处理就是一件事

    函数应该只做一件事,错误处理就是一件事,所以错误处理函数不应该做其他事,如果try在某个函数中存在,他就该在这个函数的第一个单词,而且catch,finally后也不应该有其他代码。

    消除重复代码

    相关文章

      网友评论

          本文标题:函数(clean code 学习笔记)

          本文链接:https://www.haomeiwen.com/subject/oggggctx.html