浅谈LP
目录
1. [源码与文档](#1)
1.1 [只编码,不写文档](#1.1)
1.2 [分离的源码和文档](#1.2)
1.3 [源码中插入文档](#1.3)
1.4 [文档中插入源码](#1.3)
2. [文学编程](#2)
2.1 [文学编程的好处](#2.1)
2.2 [常用文学编程工具](#2.2)
3. [参考资料](#3)
LP(Literate Programming),即文学编程。它的想法是,构造程序时,我们应该用文学的语言解释代码给人看为主要目的,而不是单单编码给计算机运行。
在开始正式介绍LP前,我们先谈谈程序员中永恒的话题,编码与文档的关系。
1. 源码与文档
程序员对这的态度或行为,大概可以概括为以下几类:
- 只编码,不写文档
- 分离的源码和文档
- 源码中插入文档
- 文档中插入源码
这里的文档泛指用来阐释源码的文字,它可能是个独立的文件,也可能是源码中的注释等等。好的文档,能帮助开发者快速地读懂源码也有利于将来的维护。
1.1 只编码,不写文档
这类程序员往往以Linus说过的 "Read The F*cking Source Code" 为宗旨(可以称为RTFSC党)。RTFSC党会认为自己写的代码清晰明了、通俗易懂、老少皆宜,完全没有必要再编写文档、注释等等。他们可能会说,我函数名起得这么好、我链式语法写得这么棒、我用promise写异步、我amb求值器设计得这么好,这样的代码你都看不懂?还要我写文档?要你何用?
虽然大多数程序员都自认为自己的源码写得巧夺天工,但是在别的程序员眼里,往往是又臭又长的存在。当一个程序员看到一段复杂的逻辑而没有一个文档说明,往往杀人的心都有了。甚至,开发者在数月后看自已以前写的代码,如果没有文档,可能自己都看懵逼了。
下面是摘自 14th国际c语言混乱大赛的代码。只要你愿意,理论上可以把任何代码写成飞机。
1.2 分离的源码和文档
这类程序员应该是比较常见的。不管主观愿不愿意,他们除了输出源码文件,还会输出对应的文档文件。要编写文档了,程序员们会创建独立的word文档,或者更有追求的可能会选择创建MarkDown、reST、AsciiDoc、DocBook、OrgMode等标记文档。
编写文档有可能在编写源码前,也有可能在编写源码后。他们可能在编写源码前,编写好相关的独立的设计文档,再按设计文档来开发代码。也可能在编写源码后,补充文档,用来日后交接工作等。
文档完成后,与源码文件往往是分开存储的,存不同的目录。在版本管理上,往往会创建不同于源码的文档工程,用来专门保存文档。
1.3 源码中插入文档
相比RTFSC,他们往往会在代码中加入大段的注释。函数、类都有规范的写注释方式。往往还有配套工具,支持从源码中抽出这些注释,再生成独立的文档。比如,doxygen、javadoc、appledoc、swagger-ui等。
这方面做到极致的是,我觉得是swagger-ui。它主要是给后台生成在线接口文档的。通过在java代码中,插入一些格式化的注释,它会生成接口的静态网页文档,并启动web服务加载。而且,你除了看在线接口文档外,你还可以在线填写参数测试接口,它会用curl进行接口请求,并显示结果,简直不要太爽。大家感兴趣可以去看看swagger-ui的demo。
有些程序员还不满足于在源码中插入普通的文本注释,还想在源码中插入流程图、交互图等。但是,源码作为纯文本文件又不能插入图片,于是只能插入ascii art文本图。如果,你给你的复杂源码中插入类似如下这么个流程图,看代码的人肯定会感动得痛哭流涕。
网上有在线生成ascii art的网站asciiflow。Emacs里也有 AsciiMode、figlet、picture等mode可以画ascii art图。
1.4 文档中插入源码
最后一种,是在文档中插入源码。它与上一种在源码中插入文档相同的是,它们的文档和源码都是放在一起的。不同的是,它强调编程应该面向人,应该以提供解释说明为主,而不是为了写出计算机可以识别的程序。
这就是文学编程的思想,即更主要目的是文学,而不是编程。
因为是主要是面向文档的,所以这里的文档可以比代码中插入的注释丰富很多。不少文学编程工具,往往提供统一显示文档和代码块的界面。比如,学习python的可能都接触过的jupyter notebook。
jupyter中可以用markdown来插入图片、链接跳转、数学公式等。同时,其中的代码块也能直接运行,并在文档中插入运行结果(如画图、表格等)。
还有其他工具环境,类似swift playgrouds
、org-mode
也提供了文学编程的能力。特别是org-mode
甚至可以在一个文档里插入多种不同语言的代码块,所以在它里面,你可以用你擅长的不同语言来处理不同的事情。
2. 文学编程
Let us change our traditional attitude to the construction of programs: Instead of imagining that our main task is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do.
(Knuth 1984)
IT界大佬Knuth
认为,构造程序时,我们更多地应该从写作的角度出发,用文学的语言解释代码给人看为主要目的,而不是以编码给计算机运行为目的。
注: 还有个RR (Reproducible research),可重复性研究,与LP有些相似的概念,可以在文末的参考资料中查看二者的区别。
文学编程,从写作、文学的角度出发,代码只是以代码块的方式插入到文档中。随后,文学编程工具一般还提供Tangle功能,可以从整个文档中抽出全部代码,也提供Weave功能,可以把文档导出成html、pdf等更通用的文档格式。
以org-mode
为例:
org-mode
是类似markdown的格式化文本。文档中可以插入图片、表格等元素,并且可以插入 #+begin_src
和 #+end_src
围起来的代码块。org-mode
中的代码块可以是任何语言,在org-mode
里面执行后可以把输出(图片、表格、raw)等插回文档。它也提供 Tangle 和 Weave功能,对org-mode
文档进行代码提取或格式导出。
2.1 文学编程的好处
文学编程把描述和代码块放一起,并且代码块可以运行,它提供了以下好处:
- 科学计算等场景,随时要验证理论是否正确,如果把理论文档和代码块放一起,可以随时验证理论是否正确。
- 软件开发场景,丰富的文档和代码放一起,更能理解代码实现,也利于以后维护、扩展。
- 教学场景,往往需要一步步、手把手地写代码(hand in hand)。一个步骤一个解释配一个代码块的方式,学员更容易理解,而且可以自己动手运行代码块尝试。
2.2 常见的文学编程工具
下面介绍文学编程的一些比较流行的工具/环境:
Jupyter notebook
首先介绍 jupyter notebook。
近年来,随着机器学习
的迅猛发民,越来越多的人用jupyter notebook
来做数据分析、课题研究、教学等,大有取代matlib
、R
之势。因为它是以文档为目的的,所以最后可以直接生成报告、演示文档等,非常酷。
Jupyter notebook
有以下几个很酷的地方:
-
支持超过40种编程语言,包括Python, R, Julia 和 Scala。它有各种内核如ipython、iswift等。
-
会起jupyter server,然后用web浏览器进行开发。所以注定,它可以很方便地进行分享。别人也可以简单地用web远程连接到你的jupyter server上,就可以开发了。
-
跟大部分文学编程工具一样,代码块可以产生丰富的内容,如网页、图片、视频等,再插入到文档中显示。
-
最后,jupyter抽代码和导出文档功能也很齐全。
基于b/s设计,也注定了客户端不需要关注开发环境,只需要一个浏览器就够了,更方便重现研究、分享。
你可以用连接官网的 Try Jupyter 进行jupyter试用。自己安装的话,建议安装
conda
全家桶。
jupyter notebook
中把文档按cell进行组织。cell可以是文档类型,也可以是code类型。
- 文档类型的cell,走markdown语法。用markdown语法,基本可以写出很丰富多彩的内容了。
- code部分的cell,和内核相关。如内核用的ipython,那么code部分就当python来解析了。
jupyter notebook
的代码块部分那么强大,能输出各种格式,这完全依赖于强大的内核功能,如依赖于强大的ipython,它可以输出丰富的网页格式。
Swift Playgrounds
学习Swift语法的同学,基本应该都是在Swift Playgrounds
中学习。Swift Playgrounds
提供一个swift的非常酷的交互环境,在教学等场景下非常高效。
可以参照 Swift Playgrounds — Interactive Awesomeness 这边的入门介绍。
我们可以通过Playing with SpriteKit in a Swift Playground 这个例子来一窥它强大的交互。
从这个图中可以看出,
- 它通过markdown展示了如何生成Rainbows的思路。
- 每行代码在右边生成了当前代码行代码的输出,有点像REPL的交互。
- 最右边的Assist中的Live View,展示了SpriteKit的运行效果(实际运行时,彩虹会动,同时会有音乐播放)。
- 最下面的console会输出打印(这个示例中没有打印输出)。
可以说交互很无敌了,非常酷。
注: 不过苹果推出的SpriteKit这个游戏库貌似实际开发中没什么人用。
Org-Mode
最后压轴出场的是Org-Mode。它是Emacs这个神器中用来写文档的一个major mode
。Org-Mode可以用来写GTD、组织文档、文学编程等。
Org-Mode
常见介绍和简单用法可以参考神器中的神器org-mode之入门篇
Org-Mode中使用文学编程的介绍,可以参考A Multi-Language Computing Environment for Literate Programming and Reproducible Research。
Org-Mode中负责处理代码块的是Org-Babel。它的介绍可以参考Babel: Introduction、组织你的意念:Emacs org mode。
之所以叫Babel,可能是因为它被翻译成的语言最多的吧,真正做到了语言无关。另外,
Douglas Adams
在科幻小说银河系漫游指南
中提到的Babel Fish
,它是一种可以很小、黄色的可以塞到耳朵里,把一种语言转换成另一种语言的奇怪的鱼。
下面展示了,在Org-Mode中,使用10种语言打印Hello world!
。
当然,Org-Mode中还可以在不同语言中传递数据。每个代码block中也可以设置session,来保证相同的语言多个代码块之间共享环境。
另外,也有人为Org-Babel开发了对应的ipython版本,我们可以在强大的Org-Mode中使用强大的ipython。(scimax)
3. 参考资料
1. A Multi-Language Computing Environment for Literate Programming and Reproducible Research