前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >可读代码编写炸鸡四(下篇) - 提炼注释的下一步是提炼注释

可读代码编写炸鸡四(下篇) - 提炼注释的下一步是提炼注释

作者头像
syy
发布2020-05-18 13:40:53
2800
发布2020-05-18 13:40:53
举报
文章被收录于专栏:多选参数多选参数

大家好,我是多选参数的一员 —— 大炮。

上一篇炸鸡 中,我们大概了解了:

什么时候不该写注释,写注释可以怎么去写。

在上一篇结尾处,我们发现注释写出来后,是可以不断提炼的,所以注释存在一些优化方向和方法。

所以本篇炸鸡作为上一篇炸鸡的补充,提供一些这方面的建议。

这一篇与上一篇炸鸡统称为注释篇,而注释篇的行文思路如下图所示:

公众号后台回复 「注释」 获得源 pdf 文件

注释应该是怎么样的

在了解注释的优化方向前,我们需要了解一下注释应该是怎么样的。就好像你优化别人的代码,你就要提前画好图做好心理预期,告诉自己这段代码之后应该要是什么样的。

注释由于是占据屏幕空间的,所以太冗长的注释影响阅读,太短的注释又不能准确地提供信息

所以我们的一个小目标:

高的 (信息 / 空间) 率。也就是越小的空间输出越多的信息。

那么就需要注释:

  • 简练
  • 细致
  • 明确

如何优化

那我们现在已经了解了注释的小目标和应该的模样,那就可以冲着这几个点,提供几个方法。

为了简练

注释紧凑起来

如下代码的注释,就比较不紧凑。

代码语言:txt
复制
-- 这是一个匹配函数
-- 但是只能匹配同一服务器上的用户
-- 同时实现了不连续匹配相同对手的功能
function match(uid)
    ...
end

三行变一行,单车变摩托。

代码语言:txt
复制
-- 本服匹配,且用户不会连续匹配相同对手
function match(uid)
    ...
end

输入输出,永远的神

当然,有时候我们想表达一个功能,即使用简练的文字也不能很直观。

代码语言:txt
复制
-- 将数组转为值为数组元素,值为 true 的 hash 表。
function array2map(array)
    ...
end

如果我们使用输入输出的例子来描述函数功能:

代码语言:txt
复制
-- f({x, y, z, ...}) -> { [x] = true, [y] = true, [z] = true ... }
function array2map(array)
    ...
end

不过使用这个方法时,尽量选择 有普遍性 的例子,就好像如上的例子,若只有 f({x, y}) 这样的例子,容易产生 只允许两个元素的数组作为参数 的误导。

为了细致

声明代码的意图,而非仅是代码层面的意思

这个其实在 上一篇炸鸡 中已经提到了,我直接抄过来,不过分吧。

阅读者通过阅读代码能明白代码在 代码层面的功能,例如循环、查找指定字符等。但是不一定能很快了解这些代码 背后的意图,也就是 高级别的抽象

如下代码所示,代码层面的含义是 打乱 citys 数组,然后再循环这个数组,其中的元素不等于 lastCityId 则进入逻辑

代码语言:txt
复制
local cityIds = random.randomArray(citys)
for _, cityId in ipairs(cityIds) do
    if cityId ~= lastCityId then
        ...
    end
end

但更高级别的抽象其实就是 从已知 citys 中随机选择一个与上次选择不一样的 cityId

所以利用注释只解释代码层面,往往是不够的。当阅读者了解代码层面的功能时,不一定能确认这段代码它的原作者意图到底是什么。

如果多了意图的解释,阅读者其实也能通过阅读来判断这段代码是否事与愿违,这其实也为代码多了一层 检查

润色粗糙用句

为了赶快,很可能就很潦草地写了一个注释。

代码语言:txt
复制
-- 找一个合适元素

这个合适,什么算合适?怎么找?都没说。

我们可以润色且增加些信息:

代码语言:txt
复制
-- 将 xxx 快排,找到最接近传参大小的 xxx 中的元素

精确描述函数行为

其实上一小点已经有了这一小点的味道了。我再举一个书中的例子:

代码语言:txt
复制
-- 统计文件行数
function countLines(string)
end

这个统计行数看似讲明白了,但是有些细节没讲:

一行的定义是 \n 结尾的字符串?

还是 \r\n 结尾的字符串?

所以把这个细节考虑在内,就更精确了。

代码语言:txt
复制
-- 利用 \n 统计统计行数
function countLines(string) 
end

命名参数式注释

我们知道,python 是有命名参数的,这样可以为阅读者提供参数的一部分信息:

代码语言:txt
复制
def xxx(first_param, sec_param):
    passs

xxx(sec_param = 2, first_param = 1)

但有些语言并不支持这么做,例如我经常使用的 lua 语言。所以我们可以参考这种方式,在函数调用时这么写:

代码语言:txt
复制
Hero.new(--[[configId = ]] 1, --[[heroId = ]] 2)

这样会更加细致。但是小心一点的是,尽量不要用在 可能高频修改的接口上,不然当接口修改,改个注释都要改半天。

这点我就被我的主程锤过。

为了明确

避免用代词

在书中提到了慎用 itthat 这样的代词。因为当主语变成两个,你可能不知道说的是谁:

代码语言:txt
复制
-- insert the data into the cache, but check if it is too big

翻译一下的话:

代码语言:txt
复制
-- 将数据写入缓存,但检查一下它是否数据过大。

所以到底是数据还是缓存会被检查呢。

记得维护同步

我记得听过一句名言

程序员最讨厌两件事,写文档和代码没有文档。

这对于注释来说也是一样的。

但是既然我们愿意写入注释了,当注释的相关代码出现变动,也要一并修改。

不然你的注释在第一层,你的代码已经在第五层,阅读者可能就在地下一层不知所措。

久而久之,很有可能导致你的团队里头的人直接忽略注释,他们开始害怕被注释误导。

这便事与愿违了。

总结

本篇炸鸡主要讲述了注释的优化方向

  • 越少空间提供越多信息
  • 简练、明确、细致

同时为了靠上这些要求,也提供了一些例子作为参考。

作为上一篇炸鸡的补充,本篇炸鸡就结束了。

写在最后,写给后头

可读代码编写炸鸡的第一层优化也告一段落了。

什么是第一层?我只在第一层,你已经第五层了对吧。

其实这段时间的炸鸡,都在于 命名、审美、注释 这些很表层的优化,而代码是逻辑的构成体,只是优化一些词句是很有限的。

所以在接下来的炸鸡,会开始着眼于代码逻辑上的优化,例如 if/else/elseiffor/while 等控制流的简化。

在最后还是感谢大家的阅读与支持

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-05-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 多选参数 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 注释应该是怎么样的
  • 如何优化
    • 为了简练
      • 注释紧凑起来
      • 输入输出,永远的神
    • 为了细致
      • 声明代码的意图,而非仅是代码层面的意思
      • 润色粗糙用句
      • 精确描述函数行为
      • 命名参数式注释
    • 为了明确
      • 避免用代词
  • 记得维护同步
  • 总结
  • 写在最后,写给后头
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档