《Clean Code》读书笔记(二)——Functions

《Clean Code》的中文译名是《代码整洁之道》,属于 [CnBeta](http://www.cnbeta.com) 不久前推荐的程序员必读 11 书之一。适合有一定工作经验的程序员阅读和提升代码质量。书中认为代码的质量的根源还是来自于一种“代码感”。书中会极力用作者及其友人几十年从业经验来阐述何谓“Clean Code”,但是本书仍然无法教会那种“代码感”。         本文是书中第三章的读书笔记,名为“ Functions ”,讲述函数编程中的“代码整洁之道”。         本章最重要的一句话应该是:“FUNCTIONS SHOULD DO ONE THING. THEY SHOULD DO IT WELL. THEY SHOULD DO IT ONLY.”(函数应该做一件事。它们要做好那件事。它们只能做那一件事。)         也就是说,“整洁”的函数代码应该要有一种自明性。这种自明性不来自于注释,而来于使用者看到函数的那几秒钟,能做出瞬间的正确判断。这种瞬间判断不必借助于注释,不必寻找函数的本体,不会引起明显的误会,不会带来多义的困惑。不管是函数本体还是调用,最好只要是个人,看见语句那一瞬,就猜到其作用和参数顺序,而且基本不会猜错。         如何做好这种自明性呢?书中将宝贵的经验如数家珍,列举出来。
  1. 小!
    要多小呢?2-4行;
  2. blocks and identing
    何意?If、else、While 包含的代码块中只能有一行;
  3. 只做一件事
    函数应该做一件事。它们要做好那件事。它们只能做那一件事。
  4. 同等抽象程度
    函数中不能细节和抽象混淆,就像 .append(“\n”) 和 getHTML();
  5. Switch 语句
    这是一个必然导致多行、重复等各种问题的语句,处理办法:放入 abstract factory (设计模式的一种);
  6. 描述性命名
    函数的名字是函数功能的描述,可以很长,可以不停改,但同一个意义的用词要一致,参见上一章“meaningful names”;
  7. 参数个数
    最好没有,次好一个,再次两个,避免三个,别用更多;
  8. 通用单参数形式
    避免这两种形式的其它单参数函数的出现,这两种形式是:1)回答问题 boolean fileExists(“myFile”); 2)转化传入值并返回 InputStream fileOpen(“myFile”);
  9. Flag参数
    就是类似这样 render(boolean isNumber)。如 isNumber 为 true ,做一件事。为 false ,做另一件事。这违反了“只做一件事”;
  10. 双参数
    两个参数最好一一对应,缺一不可,前后次序可以预知。比如点的坐标 setPoint(x, y)
  11. 三参数
    只推荐了一种三参数情况 assertEquals(1.0, amount, 0.01),因为可以给用户一个提醒:“浮点数的相等与精确性有关”;
  12. 减少参数的方法
    将有关联的组合成类;
  13. 提示参数顺序的方法
    在函数名字中暗示
  14. 无副作用
    比如 checkPassword() 里就不要包含 Session.initialize() ,不然被误调用的话,用户的 session 就被清空了;
  15. 输出参数
    不要传参然后又改变参数的值,用 参数.方法() 的形式;
  16. 答问和命令分开
    也就是用 if( attributeExists(“username”) ) 替代 if( set(“username”, “unclebob”) ) ,后者比前者更迷惑人;
  17. 用异常代替错误代码
    当错误代码的 enum 变更时,维护十分繁琐,而且要出错立即处理,错误处理就和主体代码混杂一起。而如果采用 Exception 则符合“只做一件事”的原则,同时免除前述的所有麻烦;
  18. 不要自我重复
    比如三个函数分别对应:任务加载、工作加载和计划加载,三者都 .append(data[x].name).append(data[x].time),这时要设法将重复的这些 .append 写成函数;
  19. 结构化编程
    函数代码较短时,偶尔用多个 renturn, break 或 continue 语句亦可,goto则要避免(话说现在还有人用 goto 么?);
  20. 如何做到上述标准——
    先调试好一个正确运行的代码,然后边调试边重构。

    本文完结。其实 Functions 这一章中,很多和 meaningful names 一章是重复的,比如第 3、9、11 。还有很多是可以相辅相成的,比如 1 和 13。说的玄一些,也许这就是所谓“代码感”——很多条经验都是相互联系的,交错形成一种“感觉”,便是本书所真正想表达的吧! 看这章的过程中发生了许多趣事。值得一提的是,那时我只看到第四条“同等抽象程度”。于是我费劲的拆我的 JavaScript 代码。然而那是一个给 input Box 绑定自动完成和自动搜索功能下拉框的函数。参数极其多,而我又没意识到,还不敢用全局变量。于是当我沿着函数走的顺序流程,把每个都只有 3 - 4 行的函数的参数一个个从 2 个加到5个之后……彻底风中凌乱了……还好,函数正常运行着,可我再也不想碰它了…… 这大概可以算个典型的生搬硬套的笑话吧!