编写分析器评论


本文档介绍如何编写分析器生成的注释,并给出相关指南。

内容

分析器注释的内容以 Markdown 文档的形式存储在 exercism/website-copy 代码仓库中。 每条注释都包含一个指针字符串,格式为<track-slug>.<exercise-slug>.<comment-slug>,它指向website-copy代码仓库中的某个具体 Markdown 文档。

例如,ruby.two-fer.string-interpolation 指向 https://github.com/exercism/website-copy/blob/main/analyzer-comments/ruby/two-fer/string_interpolation.md。

Note

如果一条注释只针对某种语言、而_不_针对具体练习,就把<exercise-slug>替换为general。 例如ruby.general.string-explicit_return

措辞

  • 避免注释啰嗦冗长。保持简洁。
  • 保持中立地陈述,避免带有情绪或一概而论的表述。
  • 明确给出建议。
  • 尽可能先给出建议,再作解释。
  • 避免使用“me”“I”“we”等,因为机器人不是人。
  • 避免使用“you”和“your code”,因为这样有时会显得是在评判人,而不是评判代码。
  • 避免使用“just”“simply”“obviously”这类词,它们会显得居高临下:如果这条注释有必要,那就说明它显然并_不_显而易见。
  • 不要假设人们知道什么、不知道什么。唯一的例外是已经完成的_核心_练习中的知识。避免使用“as you know”“as you remember”“as you learned”“now that we all understand x”这类说法,因为即便讲过,对方也不一定就理解了。

指导

  • 追求流利,而不是精通:Exercism 上语言轨道的目标,是让人以很低的精通程度,达到高水平的流利。 我们追求的是语法、惯用法和语言标准库方面的流利。
  • 尽可能建议地道的代码,这里的地道指的是几乎所有用该语言写代码的开发者(而非业余爱好者)都会写出的代码。 如果给出的建议并不地道,要说明这一点,并解释这条建议为什么仍然可能有用。
  • 指出差异:说清楚对方现在的做法与该语言中“地道”的写法有什么不同。
  • 使用恰当的术语和命名,这样人们能在别处认出这些概念,也能自己去查阅。
  • 不要直接给出解答,这是 Exercism 所有指导工作的通用建议。 当人们自己发现答案时,学习才会真正扎根。那是一种极其令人兴奋的体验,情绪上的冲击会让它印象深刻。 不过,如果这种发现没有带来多巴胺的冲击,那么直接展示它长什么样就完全说得通。 例如,对一份已通过的解答提一点小改进,远不如给一份未通过的解答指出一个学习要点更让人兴奋,因此后者可能更适合给出示例,而不是只放一个链接。
  • 按重要性排列注释,第一条最重要,最后一条最不重要。
  • 控制注释的数量,让它们便于处理。 每次迭代以一到三条注释为宜。
  • 在同一次分析中不要重复添加同一条注释。 同一条注释附带不同参数,_不_算作重复。
  • 如果格式或代码检查是这门语言不可或缺的一部分,可以考虑只针对格式给出注释。 尽可能引导学生使用自动格式化工具,或者链接到官方风格指南。

最初的几个练习

对于一条轨道最初的那几个练习,下面几点_格外_重要:

  • 保持相对简短,不要写成一大段文字,也不要用大量建议把人淹没。如果他们在第一个练习里有很好的体验,就会继续回来,你也会有更多机会针对自己注意到的所有问题给出反馈。
  • 不要把某个概念讲得太细:不要深入讲编译器之类的底层机制。这里更重要的是,这是语言轨道最初的练习之一,在这个阶段,反馈越简短、越直接,帮助越大。
  • 给出一个链接,用教程的方式准确演示这个概念该怎么做。也就是说:展示怎么做,而不是讨论为什么。这可能意味着这门语言的官方文档并不够用,因为官方文档往往只是代码参考,不会告诉你如何使用它、它如何运作。不过,链接只应作为更深入探索时使用。对方应当能直接从你的回答里明白你的意思,而不必点开链接。

示例

在 JavaScript 中,一名学员用let写了一个顶层常量。

<!-- not following these guidelines -->

As you know, everyone uses const, you shouldn't use let or var.

这条注释没有遵循上述指南,原因如下:

  • 建议的行动排在“解释”之后。
  • “As you know”:我们并不知道学员是否真的知道。
  • “you shouldn't”:要表达这个意思,并不需要“you”。
  • “everyone uses const”:这并不属实,_而且_会让学员觉得自己犯了天大的错。
  • 没有真正解释这个建议_为什么_要这么给。
<!-- better -->

Prefer `const` and `let` over `var`. The `const` declaration stops a variable
from being accidentally reassigned, which provides safety, and reduces
cognitive load for someone reading the code. [This article](https://medium.com/javascript-scene/javascript-es6-var-let-or-const-ba58b8dcde75)
explains the difference between the three.

在 Go 中,一名学员没有使用内置错误,而是创建了一个自定义错误:

<!-- not following these guidelines -->

I see you are creating a custom `error`. This is perfectly fine! If you did not
know about `errors.New` and `fmt.Errorf` have a look at them as they are much
simpler ways to create an error. Custom errors are helpful if you want to check
if an error is of a certain type later.

这条注释没有遵循上述指南,原因如下:

  • “I see”:分析器不是人,所以要避免用“I”。
  • “This is perfectly fine!”:看来事实并非如此,不然这句安慰话就没必要了。这整句话大概都可以删掉;如果你想就某个已有做法给一句通用提示,可以直接这么说:“An alternative, equally valid way of doing x is y.”
  • “If you did not know about”:这个过于啰嗦的词组应当删去。
<!-- better -->

A custom `error` is typically used to provide custom behavior, or to distinguish
on type later. For simpler cases, it's more common to rely on `errors.New` or
`fmt.Errorf`. This [in-depth article](https://golangbot.com/custom-errors/) about
custom errors might be interesting.

持续集成(CI)

由于注释与分析器不在同一个代码仓库中,每个分析器都应当有 CI,用来检查该分析器用到的注释(也就是可能成为输出的那些注释)是否为 exercism/website-copy代码仓库main分支上的注释。

在撰写本文时,这个 issue 跟踪着这套 CI 通用化的进展情况(如果有的话)。