art-of-comment
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseOverview
概述
Every comment should earn its place. A good comment provides context the code alone cannot convey — why a decision was made, what trade-off was accepted, or how a non-obvious piece fits the bigger picture. A comment that merely restates the code is noise; remove or avoid it. When in doubt, prefer no comment over a redundant one.
每条注释都应当有其存在的价值。好的注释能够提供代码本身无法传递的上下文——为什么做出某个决策、接受了何种权衡,或者某个非直观的代码片段在整体架构中的作用。仅仅复述代码内容的注释属于冗余信息,应当删除或避免编写。如果拿不准,宁愿不写注释也不要写多余的注释。
Guidelines
指南
- Comment only when needed. Do not add comments or JSDoc unless the code is non-obvious or you are explicitly asked. Self-explanatory code needs no narration.
- Inline comments: ≤ 2 lines. Keep them terse — explain why, not what.
- JSDoc: comprehensive yet concise. Document only what adds value: purpose, non-obvious parameters, return semantics, or usage examples. Omit what the signature already communicates.
- Use for reusable symbols. Functions, types, and constants referenced elsewhere should use JSDoc so IDE hover tooltips display the information.
/** ... */ - Document trade-offs. When the implementation accepts a trade-off, explain the rationale and why it was worth taking.
- No assumptions. Ground comments in library docs, project standards, or best practices — not guesses. Ask for clarification when unsure.
- Stay consistent; never contradict. Match the tone and terminology of existing comments. Do not duplicate information already stated in a nearby comment — reference it instead.
- 仅在必要时添加注释。 除非代码逻辑不直观或者有明确要求,否则不要添加注释或JSDoc。自解释的代码不需要额外说明。
- 行内注释:≤ 2行。 保持简洁——解释为什么这么做,而非做了什么。
- JSDoc:全面且简洁。 仅记录有价值的内容:用途、非直观的参数、返回值语义或者使用示例。省略函数签名已经能表达的信息。
- 可复用符号使用格式注释。 其他地方会引用的函数、类型、常量应当使用JSDoc,这样IDE的悬浮提示会展示相关信息。
/** ... */ - 记录权衡取舍。 如果实现方案接受了某种权衡,要解释背后的逻辑以及这么做的合理性。
- 不要主观臆断。 注释内容要基于库文档、项目规范或最佳实践,而非猜测。不确定时请询问确认。
- 保持一致,切勿矛盾。 与现有注释的语气和术语保持统一。不要重复邻近注释已经说明的内容,可引用对应的注释。
Example
示例
The annotated snippet below highlights common comment pitfalls alongside good practice.
typescript
// (1) Calculate chart segments based on priority: verified > registered > rejected
const getChartSegments = (): {
value: number
color: string
backgroundColor?: string
badgeLabel?: string
}[] => {
const verified = data?.verified ?? 0
const registered = data?.registered ?? 0
const rejected = data?.rejected ?? 0
const total = verified + registered + rejected
// (2) If all values are 0, show full gray circle
if (total === 0) {
return [{ value: 1, color: colors.palette.lightGray }]
}
// (3) Filter out zero values to prevent empty segments
const segments = []
// (4) Priority order: verified > registered > rejected
if (verified > 0) {
segments.push({
value: verified,
color: '#01C58A',
backgroundColor: '#D6F6EC',
badgeLabel: `${verified} Aset Terdata`,
})
}
if (registered > 0) {
segments.push({
value: registered,
color: '#FF9E00',
backgroundColor: '#FFF1DB',
badgeLabel: `${registered} Belum Diverif`,
})
}
if (rejected > 0) {
segments.push({
value: rejected <= 2 ? 2 : rejected, // (5) Minimum visible segment size of 2
color: '#FF5264',
backgroundColor: '#FFECEC',
badgeLabel: `${rejected} Ditolak`,
})
}| # | Verdict | Why |
|---|---|---|
| 1 | Good intent, wrong syntax. Clearly summarizes purpose and priority order — but should use | |
| 2 | Remove. The condition and return value are self-explanatory; the comment adds nothing. | |
| 3 | Borderline. States the obvious, but may be acceptable as a signpost when debugging segment logic — acceptable only if it conveys intent the code cannot. | |
| 4 | Remove — duplicates (1). The priority order is already documented above; repeating it creates a maintenance burden. Reference the earlier comment if needed. | |
| 5 | Good. Concisely explains a non-obvious workaround and its effect. |
下方带标注的代码片段展示了常见的注释误区以及最佳实践。
typescript
// (1) Calculate chart segments based on priority: verified > registered > rejected
const getChartSegments = (): {
value: number
color: string
backgroundColor?: string
badgeLabel?: string
}[] => {
const verified = data?.verified ?? 0
const registered = data?.registered ?? 0
const rejected = data?.rejected ?? 0
const total = verified + registered + rejected
// (2) If all values are 0, show full gray circle
if (total === 0) {
return [{ value: 1, color: colors.palette.lightGray }]
}
// (3) Filter out zero values to prevent empty segments
const segments = []
// (4) Priority order: verified > registered > rejected
if (verified > 0) {
segments.push({
value: verified,
color: '#01C58A',
backgroundColor: '#D6F6EC',
badgeLabel: `${verified} Aset Terdata`,
})
}
if (registered > 0) {
segments.push({
value: registered,
color: '#FF9E00',
backgroundColor: '#FFF1DB',
badgeLabel: `${registered} Belum Diverif`,
})
}
if (rejected > 0) {
segments.push({
value: rejected <= 2 ? 2 : rejected, // (5) Minimum visible segment size of 2
color: '#FF5264',
backgroundColor: '#FFECEC',
badgeLabel: `${rejected} Ditolak`,
})
}| # | 判定 | 原因 |
|---|---|---|
| 1 | 初衷很好,但语法错误。 清晰概括了函数用途和优先级顺序,但应当使用 | |
| 2 | 建议删除。 条件判断和返回值都是自解释的,该注释没有提供额外价值。 | |
| 3 | 可留可删。 描述的是显而易见的内容,但如果作为调试分段逻辑的标识是可以接受的——仅当它能传递代码无法表达的意图时保留。 | |
| 4 | 建议删除——与(1)重复。 优先级顺序已经在上方说明,重复会增加维护成本。如有需要可引用前面的注释。 | |
| 5 | 优秀。 简洁地解释了一个非直观的兼容处理及其作用。 |