读书笔记---《编写可读代码的艺术》

前言

咱们曾经在很是成功的软件公司中和出色的工程师一块儿工做,然而咱们所遇到的代码仍有很大的改进空间。实际上,咱们曾见到一些很难看的代码,你可能也见过。可是当咱们看到写得很漂亮的代码时,会很受启发。好代码会很明确告诉你它在作什么。使用它会颇有趣,而且会鼓励你把本身的代码写得更好。本书旨在帮助你把代码写得更好。程序员

每一章都会深刻编程的某个方面来讨论如何使代码更容易理解。本书分红四部分:表面层次上的改进命名、注释以及审美——能够用于代码库每一行的小提示。简化循环和逻辑在程序中定义循环、逻辑和变量,从而使得代码更容易理解。从新组织你的代码在更高层次上组织大的代码块以及在功能层次上解决问题的方法。spring

第1章 代码应当易于理解

  • 代码的写法应当使别人理解它所需的时间最小化。
  • 减小代码行数是一个好目标,但把理解代码所需的时间最小化是一个更好的目标。
  • 常常想想其余人是否是会以为你的代码容易理解

第一部分 表面层次的改进

  • 选择好的名字
  • 写好的注释
  • 把代码整洁地写成更好的格式

第2章 把信息装到名字里

  • 把信息装进名字中
  • 选择专业的词
    • 避免使用tmp、retval、it、foo泛泛的词
    • 若是不把循环索引命名为(i、j、k),另外一个选择能够是(clubi、membersi、user_i)或者,更简化一点(ci、mi、ui)
  • 用具体的名字替代抽象的名字
  • 使用前缀和后缀来给名字附带更多信息
  • 决定名字的长度
    • 在小的做用域里可使用短的名字
  • 利用名字的格式来表达含义

第3章 不会误解的名字

  • filter是个二义性单词。咱们不清楚它的含义究竟是“挑出”仍是“减掉”。最好避免使用“filter”这个名字,由于它太容易误解。
  • 推荐用min和max来表示(包含)极限
  • 建议 命名极限最清楚的方式是在要限制的东西前加上max或者min
  • 推荐用first和last来表示包含的范围
  • 推荐用begin和end来表示包含/排除范围
  • 一般来说,加上像is、has、can或should这样的词,能够把布尔值变得更明确。
  • 不少程序员都习惯了把以get开始的方法当作“轻量级访问器”这样的用法,它只是简单地返回一个内部成员变量。若是违背这个习惯极可能会误导用户。相反,这个方法应当重命名为像computeMean()这样的名字,后者听起来更像是有些代价的操做。

第4章 审美

你们都愿意读有美感的代码。经过把代码用一致的、有意义的方式“格式化”,能够把代码变得更容易读,而且能够读得更快。下面是讨论过的一些具体技巧:编程

  • 若是多个代码块作类似的事情,尝试让它们有一样的剪影,使用一致的布局,让读者很快就习惯这种风格
  • 把代码按“列”对齐可让代码更容易浏览
  • 若是在一段代码中提到A、B和C,那么不要在另外一段中说B、C和A。选择一个有意义的顺序,并始终用这样的顺序
  • 用空行来把大块代码分红逻辑上的“段落”。

第5章 该写什么样的注释

注释的目的是帮助读者了解做者在写代码时已经知道的那些事情。本章介绍了如何发现全部的并不那么明显的信息块而且把它们写下来。什么地方不须要注释:mybatis

  • 能从代码自己中迅速地推断的事实
  • 用来粉饰烂代码(例如蹩脚的函数名)的“拐杖式注释”——应该把代码改好。你应该记录下来的想法包括:
    • 对于为何代码写成这样而不是那样的内在理由(“指导性批注”)
    • 代码中的缺陷,使用像TODO:或者XXX:这样的标记
    • 常量背后的故事,为何是这个值。
    • 站在读者的立场上思考:预料到代码中哪些部分会让读者说:“啊?”而且给它们加上注释
    • 为普通读者意料以外的行为加上注释
    • 在文件/类的级别上使用“全局观”注释来解释全部的部分是如何一块儿工做的
    • 用注释来总结代码块,使读者不致迷失在细节中

第6章 写出言简意赅的注释

本章是关于如何把更多的信息装入更小的空间里。下面是一些具体的提示:框架

  • 当像“it”和“this”这样的代词可能指代多个事物时,避免使用它们
  • 尽可能精确地描述函数的行为
  • 在注释中用精心挑选的输入/输出例子进行说明
  • 声明代码的高层次意图,而非明显的细节
  • 用嵌入的注释(如Function(/arg =/...))来解释难以理解的函数参数
  • 用含义丰富的词来使注释简洁

第二部分 简化循环和逻辑

第7章 把控制流变得易读

有几种方法可让代码的控制流更易读函数式编程

  • 在写一个比较时(while (bytesexpected > bytesreceived)),把改变的值写在左边而且把更稳定的值写在右边更好一些(while (bytesreceived <; bytesexpected))
  • 你也能够从新排列if/else语句中的语句块。一般来说,先处理正确的/简单的/有趣的状况。有时这些准则会冲突,可是当不冲突时,这是要遵循的经验法则
  • 某些编程结构,像三目运算符(:?)、do/while循环,以及goto常常会致使代码的可读性变差。最好不要使用它们,由于老是有更整洁的代替方式
  • 嵌套的代码块须要更加集中精力去理解。每层新的嵌套都须要读者把更多的上下文“压入栈”。应该把它们改写成更加“线性”的代码来避免深嵌套。一般来说提前返回能够减小嵌套并让代码整洁。“保护语句”(在函数顶部处理简单的状况时)尤为有用。

第8章 拆分超长表达式

  • 把超长表达式拆成更容易理解的小块
  • 引入解释变量

第9章 变量与可读性

关于程序中的变量是如何快速累积而变得难以跟踪的。你能够经过减小变量的数量和让它们尽可能“轻量级”来让代码更有可读性。具体有:函数

  • 减小变量,即那些妨碍的变量。咱们给出了几个例子来演示如何经过马上处理结果来消除“中间结果”变量
  • 减少每一个变量的做用域,越小越好。把变量移到一个有最少代码能够看到它的地方。眼不见,心不烦
  • 只写一次的变量更好。那些只设置一次值的变量(或者const、final、常量)使得代码更容易理解。

第三部分 从新组织代码

咱们会讲到三种组织代码的方法:工具

  • 抽取出那些与程序主要目的“不相关的子问题”
  • 从新组织代码使它一次只作一件事情
  • 先用天然语言描述代码,而后用这个描述来帮助你找到更整洁的解决方案

第10章 抽取不相关的子问题

  • 所谓工程学就是关于把大问题拆分红小问题再把这些问题的解决方案放回一块儿。把这条原则应用于代码会使代码更健壮而且更容易读。
  • 积极地发现并抽取出不相关的子逻辑
    • 纯工具代码
      • 一般来说,若是你在想:“我但愿咱们的库里有XYZ()函数”,那么就写一个!(若是它还不存在的话)通过一段时间,你会创建起一组不错的工具代码,后者能够应用于多个项目。
    • 其余多用途代码
      • 当format_pretty()中的代码自成一体后改进它变得更容易。当你在使用一个独立的小函数时,感受添加功能、改进可读性、处理边界状况等都更容易。
    • 建立大量通用代码
    • 项目专有的功能
    • 简化已有接口
    • 按需重塑接口
    • 过犹不及
      • 引入这么多小函数实际上对可读性是不利的,由于读者要关注更多东西,而且按照执行的路径须要跳来跳去

第11章 一次只作一件事

  • 应该把代码组织得一次只作一件事情。

第12章 把想法变成代码

  • 用天然语言描述程序而后用这个描述来帮助你写出更天然的代码。这个技巧出人意料地简单,但很强大。看到你在描述中所用的词和短语还能够帮助你发现哪些子问题能够拆分出来。 可是这个“用天然语言说事情”的过程不只能够用于写代码。

第13章 少写代码

  • 不是全部的程序都须要运行得快,100%准确,而且能处理全部的输入。若是你真的仔细检查你的需求,有时你能够把它削减成一个简单的问题,只须要较少的代码。
  • 咱们所描述的是宇宙的天然法则——随着任何坐标系统的增加,把它粘合在一块儿所需的复杂度增加得更快。 最好的解决办法就是“让你的代码库越小,越轻量级越好”,就算你的项目在增加。那么你就要:
    • 建立越多越好的“工具”代码来减小重复代码(见第10章)
    • 减小无用代码或没有用的功能
    • 让你的项目保持分开的子项目状态
    • 总的来讲,要当心代码的“重量”。让它保持又轻又灵。
  • 熟悉你周边的库
    • 不少时候,程序员就是不知道现有的库能够解决他们的问题。或者有时,它们忘了库能够作什么。知道你的库能作什么以便你可使用它,这一点很重要。

个人总结

在平常开发中,比较注重编码规范及命名等细节,我的认为命名和注释写得好是须要观察、积累和总结的,这也很重要,同时在阅读jdk、spring、mybatis等优秀框架源码也发现好的命名的重要性,下面总结了一些命名及编码方式,周知的驼峰命名、常量大写等就不列举了。只写一些书中没提到的。布局

命名相关

  • 动宾格式命名方法
    • prepareContext、prepareEnvironment
  • 前缀命名
    • spring中doXXX是真正作事情的方法,如doLoadBeanDefinitions、doRegisterBeanDefinitions
    • preXXX、postXXX:前置、后置处理方法
    • loadXXX:loadBeanDefinitions
  • 后缀命名
    • XXXListener:一看就知道是监听器
    • XXXFactory、XXXDelegate、XXXTemplate:使用了工厂模式、委派模式、模板模式等
  • 善用词性
    • listeners.starting()、listeners.started(context)等不用说就知道区别,表示不一样阶段
  • 名词单复数
    • user、users:分别表明一个用户和多个用户

代码风格

  • 按功能划分代码,一个类不超过千行
  • 常量统一写在头部
  • 屡次使用的抽象成工具类
  • 语义化、函数式编程

更多信息能够关注个人我的博客:逸竹小站逸竹小站post

也欢迎关注个人公众号:yizhuxiaozhan,二维码:公众号二维码

相关文章
相关标签/搜索