讲师在科迪哥

在本文¹中,我想探讨计算机程序编写过程与文学小说创作过程之间的关系。 特别是,我想看看我们今天编写程序的方式,可以从Fabula的LectorFictional Woods的Six Walks中的 Umberto Eco提出的文学理论中找到什么相似之处。 本文的目的是提出以下问题:作为程序员,我们可以从文学理论中学到什么? 我们可以从该学科中将哪些想法纳入我们的日常编程活动中,以便我们编写对其他人(或我们未来的人)更容易理解的代码

在本文的第一部分中,我将介绍一些对于这些讨论至关重要的文学概念,例如“模型阅读器”和“百科全书”,同时尝试将它们与编程联系起来。 事不宜迟,让我们进入树林,并尝试浏览分叉路径的花园²。

模型阅读器

我们必须要理解的第一个概念是文本的模型阅读器。 模型阅读器不是经验阅读器(不是您或我)。 这是一个忠于作者思想的读者,作者在撰写故事时就建立了这个读者。 该模型读者将帮助作者确定工作中需要多少细节,以便经验丰富的读者能够理解。 让我们用一个例子来说明这一点。

如果我写的文字是“我坐在电脑前开始编码[…]”,则我已经根据我的Model Reader做出了一些选择,我需要传达多少信息,在这种情况下,我假设我没有无需说明我正在使用键盘键入程序,因为在大多数情况下,就是这样完成的。 在那一句话中,我的Model Reader是一个熟悉计算机工作原理以及如何在当今的计算机中键入程序的人。

因此,“模型阅读器”思想的一个方面围绕着我作为作者在文本中提供多少信息或上下文,因此我试图传达的信息是可以理解的。

同时,随着故事的发展,作者还建立了Model Reader。 现在,让我们想象一下我以前的文字如下:“我坐在电脑前,开始编码。 一旦窗外的云层被清除,就露出了火星的风景。”一旦单词“火星”出现在文字中,我们就可以很容易地看出,似乎是个人的回忆(关于我在电脑上打字),原来是一门科学。关于太空探索的小说故事。 利用这样的小线索-火星-作者建立了一个模型阅读器,该模型阅读器必须接受这个故事是虚构的,因为到目前为止我们还没有人类生活在火星中。

在Fabula的Lector一书中,Eco深入探讨了模型阅读器(和模型作者)的概念,提出了文本合作的概念。 他在那里说³:

Un testoèun meccanismo pigro(oeconomico)che vive sul plusvalore di senso introdottovi dal destinatario […]

文本是一种懒惰的(或经济的)机制,它依赖于接收者引入的含义的剩余价值[…]

阅读本质上是作者和读者之间合作的作品。

总结到目前为止,我们有一位作者使用“模型阅读器”来决定如何讲故事,既需要提供多少细节,又有如何提供线索告诉读者这是一个故事。黑色小说,或者这是史诗般的幻想,或者到目前为止所说的一切都是梦的一部分,所以如果您继续阅读,请务必小心,因为接下来发生的事情可能仍然是梦的一部分 。 模型阅读器是愿意与作者合作的人。 模型阅读器实现文本。

问题是模型阅读器的概念如何帮助我们思考如何编写程序? 谁是我们的模型阅读器? 是电脑吗? 是另一个人还是我的未来?

程序员的模型阅读器

编写程序和编写小说之间的一个显着区别是,大多数时间都是将程序编写给计算机执行,而不是像人类从小说中所期望的那样,是由人类来找到情节和故事情节的发展。

在编写软件时,我们试图满足一些非常实际的需求,试图解决人类的问题。 是的,有时我们只是出于娱乐目的而编写代码,但是关键是我们希望程序给出一些非常具体的结果。 举一个非常简单的例子。 如果我们编写一个幂函数,并为其提供5²作为输入,那么我们期望得到25作为结果。 这通常意味着我们知道正确的程序意味着什么:汽车中的ABS系统是否在正确的时间启动,导致汽车停车,还是发生了事故? 这意味着如果重要的是结果,则无需解释代码,因为我们知道代码应该做什么。

从前一种观点来看,我们应该将代码视为产生结果的黑匣子。 只要计算机能够运行它,我们就很好。 仅具有这种观点的问题是我们错过了人类发挥作用的部分。 我想到了《计算机程序的结构和解释》中的这句话:

必须编写程序供人们阅读,并且只能偶然地使机器执行。

问题是,即使一个人可以享受阅读源代码的活动,但最终,该程序的验证者将是执行该代码的计算机。 那么我们如何整合这两个看似相反的观点呢?

我们可以尝试通过思考编写程序时的模型读取器来回答这个问题? 键入代码时,我们要记住谁? 想到的第一个答案是编译器。 我们编写代码时要遵循特定编程语言的所有语法规则,同时提供所有必要的线索来查找程序中使用的函数和类型的定义。 可以说,当我们编写“我们在玩计算机”的程序时,就会想到。 由于今天几乎没有人为特定计算机编写代码,因此可以说我们在脑海中建立了模型计算机,然后根据对理想计算机的假设,尝试第二次猜测它将如何运行我们的代码。 因此,我们的模型阅读器会在尝试满足编译器和虚拟计算机之间波动。

合作游戏

在我们脑海中玩电脑的想法很有趣,因为它与Eco的将文字作为策略游戏产生的想法有关。 为了在战略游戏中获胜,我们建立了一个模型对手,并使用该模型来尝试预测他们的举动,因此我们可以制定一项有助于我们赢得游戏的战略。 Eco说,从某种意义上讲,惠灵顿在滑铁卢设法建立了一个更精确的拿破仑模型。

让我们忘记打架,让我们思考一下合作,让我们思考如何建立策略来帮助文本的目标实现它。 用生态的话来说:

取消测试的资格。

文本希望有人帮助它工作。

我们如何帮助计算机/编译器实现文本,从而能够像阅读小说时一样使代码栩栩如生? 从文献中借用,我们可以说在声明类型时进行世界构建,然后告诉编译器在哪里可以找到定义程序中使用的接口的标头。 每当我们使用名称(如变量)时,都必须先声明它们。 在强类型语言中,我们甚至为这些变量分配类型,除非该语言提供了类型推断,否则所有线索都可以帮助编译器,否则编写诸如User user = new User();的意义何在User user = new User(); 除了帮助编译器?

在文学中,我们有“副文本”的概念,从章节标题到介绍性文字,可以告诉我们这本书是基于迷失的手稿,甚至章节副标题也可以告诉我们以下文字应该是什么?即将。 例如,在唐吉Don德(Don Quixote)中,章节标题后面紧跟这样的文本:

第一章

其中介绍了拉曼恰(La Mancha)著名绅士唐吉x德(Don Quixote)的性格和追求。

我们的代码中有这种超文本吗? 是的,如前所述,我们不仅指定导入,还将代码排列在模块,包和库中。 我们为编译器指定标志,在类似Haskell的语言中,我们可以使用编译指示。 这意味着在编写代码时,我们不仅针对模型计算机,还针对编译器,并且我们正在尝试向其提供信息,以便它能够理解当它找到表示变量的代码时应该怎么做。 isActive属于AtomicBoolean类型。

虽然这解释了我们在编写程序时谁是我们的模型阅读器,但这并没有说明我们如何或为什么应该编写供人们阅读的程序,即人类应该理解的程序。

不同级别的读者

Umberto Eco在《 互文反讽与阅读水平 》一文中写道,具有美学目的的文本往往会构成几个层次的模型读者。 在第一阶段,读者只希望完成故事,了解发生的事情,知道故事的结局。 第二层次的读者是符号或审美的读者,他们想知道发生了什么事。 要成为第二层次的读者,一个人必须多次阅读一个故事。

我想假设我们人类是我们程序的第二层读者。 我们是想知道代码中发生了什么的人。

问题是我们如何理解文本并为其增添含义,同时了解其预期目标? 作为作者/程序员,我们如何帮助他人理解我们的代码? 为了回答这个问题,我们需要介绍百科全书的概念。

百科全书

在Fabula的Lector和虚构的森林中的六步走中,Eco引入了百科全书的思想,其中包含了世界上所有的知识。 可以肯定地说,没有人拥有这种知识。 我们有自己的有限百科全书。 每当我们尝试解释文本时,我们都会将自己的百科全书带入游戏并重建故事,并根据自己的能力将其实现。

就像我在上面的示例中一样,每当阅读文本时,只要有人输入一个计算机程序,我们就可以在实现文本时做出很多选择。 如果我们想象程序员在笔记本电脑上或在与计算机相连的键盘上键入程序,则没关系,除非所使用的设备与故事的其余部分有关。 我习惯于在笔记本电脑上编写程序,因此很可能我会与在这种计算机上键入程序的人一起为该场景成像。 程序员的性别是什么? 他们是金发还是黑发? 对于某些读者而言,这并不重要,因此他们甚至都无需考虑,而其他人则可以根据自己的偏好或偏见来呈现它们。 从中得到的教训是, 我们利用自己的百科全书中的可用内容来填充故事的空白 。 这就提出了一个非常有趣的问题,即我们作为作者如何设法将我们的思想从我们的思想转移到我们的交流接受者或目的地。 如果我们失败了,那么另一个人可能最终会对代码的作用做出不同的解释。

他说,法科拉的《讲故事的人》的一个关键思想是对通信理论的批评。

[…]非竞争性的竞争性权利。

[…]目的地的权限不一定是发送者的权限。

然后他补充说:

普通话的邓克(Dunque),普通语言的普通话,普通话的语言,普通话的变动,普通话的能力,普通话的提示,等等。

因此,除了语言能力之外,为了“解码”口头信息,还需要不同的环境能力,触发预设的能力,抑制特质等,等等。

在《我们计算的隐喻》中,我写道我们应该使用正确的数据结构来帮助其他人理解我们的代码。 当我们选择将集合存储在集合而不是数组中时,我们是在告诉其他人该集合中的项目必须唯一。 选择正确的隐喻可以帮助我们推理代码和算法。 在分布式系统文献中,有一篇名为《数据库维护的流行算法》的论文,介绍了用于复制分布式更新的随机算法。 它的作者使用八卦隐喻来解释这个想法,但是当是时候证明他们的工作成果时,他们发现这种流行隐喻更适合于对他们的思想进行数学推理。

我们还需要考虑paratext如何帮助我们理解程序。 当我们将utils视为程序包名称的一部分时,我们对程序包内容的期望与对networkpersistence的期望有所不同。 诸如FileSystem类的类名称告诉我们有关其API的期望的很多事情,在其中找到一个名为stringCompare的公共方法会感到很奇怪。 代码注释可能是最重要的paratext之一,可以帮助其他程序员理解我们的代码。 使它们与代码保持同步是一个完全不同的问题。 甚至塞万提斯也没有逃脱这种命运。 在《堂吉x德》中,第X章的原始描述与该章的内容不符!

需要牢记的另一点是在同名论文中Peter Naur所说的“ 编程为理论构建 ”。 他认为,要编写一个程序,我们必须首先建立关于我们要解决的问题的理论,例如,五金店的存货。 当一个新人加入团队时,我们如何传递这种隐性知识,该理论,以便他们能够理解代码? 当我们成为原始开发人员已久的项目的维护者时,会发生什么? 我们如何确保原始程序员对此问题的所有隐式知识在以后通过代码共享? 我们需要创建什么样的文本才能成功地将隐性知识转化为显性知识? 在“ 创造历史:编写需要编写的文档”一文中,我认为我们应该编写尽可能多的文档,以帮助人们理解我们的代码。 我们需要超越隐性知识。 社会以书面形式收集其传说是有原因的,因此它成为历史。 口头传统迷路了。

失败的期望

试图理解代码时要记住的另一件事是,执行上下文中的微小更改如何可以完全改变代码的含义,或者无论如何我们应该如何解释它。 实例化诸如DatabaseConnection类的类,然后在测试运行期间对该类进行模拟或存根时,从其API调用方法的代码是什么意思?

那么针对各种操作系统,不同类型的数据库或文件系统的代码又会如何以noops的形式实现某些操作呢,因为目标系统中没有等效的代码呢? 我们应该如何解释和理解调用此类操作的代码? 也许这里的paratext可以以可以提醒我们该特定实现的注释的形式来拯救。 如果我们读到一条间接说明“ ___ OS不支持此操作,但必须实现它才能满足API”的注释,那么从其余代码中我们应该了解什么? 这似乎是要满足以“本文中的一切都是谎言”开头的文本的悖论。

问题

除了结论以外,我想给我们留下一些未解决的问题。

如果我们在编写代码时没有想到在编译器中拥有编译器/计算机,而是试图构建更接近于其他程序员的Model Reader,该怎么办? 最终,我们选择的IDE将帮助我们满足编译器的要求,而验证测试可以帮助我们验证我们对模型计算机的假设是否正确。 然后,我们要做的是确保另一个程序员能够理解我们的代码。

当我们编写/阅读代码时,百科全书的思想对我们有何影响? Eco表示,我们使用百科全书中的内容来填补空白,我们将键盘添加到了他们计算机前的那个字符上,并开始进行编码。 当有人向我们提供需要执行程序的模型时,我们需要从自己的百科全书中抽取多少? 从威廉·肯特(William Kent)的数据与现实(Data&Reality)中汲取灵感,我们的五金店库存模型和实现与五金店经理库存的模型相匹配多少? 当所述经理试图向我们转让他们的模型时,我们用自己的百科全书填写了多少? 最终,这使我们认为地图不是领土。


板条箱图片:https://en.wikipedia.org/wiki/Encyclop%C3%A6dia_Britannica#/media/File:Shipping_box_for_the_encyclopedia_Britannica_2013-04-13_12-24.jpg

1 – Fabula中Eco的Lector的英文翻译是“读者的角色”,该标题也可能适用于本文。

2 –这篇文章最初是为2018年的Salon desRefusés撰写的,目前正由其委员会审查。

3 – Google翻译,由我自己改编。

Fabula的讲师—翁贝托生态

虚构树林中的六步走-Umberto Eco

论文学—翁贝托·埃克

用于复制数据库维护的流行病算法-Alan Demers等

唐吉x德-米格尔·塞万提斯

数据与现实—威廉·肯特

我们计算的隐喻— Alvaro Videla

创造历史:编写需要编写的文档-Alvaro Videla