clean code这本书是程序员必读经典之一

我相信大多数程序员都是去找过书的,网上有好多人都列了程序员必读经典,csapp,sicp,龙书,code complete是大家熟悉的几本经典。

我这里介绍的clean code其实被收入必读经典的频率其实也相当高,但是没有我刚列举的那些有名。但这本书对于没有好的编码风格的人来说绝对是非常重要的,并且容易习得。

适合人群

  • 能熟练使用一门编程语言。
  • 编码风格存在缺陷的程序员。
  • 想花一星期时间来提高的。

关于编码风格

国内大部分程序员或许都是以教科书入门的,这个时候,你就会发现一个很普遍的现象,命名都不优雅,有的网站(我在读的学校的教务系统)的命名还是拼音缩写。

这也难怪,那些教科书动辄int a,b,c,m,k;注释也不好好写,有的时候有的教科书和原文相比少一句注释,直接让我凝思苦想半小时还没结果,然后在网上一搜,发现了真理。。。

介于我们学的书编码质量如此之差,所以说国内程序员在编程风格上是吃了巨大的亏的,特别是在校生。变量命名是编程风格中基础的基础,但也是很重要的,没有好的命名,别说别人了,过了一星期自己都看不懂,而这无疑就是垃圾代码,天天看着垃圾代码,更何谈喜欢上编程。

编码风格的重要性

bug又名臭虫

整洁的代码就像整洁的玻璃,任何的虫子扒在上面能一眼找到
但是dirty的代码就像垃圾堆,你找一个虫子并把它干掉会无比艰辛

读代码比写代码难

前几天我才看完的一本书《观止-微软创建NT和未来的夺命狂奔》,是写Windows NT第一版的开发。

Windows NT第一版是20年前由超过250名成员共同编写的超过560万行代码的操作系统 (现在即便是内核都是至少千万行)。

我们想想看,当软件的代码量到了一个数量级,我们编码最困难的地方再也不是语法、算法,而是如何架构、组织、维护它

  • 现代社会很少有那种一个人完成的软件了,程序员之间的沟通至关重要的,唯有好的编码风格,他人才能更容易的阅读你的代码,从而和你进行深度有效的沟通。
  • 格式的笔记里面我也写道,或许你认为让代码能工作才是专业开发者的头等大事。但是实际上,修改和维护代码才是开发者花时间花得最多的地方。只有拥有良好的代码格式,代码的可读性才会增加,这对日后修改和维护产生深远影响。

所以说编码风格或许直接决定了整个程序的成败,一团糟的编码会使得整个程序难以维护,更别谈增加功能,很容易看到整个程序将走向再也无法维护的末路,而使得整个程序需要推倒重来。

vczh在知乎里也说过,面试的时候如果看github的主页,最看重的不是做了什么项目,而是看编码风格

编程是一门艺术

《黑客与画家》值得一读~

画画是一门艺术,我们知道,画画要讲究好多东西,布局,用色,笔法等等。

其实编程也是一样的,只有我们讲究了这些东西,我们才能像画画一样将自己脑海里的东西美美的落实于编码上,而不是由于完全不讲究章法,把整个画画的一塌糊涂,连自己都不忍卒读。

然后关于阅读笔记

具体情况具体分析,对于像我这种初学者来说,只能将这些有关整洁代码的概念记入脑海中,然后通过自己的无数实践(重构代码),体会实践的意义,这样才能真正找到属于自己的整洁编码之道。
相信对每一个人也是这样,书上的东西只是前人的体会,往往大牛的体会是有价值的,我们应该在实践中吸收。
我记的笔记或许就是前人总结的“真理”,而实践是检验真理的唯一标准

最后最重要的是我们日后编码的时候,要结合这些前人总结来实践,通过实践改善自己的编码风格,从而拥有良好的编码风格。

然后我把我认为最重要的记下来,方便读者速成,如果你认为需要深入专研,请务必读原书,因为我这里记录的只是一个个概念,为什么,都不够详细和深入。

命名

命名要有意义

  • 名副其实。通过名称我们能知道有关变量的大多数信息(是什么,做什么,怎么用)。
  • 无歧义。
  • 简洁易懂,简洁是建立在易懂的基础上的。

做有意义的区分

  • 去掉多余废话(前缀a,an,the)
  • 无意义区分容易产生歧义

尽可能避免使用的编码习惯

  • 把类型名字加进变量名里面(在强类型语言里面会增加阅读难度和修改代码的难度)
  • 丑陋的接口取名

其他细节

  • 命名取名规则使得程序更易读、规范统一。

    • 如java里常采用驼峰法:取名的时候,名字里如果有多个单词,则后面的单词的首字母要大写。
  • 要习惯把常量(34,”simply”)抽象成const变量(且变量名应该全部大写)使得以后的修改方便且不容易出错。

  • 类名大多数应该是名词
  • 方法名大多数应该是动词

  • 文件夹、文档文件用 - 分隔单词

  • 代码文件大部分用驼峰(不同语言风格不一样,比如 css 文件用 - ,所以要因地制宜,统一风格)

编写函数的规范

沃德原则:如果每个历程都让你感到深和己意,那就是整洁的代码

基本规范(重要)

  • (最为重要的一点)函数体尽可能短小尽可能短小
  • 一个函数只做一件事,并做好这件事。要判断函数是否只做了一件事,有一个办法是看在你编的函数里,你能否再拆出一个函数
  • 函数的数量也不应该太多。
  • 注意要将switch埋藏在较低的抽象层级。

函数参数

  • 参数名,最好和函数名有联系。这样可以,大大减轻记忆参数的负担
  • 禁止把布尔值传入函数

    • 因为这样做,意味着,宣称本函数不只做一件事:ture时做一件事,false时则在做另外一件事。
  • 函数参数的个数尽可能少最理想的参数数量是零

    • 这个规则,使得用函数更简单。
    • 还使得测试函数得到了方便,因为输入的参数少了,困难麻烦就少了。
  • 函数参数尽量是单个值的有序组成部份,或者多个有序的值,有序性是很重要的

    • 如果函数参数之间无序,你无法很快知道某个参数的作用。
  • 如果函数的参数有多个的话,可能需要将参数封装成对象,重要。

  • 应该避免使用输出参数(重要,后面的grade即是输出参数)。
    • 当某个函数必须要修改某个变量的时候,还不如修改所属对象的状态。这样以来我们可以通过对象来分析参数的意义,而仅仅通过某个变量所获取的会不足。比如changeGrade(grade)来调用显然没有student.changeGrade()舒服,这样也就是在用对象自身的方法来改变对象本身

函数的抽象层(重点,也称作粒度)

  • 函数的抽象层级以功能来划分,比如去买书,抽象层级:买书>去书店>走路
  • 函数的抽象层级的最高层类似于人类自然语言,使代码清晰易懂,简洁。
  • 确保每个函数在同一个抽象层级
  • 我们想要让代码拥有自顶向下的阅读顺序,因此让每个函数后面都跟着下一抽象层级的函数,此举方便了以后修改代码和阅读代码。

函数编写细则

  • 一定不要重复自己,重复的代码难以修复,且可读性差,应该把重复的代码写成函数。
  • 函数应该只做一件事,当做了多件事的时候就很容易产生副作用

    • 有的时候副作用往往是致命的,因为它的隐蔽性很强,不容易察觉,而又确实造成了影响。
    • 在对函数测试的时候,函数应该剔除所有副作用。
  • 函数要么”做什么事”,要么”回答什么事”。即是将指令和询问分隔开来

  • 抽离try/catch代码块,他们会搞乱了代码结构,把错误处理和正常流程混为一谈。所以应该把其主体部分抽离出来,另外写成函数。错误处理的代码应该就是包含它的函数的所有代码

总结

  • 好的函数并不是一开始就能写出来,而是通过分解函数、修改名称、消除重复反复打磨而成。我们相信没人能做到一开始就能写出符合这所有的规则的函数。但是厉害的人总能在修改中做到。

类的组织(代码顺序)

尽可能让外部可见的放在前面。变量优先于方法。

  1. 类应该从一组变量列表开始。如果有公共静态常量,应该先出现。然后是私有静态变量,以及私有实体变量。很少会有公共变量(尽量可能公共变量的数量)。
  2. 公共函数应跟在变量列表之后,最后再是私有函数。

类应该短小

  1. 类名应该精确。类的名称应该描述其全责。
  2. 一个类应该只有一个全责
  3. 内聚。

    • 类应该只有少量实体变量。类中的每个方法都应该操作一个或多个这样的变量。
    • 高的内聚性,意味着类中的方法和变量互相依赖、互相结合成一个逻辑整体。
    • 就像人一样,人暴露出来的属性和方法极少,而人体内的细胞、组织完成了数以万计的功能(当然人作为一个具体的类实在是只有上帝才能编写=,=,世间还没有更复杂的软件)。
  4. 将类从大类里面挣扎出来

    • 有时候,随着对方法的扩充,实体变量的数量开始上升,往往这意味着至少有一个类要从大类里面挣扎出来
    • 重构代码后,实体变量就可以分给几个不同的类了,而不是一堆挤在一起。

修进类的技巧

我们知道编写一个类不是一触而就的,而是通过了无数次修进的。而系统的每处修改(添加功能,改变逻辑方法等)都让我们冒着系统会出现问题的风险。这时候我们要对类加以修进(组织和重构),以降低修改所面临的风险。

  1. 当一个类庞杂巨大需要重构的时候,将一个类分隔为几个类,用明确的功能权责来划分。
  2. 当有新特性要添加时,可以写一个新类,如果能达到新类只用了原有类的极少数(一个或两个)方法时,就是低耦合度。原有类没有被干扰,新类也相当简洁(只服务于某个新特性)。
文章目录
  1. 1. 适合人群
  2. 2. 关于编码风格
  3. 3. 编码风格的重要性
  4. 4. 编程是一门艺术
  5. 5. 然后关于阅读笔记
  • 命名
    1. 1. 命名要有意义
    2. 2. 做有意义的区分
    3. 3. 尽可能避免使用的编码习惯
    4. 4. 其他细节
  • 编写函数的规范
    1. 1. 基本规范(重要)
    2. 2. 函数参数
    3. 3. 函数的抽象层(重点,也称作粒度)
    4. 4. 函数编写细则
    5. 5. 总结
    1. 1. 类的组织(代码顺序)
    2. 2. 类应该短小
    3. 3. 修进类的技巧
  • ,