什么勾勒有优雅的函数(Clean Code读书笔记之二)

函数是代码组合的基本单位,高级编程语言的进化起结构化到面向对象,再届近年来坏发使复兴的势的函数式编程,函数都是构成这座高楼不可或缺的主干有,它的严重性不言而喻。本文将因「clean
code」第三章节的内容,大致捋一通如何勾勒来优雅的函数。

老三回说了当形容函数时应有专注的事体,作者首先以一个开源的测试工具(Fitnesse)来选了一个例,来说明好的函数该是呀体统。原则及其实和达标同首被讲到的命名的部分准绳很一般,就是一个名字如果能打说的,当然这同样章节还会说到非常多新的事物,这里用这个函数作为一个引子。

//代码2-1
public static String renderPageWithSetupsAndTeardowns(PageData pageData, boolean isSuite)throws Exception{
    boolean isTestPage = pageData.hasAttribute("Test");
    if(isTestPage){
        WikiPage testPage = pageData.getWikiPage();
        StringBuffer newPageContent = new StringBuffer();
        includeSetupPages(test Page, newPageContent, isSuite);
        newPageContent.append(pageData.getContent());
    }
}

从上述代码可以看来上一致段中涉嫌的有些东西,不要怕你的函数或者变量名为定义的不可开交丰富,在编译器已经快速进步的今日,对于生丰富之函数命名的处理就休见面化语言或性质的瓶颈了;然后所有函数就比如是在叙述做相同码业务的步调,每一样步我们且能看明白就是在涉及几什么事情,以上是事例十分好之显得了一个「好函数」应该的则。

自己都听了一个Oracle的工程师称到她们之编码要求,包括一个函数内部的if不能够跨越两个,所有的函数应该限制于10履行内等,与是例子的琢磨都是不谋而合。

下面开始列举作者对一个写好一个函数应该仍的规则的叙说:

1. 小!!!

The first rule of functions is that they should be small. The second
rule of functions is that they should be smaller than that.

稍稍之函数不肯定好,但是可以肯定的凡极长之函数一定是当某种程度上非常烂的。

作者说到他直以来的观是函数不应超过一个屏幕能够亮的品位,当然现在的屏幕越来越不行,那么一旦无要是下一个数字来说,他当相同履行不该超过150单字符(我看实际最好好还保持在80要120独字符中),函数的行数最好不要跨越100实践,如果能少20履最好不了了。

作者以此讲述了外以及名牌的Kent Beck的同等截讲话来比喻,Kent
Beck说一个函数最多应该不要过4行。这个的确来接触恐怖,我看能够说了算在20尽内就既死厉害了。函数要设计的略微连无是目的,而是经过写出来小函数来达到让程序的阅读者可以长足的羁押明白就段先后,而且再也短的先后往往意味着又少之bug。接下来会发出部分准绳,如果您得理解它们并尽量遵循,会中之帮助你勾勒起些许如强质量的代码。

  • 代码块和缩进
    作者以及时无异于节省讲了少单工作,代码块(就是if或者else块)的情尽多未超越一行,这样是以片被之函数往往得产生一个自解释的讳;一个函数的缩进等级最多不能够过2层。这半个要求在我看来都是最好严峻了,一般人还召开不至,不过为这面全力总是好的。

2. 一味做一样项事

一个好之函数应该只有开相同桩事,这是豪门常看的传道,那么怎么才能够说一个函数是「只做了平家从事」呢,如果一个函数做了3宗事,这使3桩事又有何不可说凡是另外一件事的3只步骤,那么这好不容易不到底「只开同样起事」呢?

作者认为这种状况是属于「只做了平等码事」的,但是是函数应该只有含有这3只步骤,而非包3独步骤的切切实实贯彻,也就是说,如果是函数里含有了有一个步骤的实际实现,那么这函数就非是「只开同样起事」。

换言之,如果一个函数function1里之几只报告词可以被extract出来改成一个新的函数function2,那么function1就从来不达成「只开相同起事吗」的规范。

  • 函数里之小节
    微人写代码喜欢当一个函数里应用不同之代码小节(比如第一节定义变量,第二节实例化这些变量,第三省还对这些变量进行部分操作),作者认为这重背离了「只开同样件事」原则,是老坏的惯。

3. 每个函数只含有同一个层级的虚幻

其一法是比好理解的,比如代码2-1负之getWikiPage()函数的内部贯彻,和renderPageWithSetupsAndTeardowns()里之几个函数调用就未在一个浮泛层级上;或者对newPageContent.append()的函数调用明显就是同其他函数调用不是当平抽象层级。

  • 起上使下的看代码:层层向下
    笔者认为好的代码读起来应当像是笔记叙文,自上而下的讲授完成同样桩业务的步调。换种说法就是是读一个程序即使比如是当读书一堆的TO(英文单词to,为了……)段落:为了开某起事情1,我们错过做了政工2,为了工作情2,我们去开了工作3。与此同时作者以说当是规则仍起来相当麻烦,但是及时是一个尽力的取向,努力去读书之规格会赞助而写出来又有些之,只包含同一级抽象的函数。

4. Switch语句

在coding过程遭到颇不便幸免如用到switch语句的景象,在这种状况下就坏为难去维持以上讲到的部分规则,作者的建议是对Switch语句,应该用她包裹起来,使用多态(具体说恐怕就是是概念抽象工厂方法,然后switch可以给在抽象工厂方法的兑现类似里,同时让switch对于它的调用者完全透明)为这函数的的确使用者提供服务。

5. 利用自解释(descriptive)的名字

函数的讳只要力所能及描述其自己的工作内容,不要惧怕函数称会变换得生丰富,一个长的自解释的名字比一个短的不明所以的名而好得差不多。

与此同时在名字的选上一经上下一致,这个标准以及前无异首讲话命名中的组成部分规则而产生同措施。

6. 函数参数

最精美的函数应该没参数的,其次比较好之凡仅仅发生一个参数的、只生半点个的,包含三单参数的函数应该尽量为免以,三只以上之参数的函数不应有留存。

蕴含参数的函数明显已包含了一个同函数内容无在跟一个层级上之纸上谈兵(参数本身),还有从测试的见解看,参数的在呢加强了描写测试用例的难度。

突发性小参数还为看作出口用途,这种情景应该尽量避免。

「Clean
Code」整本书都是基于Java和外类似之高等级语言也底蕴之,但是当有的看法不同的语言中,含有多个参数的函数在明亮上是了没问题之,但是她或于旁方(比如编写测试用例)也会见满怀于各式各样的题材。

  • 单个参数
    出少栽比较普遍的现象适合利用单个参数的函数,一种植是「函数是要是针对性斯参数问一个问题,并获得一个答案」(比如
    boolean
    fileExists(“MyFile”),另一样种是「此函数是设对这函数对这参数进行一个操作,把它们化另外一挨东西,并拿它回到」(InputStream
    fileOpen(“MyFile”))。

另外还有同栽情景比较不那么周边,但是也格外中之单个参数函数形式,event。这种状况下函数接受一个参数event,但是没回来值,函数会依据这个event对象来开展有另操作。

运这些形式时为同时如果动用一个得体的讳来清晰的讲述函数的用处,从而为代码阅读者可以清楚快速地问询函数的目的。

  • Flag参数
    Flag参数是丑陋的,不应当受以;往往一个富含Flag参数的函数可以让说或简捷的采用if
    else代码块就可齐平等的功用。

  • 简单独参数
    笔者认为简单独参数的函数是难以掌握的,唯一可能于适度的情景是,这片单参数本身即是「一个独对象的有限独不变的组件」,比如Point(x,
    y),x轴坐标和y轴坐标共同构成了平面坐标系受的一个沾。
    但是,作者认为简单单参数的函数并无是邪恶了,所有人都不可避免的当其实编程中动用其,但是得要询问它们是碰头带来有不良后果的,最好是可将这些函数都转发成单个参数的函数。

  • 老三个参数
    老三单参数的函数非常麻烦明白还不时会让误会,所以当使前最好好三怀念再三思。

  • 参数对象
    当一个函数需要2独或3独参数是,往往得将她们任何要部分封装成一个靶,从而达到减少参数数量,使函数更加容易掌握与保障的目的。

  • 参数列表
    有时一个函数会接受一个变长的参数列表,这种气象下实际它们可作为一个List结果的参数对象,所以可以给用作一个么参数的函数,作者是比较推荐这种方式的。

      public String format(String format, Object...args)
    
  • 动词和重要词
    运用一个吓的函数名好清楚的讲函数和参数的目的。对于单个参数的函数,函数和参数应该是一个「动词 +
    名词」的组合。

再有平等种植「关键词」的模式来当函数的名,比如使assertEquals(expected,
actural),而非是assertExpectedEqualsActual(expected,
actural),这样便无欲读者必须理解参数的逐条,从而降低了翻阅者代码的难度。

7. 并非闹副作用

函数的副作用就如谎言一样,一个函数声称她要开一样宗事,但是还要它同时举行了另外一桩「隐藏的」事,有时候它会修改好的切近吃的习性,有时候它会改传上的参数或者其他全局变量,不管啊种状况,这都是糟糕的。

  • 输出参数
    于「面向对象编程」出现之前(比如C语言),有时候要运用一个参数(通常是一个指针)来当函数的输出,但是于「OOP」中,「this」指针往往隐喻了其是用来当出口指针的意,那么输出参数应该尽量的避免下,如果产生这般的求,修改「this」中的性能往往是再好之选择。

8. 推行及搜索分离

一个函数要无执行了某个行为(比如改变了一个目标的状态),要无回话了有问题(比如返回某个对象的一些信息),但是不应以做这么点滴码事。

9. 使用Exception,不要以返回错误码

回错误码轻微地反其道而行之了直达一个条条框框,作者建议不用使用返回错误码而动抛出Exception的计。这样的计往往会时代码更短要清丽易读。

  • 提取try/catch代码块
    笔者建议以运try代码块常一旦拿try中的代码提取,使得整try/catch代码块是一个全然的错误处理代码块,而无带有具体的其余操作逻辑,这就合了「只开同样桩事」的准。

  • 错误处理是「一项事」
    笔者建议召开错误处理的函数,应该单纯做错误处理这「一宗事」,也就是说一个包含try关键词的错误处理函数应该是为try这个单词也开端的。如代码2-2所著:

      代码2-2
      public void delete(Page page){
          try{
              deletePageAndAllReferences(page).
          }catch(Exception e){
              logError(e);
          }
      }
    
  • 仗磁铁
    返回错误码的方法还有一个题目是,往往在这种现象下,所有的要错误处理的地方都见面得依赖是近乎或文件,这样的叫大依赖之类叫做「依赖磁铁」

凭借磁铁在日常的寻常支付被生为难幸免,而且自以为这吗无是一个得强力避免的规范。

10. 毫不还自己(Don’t repeat yourself)

咱俩以形容代码时多次会以同一个算法、或者千篇一律段处理逻辑、甚至同一段落同样的代码重复的产出于差不多个地方,甚至是跟一个来源文件的差地方。这往往是很多代码质量问题的源头,也发出许多编程原则以及最佳实践都是为着控制或消灭更设来的。

  • 结构化编程
    笔者认为要会保证保持函数「很有点」,那么多题目即使好化解了,那么结构化编程的组成部分条条框框(比如一个函数只发生一个输入和一个出口)则非需要让遵守了。

11. 公哪才能够写起如此的函数

程序员写代码和其他种类的做一样,是一个连改善的经过。作者认为写来好之函数大致是这般几单步骤

  • 先期直接拿想法写成代码,它们或者是好丰富而复杂的,可能违反了上述博条条框框,同时为会见生相同模仿单元测试来cover所有的代码用来开回归测试,做吧将来本着代码重构的底蕴
  • 接下来起针对代码进行改动,分离函数,修改名称,消灭更,同时如果维持测试用例完全通过。
  • 末了以上述有规则来针对函数进行地毯式的尾声修改。

12. 总结

如若您照以上有的规则,你的函数会变换得体量短小、良好命名、并且具有优秀的团队结构。但是永远不要遗忘这不是目的而是手段,你的尾声目的是深受总体体系进一步全面。

自我的博客

相关文章