文学编程的直觉动机?

时间:2009-08-07 18:51:16

标签: scheme racket literate-programming scribble

所以,我使用 scribble/lp 模块使用plt-scheme编写我的第一个识字程序:

#lang scribble/lp
(require scribble/lp)

<<lp_scheme.ss>>

@chunk[<squarefunction>
        (define (f x)
         (* x x))]

当然没有什么用处。现在我有点想知道为什么我不会使用简单的注释,而不是文字编程结构。任何意见欢迎。如果有人可能有更多的曝光/曝光,那将是非常好的。有了它可能会更直观地解释良好记录的代码和使用Literate编程结构编写的代码之间的差异。

3 个答案:

答案 0 :(得分:9)

(我假设您正在使用Donald Knuth对文字编程的定义。)

关键区别在于序列

在编写常规应用程序时,对表达内容的顺序有限制。

举例说明:

  • 特定类的所有代码必须在一个地方表示
    (或在极少数地方,例如C#部分类)
  • 一个方法的所有代码必须按照正确的执行顺序一次性给出
  • 必须在依赖于它们的事物之前声明依赖性 (在大多数语言中使用之前声明的变量;在Pascal中使用之前声明的过程/函数;在.NET之前编译的库程序集)

使用识字编程,您可以摆脱这一限制,并在向其他开发人员解释程序时,以任何有意义的顺序表达您的概念。

这有另一个结果 - 在某些形式中,您可以表达一个概念(例如,“所有属性将在更改时触发PropertyChanged事件”),并在整个应用程序中将编织无数其他地方。

对于非常简单的程序,一个有文化的程序和一个评论良好的程序可能看起来一样 - 但随着系统复杂性的增加,两者将开始显得非常不同。

答案 1 :(得分:0)

对我而言,主要动机是每个程序员都使用纸张/笔记本来“设计”架构,开发创意,在那里他编写方案,图表,尝试一些数学等等。完成程序后,所有这些笔记本/纸张都丢失了,因此程序的可支持性正在下降。 我在我的LP工具NanoLP的WiKi中写到了这个:http://code.google.com/p/nano-lp/wiki/AboutLP

第二个动机,不是那么明确,是较小的错误。但这不是'理论'的事情,它是经验事实(对我来说) - 当你在纸上'思考',绘制图表,算法方案时 - 你的程序将有较小的错误。 LP就是这样的“纸”,没有别的。

有很多开发人员,他们从不画画,甚至没有评论(!),他们只编写程序......可怕!

并且LP可以帮助您创建良好的文档(不是以正式的方式 - 对函数的描述,它的args,以及它返回的内容,并且确定这对于函数签名很有名,所以为什么需要这样的文档?),但是它有助于用语义,图片和描述真实行为来编写真实的ACTUAL文档......

很多动机:)有时候最好只使用反向LP(例如Doxygen),有时候 - 真正的LP,取决于很多因素。

答案 2 :(得分:0)

Literate Programming基于三个简单的陈述:

  1. 程序员必须编写计算机可以理解的代码
  2. 程序员应该编写文档,人们可以理解
  3. 如果这些是单独的文件,那么它们将不可避免地不同步
  4. 事实上,根据我的经验,#2通常会被忽视。我已经不知道QA告诉我多少次了#34;医生说这个,但代码确实如此;是代码不正确还是文档已过期?&#34;在这方面,我不希望我的工作场所与众不同。此外,在我的一个早期项目中,我试图使文档保持最新,因为与利益相关者的反复导致需求的变化。这是非常耗时的,管理层告诉我,要停止搞乱文档并让项目工作。从那时起,我们就开始采用不那么繁琐的文档流程了(谢天谢地!)。

    我们有代码审查工具,当我们对代码进行更改时,多个人可以看到更改,明确描述,可以发表评论,提出问题,解释内容,提供改进。如果代码是用文字编程技术编写的,那么这个问题/答案的大部分内容都会过于夸张,因为会有解释。

    现代编程的大部分心态是你的代码应该是它自己的文档。许多权威人士认为,如果您发现自己需要在注释中解释代码,则应该重新格式化代码(更改变量/函数名称等),以便不需要注释。我发现这在理论上是伟大的,在现实中不太实际。我的意思是,当我使用由其他人创建/维护的库时,他们对方法/函数名称的选择对我来说并不总是直观的。例如:

    Set<String> statesWeCareABout = new HashSet<String>(Arrays.asList(new String[] { "one", "two", "three" }));
    Set<String> statesWeFound = <some function>;
    statesWeFound.retainAll(statesWeCareAbout);
    

    如果您不熟悉Set&lt;&gt;或者HashSet&lt;&gt;,你可能不知道.retainAll()意味着给我两者的交集,结果在修改后的Set&lt;&gt;。

    最后,Literate Programming通常会让你分解,这样你就可以单独解释这段代码,然后将它嵌入到另一段代码中。这更符合人类理解的运作方式。向我解释这是如何工作的,然后以这种理解为基础来解释更大的图景。电脑并不在乎;你可以编写一个包含1000行代码的函数,并且可以理解整个问题。如果你作为一名开发人员必须坚持下去,上帝会帮助你。

    而且,这确实是Literate Programming背后的原因。无论是修复了错误还是添加了功能,都需要维护代码。如果它不能被别人理解,以后,以有效的方式,它将被取代。有很多方法可以只写#34;这个世界的代码。文学编程使阅读和理解更容易,这使得它更有可能被长期保存和使用。

    我们真的有时间继续重新发明轮子吗?