编写可读代码的艺术

(一)修改外表

被修改过的代码都像华哥那样帅

把信息装到名字里

  • 选择专业的词

    getPage()可以具现为downloadPage()

  • 避免泛指的名字

    比如:tem,abc

    循环迭代器都喜欢使用:i、j、it做索引。但是有些复杂的情况下,最好使用更精确的名字。

  • 用具体的名字代替抽象的名字

    比如:ServiceCanStart()CanListenOnPort()

    检测服务端口是否可以开始监听,明显后一个要更好一些。

  • 为名字附带更多的信息

    • 带单位的值

      比如:start_ms 代表开始时间,单位为毫秒。

    • 带其他重要属性

      比如:password -> plaintext_password , data -> data_urlenc

      某些容易误解的变量可能会产生bug,所以附加一些属性也是很必要的。

  • 名字应该有多长

    • 在小的作用域里使用短的名字

    • 尽量不要缩写

      缩写对于新加入的成员很不友好,去维护旧代码也变得很难,更别说瞎缩写的。

    • 丢掉没用的词

  • 利用名字的格式来传递含义

    比如:规定静态变量必须用全大写+下划线_的形式来命名。

  • 其他格式规范

不会误解的名字

  • 推荐用minmax来表示极限

    比如:MAX_ITEMS_IN_CART = 10

  • 推荐用firstend来表示包含/排除的范围

  • 给布尔值命名

    通常,加上is、has、canshould这样的词,可以把布尔值变得更明确。

    避免使用反义名字:boolean disableSSL = false

  • 与使用者的期望相匹配

    有些名字之所以让人误解是因为用户对它们的含义有先入为主的印象。

    • get*()

      很多程序员习惯了把以get开始的方法当做轻量级访问器这样的用法,他只是简单的返回一个内部成员变量。

      避免使get方法成为非轻量级的操作。

    • list::size()

审美

  • 为什么审美这么重要

    使用审美上让人愉悦的代码更容易

  • 重新安排换行来保持一致和紧凑

  • 用方法来整理不规则的东西

    消除重复代码,功能变得清晰,添加新测试变得简单

  • 在需要时使用列对齐

  • 选择一个有意义的顺序,始终一致地使用它

  • 把声明按块组织起来

    适当的使用注释,区分自己方法内的一个个块。

  • 把代码分成“段落”

  • 个人风格与一致性

改写什么样的注释

注释的目的是尽量帮助读者了解得和作者一样多

  • 什么不需要注释

    不要为那些从代码本身就能快速推断的事实写注释

    • 不要为了注释而注释

    • 不要给不好的名字加注释–应该把名字改好

      好代码 > 坏代码 + 好注释

  • 记录你的思想

    • 加入导演评论

      比如:出乎意料的是,对于这些数据用二叉树比用哈希表快40%

    • 为代码的瑕疵写注释

      流行的程序员标记:TODO:还没处理的事情。FIXME:已知的无法运行的代码。HACK:对一个问题不得不采用的比较粗糙的解决方案。XXX:危险!这里有重要的问题。

    • 给常量加注释

  • 站在读者的角度

    • 意料之中的提问

    • 公布可能的陷阱

    • 全局观注释

    • 总结性注释

  • 克服作者心里阻滞

如何写出言简意赅的注释

注释应当有很高的信息/空间率

  • 让注释保持紧凑
  • 避免使用不明确的代词

    比如:it,this 等。

  • 润色粗糙的句子
  • 精确的描述函数的行为
  • 用输入/输出例子来说明特别的情况
  • 声明代码的意图
  • “具名函数参数”的注释
  • 采用信息含量高的词

(二)简化循环与逻辑

把控制流变得易读

把条件、循环以及其他对控制流的改变做得越“自然”越好。运用一种方式使读者不用停下来读你的代码。

  • 条件语句中参数的顺序

    比较的左侧:“被询问的”表达式,它的值更倾向于不断变化

    比较的右侧:用来做比较的表达式,它的值更倾向于常量

  • if/else语句块的顺序

    • 首先处理正逻辑而不是负逻辑的情况。
    • 先处理简单的情况。
    • 先处理有趣的或者可疑的情况。
  • ? :三目运算符

  • 避免do/while循环

  • 从函数中提前返回

  • 臭名昭著的goto

  • 最小化嵌套

    • 通过提早返回来减少嵌套

    • 减少循环内的嵌套

  • 执行的流程

拆分超长的表达式

把你的超长表达式拆分成更容易理解的小块。

  • 用做解释的变量

  • 总结变量

  • 使用德摩根定理

  • 滥用短路逻辑

    小心智能的代码段,可能使人读起来感到困惑。

  • 拆分巨大的语句

  • 简化表达式

变量与可读性

  • 减少变量

    • 是否拆分复杂的表达式

    • 是否做更多的澄清

    • 是否多次使用

    • 减少中间结果

    • 减少控制流变量

  • 缩小变量的作用域

    让你的变量对尽量少的代码行可见。

  • 只写一次的变量更好

    操作一个变量的地方越多,越难确定它的当前值。

(三)重新组织代码

抽取不相关的子问题

看到某个函数或代码块,问问自己:这段代码高层次的目标是什么?

对于每一行代码,问一下:它是直接为了目标而工作么,这段代码的高层次目标是什么?

如果足够的行数在解决不相关的子问题,抽取代码到独立的函数中。

  • 纯工具代码

  • 其他用途代码

  • 创建大量通用代码

  • 项目专有的功能

  • 简化已有的接口

  • 按需重塑接口

  • 过犹不及

一次只做一件事

  • 任务可以很小

  • 从对象中抽取值

把想法变成代码

  • 清楚的描述逻辑

    用自然语言描述解决方案。

  • 了解函数库

少写代码

最好读的代码就是没有代码。

  • 别费神实现那个功能

  • 质疑和拆分你的需求

  • 保持小代码库

  • 熟悉你周边的库

(四)测试与可读性

  • 使测试易于阅读和维护

    测试应该具有可读性,以便其他程序员可以舒服的改变或者增加测试。

  • 使测试更可读

    对使用者隐去不重要的细节,以便更重要的细节会更突出。

  • 让错误消息具有可读性

  • 选择好的测试输入

  • 为测试函数命名

  • 对测试友好的开发方式

    • 类中只有很少或者没有内部状态

    • 类/方法只做一件事

    • 每个类对别的类的依赖很少;低耦合

    • 函数的接口简单,定义明确

  • 走得太远

    • 牺牲真实代码的可读性,只是为了使能测试

    • 着迷于高测试覆盖率

    • 让测试成为产品开发的阻碍

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值