所以,我用了 涂鸦/LP 使用 plt-scheme 编写我的第一个读写程序的模块:

#lang scribble/lp
(require scribble/lp)

<<lp_scheme.ss>>

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

当然,那里没有任何有用的东西。现在我有点想知道为什么我不使用简单的注释,而不是文字编程结构。欢迎任何意见。如果有人可能有更多的接触/经验,那就太好了。它可以更直观地解释有据可查的代码和使用 Literate 编程结构编写的代码之间的差异。

有帮助吗?

解决方案

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

主要区别之一是 顺序.

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

为了显示:

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

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

这还有另一个结果 - 在某些形式中,您可以表达一个概念一次(例如,“所有属性在更改时都会触发 PropertyChanged 事件”),并拥有该概念 编织 在您的应用程序中的许多其他地方。

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

其他提示

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

第二个动机(不那么明确)是减少错误。但这不是“理论”的事情,它是经验事实(对我来说)——当你在纸上“思考”、画图表、算法方案时——你的程序会有更少的错误。LP就是这样的“纸”,仅此而已。

有很多开发人员,他们从不画东西,甚至没有评论(!),他们只写程序......糟糕的!

LP 可以帮助您创建良好的文档(不是以正式的方式 - 函数的描述,它的参数,以及它返回的内容,并且确保这是众所周知的函数签名,那么为什么需要这样的文档??),但它有助于用语义、图片、真实动作的描述来编写真实的文档......

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

文学编程基于三个简单的语句:

  1. 程序员必须编写计算机可以理解的代码
  2. 程序员应该编写人们可以理解的文档
  3. 如果这些是单独的文档,那么它们将不可避免地不同步

事实上,根据我的经验,#2 通常会受到冷遇。我已经记不清有多少次 QA 告诉我“文档是这么说的,但代码是这么做的;代码是否不正确或者文档是否已过时?”在这方面,我不认为我的工作场所与众不同。此外,在我的一个早期项目中,我试图使文档保持最新状态,因为与利益相关者的反复交流导致了需求的变化。这非常耗时,管理层告诉我不要再搞乱文档,让项目正常运行。从那时起,我们就采用了不那么繁琐的文档流程(谢天谢地!)。

我们有代码审查工具,当我们对代码进行更改时,多个人可以看到更改,清楚地描述,并且可以发表评论,提出问题,解释内容,提供改进。如果代码是使用文学编程技术编写的,那么这个问题/答案的大部分内容将是多余的,因为将包含解释。

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

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

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

最后,文学编程通常让您分解事物,以便您可以单独解释这段代码,然后将其内联到另一段代码中。这更符合人类的理解方式。向我解释这是如何工作的,然后在此基础上解释更大的情况。计算机并不真正关心;你可以用 1,000 行代码编写一个函数,并且理解整个过程没有问题。如果您作为开发人员必须维护这一点,那么上帝会帮助您。

这确实是文学编程背后的原因。代码需要维护,无论是修复错误还是添加功能。如果其他人无法理解它,那么稍后就会以有效的方式被替换。这个世界上有很多“只写”代码。文学编程使它更容易阅读和理解,这使得它更有可能被长期保留和使用。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top