文章摘要
文章认为在AI时代应重新审视"文学化编程"理念,即代码与解释性文字混合编写的方式。虽然该理念有助于理解代码,但实践中维护双重叙述(代码和文字)较为繁琐,导致普及受限。目前主要在数据科学的Jupyter笔记本和少数技术爱好者中使用。作者虽热衷此模式,但也承认其存在操作繁琐的问题。
文章总结
重写后的文章:
标题:在智能体时代,我们应当重新审视文学化编程
文学化编程是一种将代码与叙述性文字交织在一起的编程理念,旨在让不熟悉代码的读者能够通过阅读代码库的叙述性内容,理解其工作原理和功能。
尽管这一理念令人着迷,并在某些特定场景中得到应用,但在实践中,维护代码和叙述文字两套平行内容往往成为负担,这也限制了其普及。历史上,文学化编程最常见于数据科学领域的Jupyter笔记本中,其中解释性文字与计算过程和结果并存于网页浏览器中。
Emacs Org模式通过org-babel包支持多语言文学化编程,允许执行任意语言并将结果捕获回文档中,但这仍然是小众的技术爱好者使用的模式。即使对于像我这样热衷于这种模式的人来说,将Org作为大型软件项目的唯一来源也会变得繁琐,因为源代码实际上变成了编译输出,每次编辑Org文件后,代码都必须重新提取并放置到目标位置(在Org模式中称为"tangling")。虽然可以自动化这一过程,但很容易出现令人烦恼的情况,比如你或你的智能体编辑了实际源代码,而在下一次tangling时被覆盖。
然而,在个人配置管理方面,文学化编程取得了一定成功,即使在大型语言模型(LLM)出现之前,我也未能完全放弃这一理念。例如,在编码智能体出现之前,我采用了一种使用Org模式进行手动测试和记录笔记的模式:不是在命令行中操作,而是在编辑器中编写命令并执行,逐步编辑直到每个步骤正确完成,从而在结束时获得一个准确记录所有步骤的文档。将创建笔记和运行测试结合起来,可以在测试完成时免费获得笔记。
现在有了编码智能体,这一方法更加令人兴奋。Claude、Kimi等智能体对Org模式语法有很好的掌握,这是一种宽容的标记语言,智能体非常擅长处理。所有文档都可以在线获取,并且可能在训练数据中。虽然Org模式的一个大缺点是其复杂的语法,但这对于语言模型来说完全不是问题。
现在,当我想测试一个功能时,我会让智能体在Org中编写一个运行手册。然后我可以审查它——叙述文字解释每个步骤的意图,而代码块在审查后可以交互式执行,可以一次执行一个或整个文件像脚本一样。结果会像Jupyter笔记本一样存储在文档中代码块的下方。
我可以编辑叙述文字并让模型更新代码,或者编辑代码并让模型反映到文字上。也可以让智能体同时更改两者。维护两套平行系统的问题消失了。
智能体负责处理tangling,提取问题也随之解决。可以通过AGENTS.md文件指示智能体将Org模式文件视为唯一来源,始终用文字解释正在发生的事情,并在执行前进行tangling。智能体非常擅长所有这些事情,并且永远不会因为代码的小调整而厌倦重新用文字解释。
文学化编程的基本额外劳动——我认为这是它没有被广泛实践的原因——被智能体消除了,并且它利用了大型语言模型最擅长的能力:翻译和总结。
作为额外好处,代码库现在可以导出为多种格式以便阅读。如果工程师的主要角色从编写转向阅读,这一点尤其重要。
虽然没有数据支持,但我怀疑文学化编程会提高生成代码的质量,因为解释每个代码块意图的文字会与代码本身一起出现在上下文中。
我还没有机会在更大、更严肃的代码库上尝试这种模式。到目前为止,我只在测试和记录手动流程的工作流中使用它,但对其应用感到兴奋。
我也认识到Org格式因其与Emacs的紧密集成而成为限制因素。然而,我一直认为Org应该脱离Emacs。我会推荐像Markdown这样的替代品,但Markdown缺乏包含元数据的能力。但就像我关于Emacs的其他文章一样,让我兴奋的不是Emacs对理念的具体实现(在这个例子中是Org对文学化编程的实现),而是理念本身。
有了智能体,是否可以实现大型代码库像叙述一样可读,其文字内容由不知疲倦的机器与代码变更保持同步?
我认为这是一个引人深思的问题。
评论总结
以下是评论内容的总结,涵盖主要观点和论据:
反对"文学化编程"的观点
- 认为代码本身应足够清晰,过多的注释反而会误导(sublinear)
"Literate programming failed to take off because with that much prose it inevitably misrepresents the actual code"
"You can't 'test' comments. The author doesn't even need to know why the code works to write comments" - 自然语言具有歧义性,编程语言才是精确的(palata)
"Natural languages are ambiguous. That's the reason why we created programming languages"
- 认为代码本身应足够清晰,过多的注释反而会误导(sublinear)
支持适度文档化的观点
- 建议采用轻量级文档:清晰的命名、类型签名和关键注释(perrygeo)
"Good names, docstrings, type signatures, strategic comments re: 'why' are enough" - 模块级文档和公共API文档对LLM特别有效(rednafi)
"My version is ensuring each package has top-level docs and public APIs have good docstrings"
- 建议采用轻量级文档:清晰的命名、类型签名和关键注释(perrygeo)
工具化解决方案
- 建议用LLM自动检测文档与代码的同步问题(cfiggers)
"Use LLMs to flag when comments/docs have come out of sync with the code" - 推荐Rakudoc等嵌入式文档工具(librasteve)
"Rakudoc is useful for literate programming and for LLM inversion of control"
- 建议用LLM自动检测文档与代码的同步问题(cfiggers)
测试驱动的方法
- 提倡测试代码与生产代码对称(cadamsdotcom)
"Test code and production code in symmetrical pair has lots of benefits like double entry accounting" - 示例代码作为可执行的文档(akater)
"The examples are written as tests while implementing a function... always in sync with the code"
- 提倡测试代码与生产代码对称(cadamsdotcom)
LLM时代的新实践
- 观察到人们更愿意为LLM而非人类编写文档(rustybolt)
"When done to help an LLM instead of a human, people suddenly seem more motivated" - 提示词(prompt)本身就是高级代码(ajkjk)
"LLM prompts are code -- text that gets 'compiled' into actual code"
- 观察到人们更愿意为LLM而非人类编写文档(rustybolt)
极端立场
- 主张完全形式化规范(pjmlp)
"I rather go with formal specifications, and proofs" - 认为优秀代码不需要文档(nailer)
"Have you tried naming things properly? Then code reads as narrative"
- 主张完全形式化规范(pjmlp)
关键分歧点在于文档的适度性:支持者认为文档(尤其是对LLM友好的文档)能提升可维护性,反对者则认为代码自解释性更重要。值得注意的是,多位评论者提到Jupyter Notebooks和测试用例作为平衡方案。