当前位置: 首页 > article >正文

为什么不写注释?写“为什么不”注释?

在这里插入图片描述

原文:Hillel - 2024.09.10

代码是用结构化的机器语言编写的,而注释是用富有表现力的人类语言编写的。人类语言让注释比代码更具表达性和沟通能力。代码中也包含少量类似于人类语言的内容,例如标识符。所谓“注释要写为什么,而不是写做了什么”,意思是尽可能将信息嵌入到标识符中。并非所有“做了什么”都能这样嵌入,但很多都可以。

近年来,我看到越来越多的人主张,连“为什么”也不应该出现在注释中,它们可以通过LongFunctionNames(长函数名)或测试用例的名称体现出来。几乎所有“自解释”代码库都通过增加标识符来进行文档化。

那么,有哪些人类表达的内容是无法通过更多代码来呈现的呢?

反面信息,也就是引起注意系统中“没有的”东西。“为什么不”的问题。

一个近期的例子

这是一个来自《Logic for Programmers》的例子。由于技术上的复杂原因,epub 电子书构建过程中未能将数学符号(\forall)正确转换为符号()。我写了一个脚本,手动遍历并将数学字符串中的标记替换为对应的 Unicode 等价符号。最简单的方法是对每个需要替换的 16 个数学符号依次调用string = string.replace(old, new)(一些数学字符串包含多个符号)。

这种方法效率非常低,我可以将所有 16 个替换在一次遍历中完成。但那将是一个更复杂的解决方案。因此,我选择了简单的方法,并加了一条注释:

对每个字符串进行了 16 次遍历。
整本书中只有 25 个数学字符串,大多数字符少于 5 个。
因此,速度仍然足够快。

你可以把这看作是“为什么我用了慢的代码”的解释,但也可以理解为“为什么不用快的代码”。它引起了对“没有的东西”的关注。

为什么要有注释

如果慢速代码没有造成任何问题,为什么还要写注释呢?

首先,这段代码可能以后会成为问题。如果将来的《Logic for Programmers》版本中有上百个数学字符串,而不是几十个,这个构建步骤将成为整个构建过程的瓶颈。现在留下标注,方便将来知道该修复什么。

即使这段代码永远不会有问题,注释仍然很重要:它表明我意识到了权衡。假设两年后我回到这个项目,打开epub_math_fixer.py,看到我这段糟糕的慢代码。我会问自己:“当时为什么写了这么糟糕的代码?” 是因为缺乏经验,时间紧迫,还是纯粹的随机失误?

这条反面注释告诉我,我知道这段代码很慢,考虑过替代方案,并决定不做优化。这样,我不必花大量时间重新调查,却得出同样的结论。

为什么这不能通过代码“自解释”(self-documented)

当我第一次尝试这个想法时,有人告诉我,我的反面注释没有必要,只需将函数命名为RunFewerTimesSlowerAndSimplerAlgorithmAfterConsideringTradeOffs。除了名字过长、未解释权衡点,并且如果我优化了代码,还得在所有地方修改函数名外……这实际上使代码更不能自解释。因为它没有告诉你函数实际做了什么

核心问题在于,函数和变量的标识符只能包含一条信息。我无法在一个标识符中同时存储“函数做了什么”和“它作出了什么权衡”。

那么用测试代替注释呢?我猜你可以写一个测试,用grep查找书中的数学块,并在超过 80 个时失败?但这并没有直接测试EpubMathFixer。函数本身没有任何内容可以让你直接关联上。

这是“自解释”反面信息的根本问题。“自解释”是伴随代码书写的,它描述了代码在做什么。而反面信息是关于代码没有做什么的。

最后的思考

我在想,是否可以将“为什么不”注释视为反事实的一个例子。如果是这样,那么“人类沟通的抽象”是否一般都无法“自解释”?你能“自解释”一个比喻吗?不确定性呢?伦理主张呢?


http://www.kler.cn/a/301201.html

相关文章:

  • SD模型微调之Textual Inversion和Embedding fine-tuning
  • 【后端】版本控制
  • CC工具箱使用指南:【CAD导出界址点Excel】
  • 3、C语言基本数据类型关键字
  • 【大语言模型】ACL2024论文-16 基于地图制图的罗马尼亚自然语言推理语料库的新型课程学习方法
  • HBase 开发:使用Java操作HBase
  • pdf删除一页怎么删除?5种方法详细讲解,pdf删除页面实用技巧分享!
  • 【iOS】push和present的区别
  • echarts 多个3D柱状图
  • Python爱心射线(完整代码)
  • git一个项目关联多个远程仓库
  • android 权限说明
  • Parasoft如何助力AUTOSAR C++合规测试
  • 力扣322-零钱兑换(Java详细题解)
  • 开源网安斩获CCIA中国网络安全创新创业大赛总决赛三等奖
  • iOS 18 RC 版本更新,为相机应用引入了“暂停录制视频”功能
  • 滑动窗口——优选算法
  • MySQL主从同步延时高问题排查
  • 省市县相关校验sql随笔
  • 建筑物检测系统源码分享
  • linux内核驱动:ptp内核phc框架
  • rman compress
  • starrocks结合同步和异步物化视图建立数据湖和数据仓库
  • java的ReentrantLock原理
  • ARM32开发——DMA内存到内存
  • CSS实现前端布局更巧妙的方案!在 flex 布局中通过使用 margin 实现水平垂直居中以及其他常见的前端布局