2015年5月27日晚19:45左右,我们开发小组开了一个分享会,会上靖哥哥做主要分享人,我负责记录大家讨论的精华部分,然后整理成文;本文包含了原书中的主要思想,也包含了我们小组的实战总结。
可读性基本定理
代码的写法应当使别人理解它的时间最小化。
这也是这本书的目标,简单说,好的代码应当易于理解。
如何使代码易于理解呢?可以从四个方面来改进:
一. 表面层次上改进:命名,注释和审美
要多问自己几遍:“这个名字会被别人解读成其他的含义吗?”要仔细审>视这个名字。
提到命名,看似简单,实则不易。名字是给人读的,不是给机器读的,所以不是说只要编译器编译通过就算完事了,还要看名字本身是否有助于别人理解它背后的意义。这里的名字包括,变量名,类名,方法名或者函数名。
最佳的命名是这样的:名字本身不能比它的含义大,也不能比它的含义小,要刚好包含它的含义,如果无法刚好包含,通常说明这个名字的意义太大,可能需要考虑拆分职责。
取名字往往需要仔细斟酌,要选择当前语境下最合适的词,比如:一个方法是取get,还是fetch,还是download呢?有时可能会实在找不出一个感觉很合适的词,职责划分也没啥问题,该怎么办呢?这时就需要和团队内的同事一起讨论,只要大家达成共识就行,即便大家选定的词仍无法准确表达背后的含义,以后团队内其它同事在阅读这个代码的也能迅速理解,毕竟大家曾经达成过共识,会留下印象。
程序代码的名字都是英文,我们中国人很多往往对英文的意思的细微差别难以分辨,但取好名字最重要的目的是让团队内的人看到的时候,能迅速理解,而不是给外国人去评估的,所以当你在写代码过程中,遇到起名字的困难时,请团队来讨论真的是个好方法,虽然团队的理解在外国人看来也不一定准确,但能让团队成员能比较容易的读懂你的代码。还记得可读性基本定理吗?当新人加入的时候,对于哪些看起来不那么准确的名字,可以鼓励新人在熟悉的代码的时候,说出自己的看法,新人也和大家一起达成共识,这也应该是融入团队文化的一部分。
注释的目的是尽量帮助读者了解得和作者一样多。
不过,不要为了注释而注释,当你准备加注释的时候,先问一个问题:
“我可以通过优化此处的代码,来让读者更明白这段代码的意思吗?比>如使用更合适的变量或者函数名,能做到吗?”
当你写代码的时候,需要留意如下应该写注释的情况:
- 加入有意义的评论,或者提示,让读者更清楚代码的背景,意图,成效等。比如:
// 出乎意料的是,对于这些数据用二叉树比哈希表快40%
再比如:
//TODO(dustin):处理除JPEG以外的图像格式
- 加入全局观的注释,或者总结性的注释
思考如下场景:有新人刚刚加入你的团队,她坐在你旁边,而你需要让她熟悉代码库。在你带领她浏览代码库的时候,你可能会指着某些文件或者某些类说这样的话:
“这段代码把我们的业务逻辑和数据库黏在一起了。任何应用层代码都不该直接使用它。”
“这个类看上去很复杂,但它实际上只是个巧妙的缓存。它对系统中的其它部分没有任何依赖。”
这样的一分钟的随意对话之后,你的新团队成员就知道的比她自己阅读源代码更多了。
而这正是应该写入注释中的信息。
- 克服“作者心理阻滞”
很多程序员不喜欢写注释,因为觉得会花很多时间。其实当你在写代码的时候,遇复杂问题时,把你的所思所想要精要的话写出来,就可以了,这些话往往正是读者在阅读的时候所需要的。
例如:
//小心:这段代码不会处理列表中的重复(因为这很难做到)
有时自己的所思所想有点混乱,尝试用精要的注释来整理你的思路是个好办法。
有时写出言简意赅的注释也很困难,也要像重构代码一样重视它们,重视它们就是重视你的同事。
顺便提一下代码美化相关的,代码美化也能辅助读者快速理解代码。有三条原则:
-
使用一致的布局,让读者很快就习惯这种风格。
-
让相似的代码看上去相似
-
把相关的代码行分组,形成代码块。
二. 简化循环和逻辑
把条件、循环以及其他对控制流的改变做得越“自然"越好,运用一种方式使读者不用停下来重读你的代码。
有几种方法可以让代码的控制流更易读。
在写一个比较时
> while (bytes_expected > bytes_received)
把改变的变量写在左边并且把更稳定的变量写在右边更好一些
> while (bytes_received < bytes_expected)
你也可以重排if/else
的语句中的语句块。通常来讲,先处理正确的/简单的/有趣的情况。有时这些准则会冲突,但是当不冲突时,应当遵守这些准则。
尽量避免嵌套的代码块。应该把它们改成更加线性的代码来避免深嵌套。
通常来讲提早返回可以减少嵌套并让代码整洁。
要把超长的表达式拆分成更加容易理解的小块。
减少不必要的变量。
减少每个变量的作用域,越小越好。
如果有些变量的值不会发生变化,最好明确指出。比如,加上const
,final
类似的修饰。
三. 重新组织你的代码
- 抽取出那些与程序主要目的“不相关的子问题”,单独成为一个函数。
- 使每个函数只做一件事,每个变量只关心一个唯一的意义。
- 先用自然语言描述代码,然后用这个描述来帮助你找到更整洁的解决方案。(通常你这时的描述,都可以作为注释)
这三条看似简单,实则需要训练,通常只要在写代码的过程中反复思考,回想这些建议,就会有意想不到的收获。好的的程序员往往一步三回头,也就是每写一部分代码的时候,他都会回头看看曾经的设计思路是否仍旧适合,是否需要调整,当下的代码逻辑是否足够清晰,是否需要重新整理,这些问题看似多,但当思考的多了,并以成为习惯,这些思考过程往往会缩短成直觉反应,直觉会告诉你该怎么做,你就会发现自己异常高效,因为写出的代码相当优美,大大节省后期维护时间。
少写代码,别费神实现你不需要的功能
通常我的经验是,不要做过早设计和实现,让你的设计最小化,只要你确信现在的设计能够完全胜任现在的需求,而且能在不重做的情况下满足未来新增需求,比如未来改动少量代码和新增一些代码,就可以了,没必要现在就为未来编码,因为未来太不确定,代码上做太多准备,可能会造成很大的浪费。
尽量保持代码的小巧,不要冗余代码;
删除没用的代码,即便将来50%的可能性会再有用,也不要手软。
熟悉你周边的库,不要重新发明轮子
站在今天对未来的预估,总是存在很大差距,可以先把这些暂时没用的代码放在另外的代码仓库里,需要用的时候再拿出来,不要让它成为你阅读代码和维护代码的障碍。
网友评论