前端阅读——《代码整洁之道》摘记之整洁代码命名函数注释

宁静致远 宁静致远     2022-09-24     642

关键词:

这本书提出一种观念:代码质量与其整洁度成正比。干净的代码,既在质量上较为可靠,也为后期维护、升级奠定了良好基础。(作者认为书可以有另一个名字:《如何在意代码》)

读这本书,促使我思考代码中何谓正确,何谓错误。更重要的是,它还可以促使自己重新评估自己的专业价值观,以及对自己技艺的承诺。

1、整洁编程

  • 混乱风险:制造混乱无助于赶上期限。混乱只会立刻拖慢你,叫你错过期限,赶上期限的唯一方法——做得快的唯一方法——就是始终尽可能的保持代码整洁。
  • 代码感:写整洁代码,需要遵循大量的小技巧,贯彻刻苦习得的“整洁感”。这种“代码感”就是关键所在。缺乏“代码感”的程序员,看混乱是混乱,无处着手。有“代码感”的程序员能从混乱中看出其他的可能与变化。“代码感”帮助程序员选出最好的方案,并指导程序员制订修改行动计划,按图索骥。
  • “整洁的代码只做好一件事”——Bjarne Stroustrup(C++语言发明者)。软件设计的许多原则最终都会归结为这句警语。糟糕的代码想做太多事,它意图混乱、目的含混。整洁的代码力求集中。每个函数、每个类和每个模块都全神贯注于一事,完全不受四周细节的干扰和污染。

    整洁的代码应可由作者之外的开发者阅读和增补。它应当有单元测试和验收测试。它使用有意义的命名。它只提供一种而非多种做一件事的途径。它只有尽量少的依赖关系,而且要明确地定义和提供清晰、尽量少的API。代码应通过其字面表达含义,因为不同的语言导致并非所有必需信息均可通过代码自身清晰表达。——Dave Thomes(OTI公司创始人,Eclipse战略教父)

  • 贝克的简单代码规则:消除重复并提高表达力,提早构建简单抽象
  1. 能通过所有测试
  2. 没有重复代码
  3. 体现系统中的全部设计理念
  4. 包括尽量少的实体,比如类、方法、函数等

 

2、有意义的命名

  • 名副其实
  • 避免误导
  • 做有意义的区分
  • 使用读的出来的名称
  • 使用可搜索的名称
  1. 单字母名称用于短方法中的本地变量。名称长短应与其作用域大小相对应。若变量或常量可能在代码中多处使用,则应赋其以便于搜索的名称。
  • 避免使用编码
  1. 不必用m_前缀来标明成员变量。应当把类和函数做的足够小,消除对成员前缀的需要。(人们会很快学会无视前缀或后缀,只看到名称中有意义的部分。代码读的越多,眼中就越没有前缀。最终,前缀变作了不入法眼的废料,变作了旧代码的标志物)
  • 避免思维映射
  1. 单字母变量名就是个问题。在多数除循环计数器之外的其他情况下,单字母名称不是个好选择,读者必须在脑中将它映射为真实概念。(仅仅是因为有了a和b,就要取名为c,实在并非像样的理由。)
  2. 聪明程序员和专业程序员之间的区别在于:专业程序员了解,明确是王道。专业程序员善用其能,编写其他人能理解的代码。
  • 类名
  1. 类名和对象名应该是名词或名词短语,如Customer、WikiPage、Account和AddressParser
  2. 避免使用Mannager、Processor、Data、或Info这样的类名。
  • 方法名
  1. 方法名应当是动词或动词短语,如postPayment、deletePage或save
  2. 属性访问器、修改器和断言应该根据其值命名,并依Javabean标准加上get、set和is前缀。
    string name = employee.getname();
    customer.setName("mike");
    if (paycheck.isPosted())...
  • 别扮可爱
  1. 言到意到,意到言到。
  • 每个概念对应一个词
  1. 给每个抽象概念选一个词,并且一以贯之。(对于那些会用到你代码的程序员,一以贯之的命名法简直就是天降福音)
  • 别用双关语
  1. 避免将同一单词用于不同目的。同一术语用于不同概念,基本上就是双关语了。
  2. 比如,在多个类中都有add方法,该方法通过增加或连接两个现存值来获得新值。假设要写个新类,该类中有一个方法,把单个参数放到群集(collection)中。如果把这个方法叫做add,貌似和其他add方法保持了一致,但实际上语义却不同,应该用insert或append之类词来命名才对。(把该方法命名为add,就是双关语了)
  • 使用解决方案领域名称
  1. 记住,只有程序员才会读你的代码。所以,尽管去用那些计算机科学术语、算法名、模式名、数学术语吧
  2. 比如,对于熟悉访问者(VISITOR)模式的程序员来说,名称AccountVisitor富有意义。(程序员要做太多技术性工作,给这些事取个技术性的名称,通常是最靠谱的做法)
  • 使用源自所涉问题领域的名称
  1. 如果不能用程序员熟悉的术语来给手头的工作命名,就采用从所涉问题领域而来的名称吧。至少,负责维护代码的程序员就能去请教领域专家了。
  2. 优秀的程序员和设计师:其工作之一就是分离解决方案领域和问题领域的概念。与所涉问题领域更为贴近的代码,应当采用源自问题领域的名称。
  • 添加有意义的语境
  1. 很少有名称是能自我说明的——多数都不能。反之,你需要用到良好命名的类、函数或名称空间来放置名称,给读者提供语境。如果没这么做,给名称添加前缀就是最后一招了。
  2. 比如,对孤零零的一个state变量来说,可以添加前缀addrFirstName、addrLastName、addrState等,以此提供语境。至少,读者会明白这些变量是某个更大结构的一部分。当然,更好的方案是创建名为Address的类。这样,即便是编译器也会知道这些变量隶属某个更大的概念了。
  3. 语境的增强,也让算法能够通过分解为更小的函数而变得更为干净利落。
  4. //语境不明确的变量
    private void printGuessStatistics(char candidate,int count){
          String number;
          String verb;
          String pluralModifier;
           ...
    }
    
    //有语境的变量
    //创建GuessStaticsMessage类,把三个变量做成该类的成员字段
    public class GuessStaticsMessage{
          String number; 
          String verb; 
          String pluralModifier; 
           ... 
    }
  • 不要添加没用的语境
  1. 设若有一个名为“加油站豪华版”(Gas Station Deluxe)的应用,在其中给每个类添加GSD前缀就不是什么好点子。
  2. 只要短命称足够清楚,就要比长名称要好。
  3. 对于Address类的实体来说,accountAddress和customerAddress都是不错的名称,不过用在类名上就不太好了。Address是个好类名。如果需要与MAC地址、端口地址和Web地址相区别,我会考虑使用PostalAddress、MAC和URI。这样的名称更为准确,而精确正是命名的要点

 

3、函数

  •  短小
  1. 代码块和缩进:if语句、else语句、while语句等,其中的代码块应该只有一行。该行大抵应该是一个函数调用语句。这样不但能保持函数短小,而且,因为块内调用的函数拥有较具说明性的名称,从而增加了文档上的价值。
  2. 这也意味着函数不应该大到足以容纳嵌套结构。所以,函数的缩进层不该多于一层或两层。(这样的函数易于阅读和理解)
  • 只做一件事
  1. 函数应该做一件事。做好这件事。只做这一件事。
  2. 问题在于很难知道那件该做的事是什么?(其实,有时候一件事也很容易被看作是三件事或很多具体细化的步骤)如果函数只是做了该函数名下同一抽象层上的步骤,则函数还是只做了一件事
  3. 要判断函数是否不止做了一件事,还有一个方法,就是看是否能再拆出一个函数,该函数不仅只是单纯地重新诠释其实现。
  4. 函数中的区段:只做一件事的函数无法被合理的切分为多个区段。(这也是函数做事太多的明显征兆)
  • 每个函数一个抽象层级
  1. 函数中混杂不同抽象层级,往往让人迷惑。读者可能无法判断某个表达式是基础概念还是细节。更恶劣的是,就像破损的窗户,一旦细节与基础概念混杂,更多的细节就会在函数中纠结起来。
  2. 自项向下读代码:向下规则。这是保持函数短小、确保只做一件事的要诀。让代码读起来像是一系列自项向下的TO起头段落是保持抽象层级协调一致的有效技巧。

          

  • switch语句
  1. 问题:写出短小的switch语句很难(包括if/else在内),写出只做一件事的switch语句也很难,Switch天生要做N件事。
  2. 解决:利用多态,确保每个switch都埋藏在较低的抽象层级,而且永远不重复。
  3. 如下代码:将switch语句埋到抽象工厂底下,不让任何人看到。该工厂使用switch语句为Employee的派生物创建适当的实体,而不同的函数,如calculatePay、isPayday和deliverPay等,则藉由Emplyee接口多态地接受派遣。
  4. 对于switch语句,(作者的)规矩是如果只出现一次,用于创建多态对象,而且隐藏在某个继承关系中,在系统其他部分看不到,就还能容忍。当然也要就是论事,有时也会部分或全部违反这条规矩。

        

  • 使用描述性的名称
  1. 沃德原则:“如果每个例程都让你感到深合己意,那就是整洁代码。”函数越短小、功能越集中,就越便于取个好名字。
  2. 别害怕长名称。长而具有描述性的名称,要比短而令人费解的名称好。长而具有描述性的名称,要比描述性的长注释好。
  3. 选择描述性的名称能理清你关于模块的设计思路,并帮你改进之。追索好名称,往往导致对代码的改善重构。
  4. 命名方式要保持一致。使用与模块名一脉相承的短语、名词和动词给函数命名。例如:includeSTeardownPages、includeSetuoPages、includeSuiteSetupPage等
  • 函数参数
  1. 最理想的参数数量是零(零参数函数),其次是一(单参数函数),再次是二(双参数函数),应尽量避免三(三参数函数)。有足够特殊的理由才能用三个以上参数(多参数函数)——所以无论如何也不要这样做。
  2. 阅读模块所讲述的故事时,includeSetupPage()要比includeSetupPageInto(newPage-Content)易于理解。参数与函数名处在不同的抽象层级,它要求了解目前不是特别重要的细节(即那个Stringbuffer
  3. 测试的角度:要编写能确保参数的各种组合运行正常的测试用例,是一件非常困难的事情。
  4. 输出参数比输入参数还要难以理解。
  • 无副作用
  1. 副作用是一种谎言。函数承诺只做一件事,但还是会做其他被藏起来的事。有时,它会对自己类中的变量做出未能预期的改动。有时,它会对自己类中的变量做出未能预期的改动。有时,它会把变量搞成向函数传递的参数或是系统全局变量。无论哪种情况,都是具有破坏性的,会导致古怪的时序性耦合顺序依赖。(如果一定要时序性耦合,就应该在函数名称里说明)
  2. 输出参数:参数多数会被自然而然地看作是函数的输入。普遍而言,应避免使用输出参数。如果函数必须要修改某种状态,就修改所属对象的状态吧。
  • 分隔指令与询问
  1. 函数要么做什么事,要么回答什么事,但二者不可得兼。
  2. 函数应该修改某对象的状态,或是返回该对象的有关信息。两样都干常会导致混乱。
  • 使用异常替代返回错误码
  1. 从指令式函数返回错误码轻微违反了指令与询问分隔的规则。它鼓励了在if语句判断中把指令当作表达式使用。另一方面,如果使用异常替代返回错误码,错误处理代码就能从主路径代码中分离出来,得到简化。
  2. 抽离Try/Catch代码块:Try/Catch代码块丑陋不堪。它们搞乱了代码结构,把错误处理与正常流程混为一谈。最好把它的主体部分抽离出来,另外形成函数。如图:
  3. 错误处理就是一件事:函数应该只做一件事,错误处理就是一件事,因此,处理错误的函数不该做其他事。

       

  • 如何写出这样的函数
  1. 一开始都冗长而复杂。然后,会打磨,分解函数、修改名称、消除重复。缩短和重新安置方法。有时还拆散类。同时保持测试通过。
  2. 并不从一开始就按照规则写函数。一般没人做得到。

 

4、注释

  • 注释会撒谎。
  1. 注释存在的越久,就离其所描述的代码越远,越来越变得全然错误。(原因很简单,程序员不能坚持维护注释)
  • 注释不能美化糟糕的代码
  1. 带有少量注释的整洁而有表达力的代码,要比带有大量注释的零碎而复杂的代码像样的多。
  • 用代码来阐述
  1. 很多时候,简单到只需要创建一个描述与注释所言同一事物的函数即可。
  • 好注释——唯一真正好的注释是你想办法不去写的注释
  1. 法律信息
  2. 提供信息的注释
  3. 对意图的解释
  4. 阐释
  5. 警示
  6. TODO注释(一种程序员认为应该做,但由于某些原因目前还没做的工作)
  7. 放大
  8. 公共API中的Javadoc
  • 坏注释
  1. 喃喃自语
  2. 多余的注释
  3. 误导性注释
  4. 循规式注释
  5. 日志性注释
  6. 废话注释
  7. 可怕的废话
  8. 能用函数或变量时就别用注释
  9. 位置标记
  10. 括号后面的注释(尽管这对于含有深度嵌套结构的长函数可能有意义,但只会给我们更愿意编写的短小、封装的函数带来混乱。如果你发现自己想标记右括号,其实应该做的是缩短函数)
  11. 归属与署名
  12. 注释掉的代码
  13. HTML注释
  14. 非本地信息
  15. 信息过多
  16. 不明显的联系
  17. 函数头
  18. 非公共代码中的Javadoc

 

注:转载请注明出处

代码整洁之道

...只有类的命名用名词,方法的命名用动词,我们程序员在阅读代码的过程中才像是正在阅读现实中的解决问题,我们写的 查看详情

代码整洁之道(代码片段)

...可见命名。我们给变量、函数、参数、类和封包命名、源代码文件命名、目录命名,良好的命名规范使得代码以及工程的维护难度大大降低,下面列出良好命名的几条简单规则。1.名副其实变量、函数或类的名称应该已经... 查看详情

typescript代码整洁之道

干净整洁的代码,不但质量更可靠,也为后期升级、维护打下了良好的基础。那么,整洁代码的衡量标准是什么?本文将RobertC.Martin的CleanCode思想融入到TypeScript,一起探讨研究代码整洁之道。 WTFs/Minute 1.命名的艺术计算... 查看详情

代码整洁之道

...释不如无注释,不能保证注释新鲜,删除注释。四、格式代码排版上下有间隙代码 查看详情

第五次读书笔记——robrtc.martin的《代码整洁之道》

...者RobrtC.Martin的《代码整洁之道》。一周的时间,我主要阅读了本书的前五章,关于整洁代码、有意义的命名、函数、注释以及格式等内容。书中作者有个观点:优雅和高效。作者说:代码逻辑应当直截了当,叫缺陷难以隐藏;... 查看详情

读《代码整洁之道》有感

本周我开始阅读RobertC.Martin所著的《代码整洁之道》一书,希望能从中收获高效编写代码的诀窍,因为我自认为我的代码有时候比较糟糕,不太容易维护。一方面,是我没有养成良好的编程习惯;另一方面,我不太清楚什么才是... 查看详情

代码整洁之道-函数

函数参考书籍:《代码整洁之道》,语言:Python1.函数要短小1)每个函数只做一件事,并且每个函数都依次把你带到下一个函数,这就是函数应该达到的短小程度。2)if,else,while等语句的代码块应该只有一行,该行大概是一个函... 查看详情

代码整洁之道-函数

函数参考书籍:《代码整洁之道》,语言:Python1.函数要短小1)每个函数只做一件事,并且每个函数都依次把你带到下一个函数,这就是函数应该达到的短小程度。2)if,else,while等语句的代码块应该只有一行,该行大概是一个函... 查看详情

代码整洁之道读书笔记

代码整洁之道 前言如何用功 阅读大量代码 找优点和缺点第一章整洁代码不要留到以后,稍后等于永不烂代码影响生产力代码整洁性不但有关效率,还有关生存好代码 C++之父  尽量减少依赖关系,便于维护... 查看详情

代码整洁之道

文章目录代码整洁之道定义变量名字的时候常用的单词有意义的命名怎样写简洁的,别人一眼可以看的懂的方法方法参数越少越好注释格式别给方法返回null值我们该提炼方法中的变量还是不提炼方法中的变量?代码整洁之道定... 查看详情

代码整洁

整洁的代码能够提高项目的可读性、可维护性、可扩展性,这二天大致看了一本书代码整洁之道,粗略的看了一遍,总结了一下,写下来作为以后做项目的时候的参考。代码的整洁简单的总结二种分类:1.命名?有意义命名说明:... 查看详情

读c#代码整洁之道笔记02_类对象和数据结构及编写整洁函数

...职责就是类所具备的功能3. 从注释生成文档3.1. 源代码文件的顶部都应当包含版权声明3.2. 命名空间、接口、类、枚举、结构体、方法和属性都应当包含注释4. 内聚4.1. 高内聚4.1.1. 代码应恰当分组4.2. 低... 查看详情

《代码整洁之道》

代码整洁之道代码猴子(CodeMonkey):低水平编码者.童子军规.技艺(craftsmanship):知和行.学写整洁代码,掌握原则和模式,并付出行动.整洁代码代码呈现了需求的细节.这些细节无法被忽略或抽象,必须要严谨,精确,规范和详细.糟糕的代码... 查看详情

代码整洁之道——2函数

一、函数参数(两个或者更少)限制函数的参数至关重要,因为这样测试函数会更简单。有超过三个以上的参数,测试的时候就要使用不同参数测无数的场景。一个或者两个参数是理想情况。如果可能的话避免三个参数。三个以... 查看详情

代码整洁之道(代码片段)

有意义的命名1名副其实2避免误导3做有意义的分区废话都是冗余。Variable永远不应出现在变量名中,Table一词永远不应出现在表名中。当缺少明确约定:变量moneyAmout与money没区别,customerInfo与customer没区别,accountData与account没区别... 查看详情

代码整洁之道(代码片段)

有意义的命名1名副其实2避免误导3做有意义的分区废话都是冗余。Variable永远不应出现在变量名中,Table一词永远不应出现在表名中。当缺少明确约定:变量moneyAmout与money没区别,customerInfo与customer没区别,accountData与account没区别... 查看详情

代码整洁之道

由于大量的工作程序的复杂度越来越高,需要更多的时间去花很多的时间去调试,所以我们更需要去深思。少既是多细节的关注甚至是关键的专业性基础。首先开发者通过小型实践获得可用于大型实践的技能和信用度。如。宏大... 查看详情

代码整洁之道读书笔记

代码整洁之道TableofContents1.原则1.1.单一权责1.1.1.一个类应该完成一个类型的任务1.1.2.內聚性要高,即每个函数使用类变量的多少1.2.开放封闭原则1.2.1.对内封闭对外开放2.军规2.1.只做好一件事2.2.短小精悍2.3.代码不要重复2.4.开... 查看详情