acm-header
登录

ACM通信

实践

计算机程序的意义和上下文


三个人盯着一个显示屏

图片来源:PeopleImages.com,尤里·阿克斯

回到顶部

当您查看函数程序的源代码时,您如何知道它的含义—即,这个函数代表什么对象或进程?意义是在函数的返回值中找到的,还是位于函数体内部?函数名呢?

回答这些问题对于理解如何在使用源代码作为媒介的程序员之间共享领域知识非常重要。无论是调试还是向程序添加新特性,程序员都必须阅读代码来理解程序在做什么。通过阅读本文,程序员还必须知道问题域是如何在代码中表示的,这样他们就可以确定对源代码的更改不会使程序以意想不到的方式工作。

编程往往发生在团队中,在一个正在进行的项目中,程序员可能会被添加到团队中。新程序员应该通过阅读代码来理解程序在做什么。在一个程序员独自工作的情况下,当一段时间后回到源代码时,这个程序员必须理解他们过去写了什么。在任何情况下,程序都是程序员之间共享解决方案的通信媒介。

有句谚语说:“程序必须是为人们阅读而编写的,只是顺便让机器执行而已。”1那么,在程序的什么地方可以找到这种共享的意义呢?

回到顶部

函数和方法名

假设我们有一个类动物,哪个有一个方法被调用getName.类在迭代中使用forEach循环中所示图1

f1.jpg
图1。getName方法在做什么?

该方法可以返回宠物的名称(例如,托托)或物种名称(例如,).运行这个程序将产生如下输出马、猫,,这将帮助您推断该方法返回的是物种名称。(你可能会说这个方法更好的名字是getSpeciesName (),这是一个有效的批评。)

该方法getName提出了一种解释上的歧义,可以通过查看方法的返回值来解决。然而,你不能确定你的基础是正确的,因为你不知道需要多少情况才能做出正确的推论。在代码中是否有另一种装置可以帮助理解意思?要回答这个问题,请假设您一直在浏览这个项目的代码,直到您惊讶地发现一个不同的文件,其中的代码与动物文件。这是一个复制错误,还是这里发生了什么?在多次执行新找到的代码之后,您会看到它返回诸如独角兽美人鱼虚构的动物。检查这两个文件的文件夹结构,您会发现最后一个文件存在于该文件夹中lib /动物/虚构的,而第一类人住在lib /动物/非小说.因此,源代码外部的一段上下文——种并行-是帮助翻译。3.

一个旁注是一段信息,比如书名,章节标题,或序言,它表明了如何解释一篇文章,所以即使你很容易这样想堂吉诃德可能是一个历史的叙述,事实是它被描述为一个“小说”在这本书的前面事项告诉读者,它不能被视为事实。

的返回值独角兽而且美人鱼可以帮助您推断函数的含义,文件夹结构可以提供关于该方法含义的更有力的信息—例如,揭示该项目正在使用两种动物,虚构的和非虚构的。(Java和c#等编程语言在语言级别支持此特性,分别称为包或名称空间。)

回到顶部

返回值

一个函数的返回值是否可以被信任,作为一个函数的指示符,以及它可能的含义?考虑中的函数图2.(双正斜杠表示代码注释—也就是说,编译器将忽略因此不执行的源代码。)

f2.jpg
图2。我们能相信返回值是意义的来源吗?

调用的函数广场,当提供整数时x的2次方。在本例中,提供5,函数返回25。到目前为止,一切顺利。如果检查函数的源代码发现以下情况会发生什么?

函数平方(x) {

返回25;

该函数返回硬编码的25,因此如果传递5或-5,该函数将按预期工作。函数返回值可以被视为索引符号—也就是说,它们表明函数已被执行,但它们不能告诉您函数是否按预期工作。就像在雪地里看到脚印一样。你可以假设一只野兔刚刚穿过森林,但仅根据脚印你不能100%确定,因为它们可能是有人想要恶作剧你的脚印(参见翁贝托·艾柯关于索引标志的文章)2).

同样地,返回值也不足以推断函数是否正确工作—即使函数的返回值可以与已知的正确值进行比较,这些值可能符合函数的含义。在这种情况下广场,您可以编写一个测试程序,检查如果提供值3,该函数返回9,如果提供值-5,则返回25,以此类推。这就变得赘述了:因为您假定函数平方实现了2的数学幂,所以您假定9和25是正确的返回值。

在前面的例子中Animal.getName (),这些返回值指示广场(x)在屏幕上绘制边长等于所提供边长的正方形的图形函数不是这样吗x输入值。是否该函数广场(x)返回一个整数或在屏幕上绘制一个正方形,但是,可以从函数返回值的类型推断,假设信息可以在程序的源代码中指定。某些编程语言(如Haskell或Java)允许程序员为函数提供类型定义。因此,在前面的例子中,你可以这样写广场(x:整数)- >整数,这意味着函数方接受一个整数参数x返回另一个整数引导你的绑架或假设它返回x的平方。

然后,您可以从返回值查看函数的实际主体,因为在那里您可以了解正在实现的算法类型。

回到顶部

函数体

下一个任务是了解是否所有返回值都是相等的。假设你有一个函数random(start:Integer, end:Integer)—>整数-也就是说,该函数返回一个随机整数,该整数落在开始而且结束输入参数。问题是,您仍然不知道从函数中接收到的是哪种类型的随机数。

从安全的角度来看,当使用prng(伪随机数生成器)时,您可能想知道用于生成它们的算法,因为有些算法对于加密应用程序来说或多或少是安全的。该信息可以在函数体中找到,在该函数中实现了哪种类型的算法。如果你有两个随机函数,有不同的实现,一旦执行都碰巧返回数字7,那么你可能想知道这些数字是否来自一个系列,比如由Donald Knuth提出的线性同余方法产生的那个,4或者是盖伊·斯蒂尔提议的那部剧。5

在调用的函数中可以看到类似的示例sort (List [Integer]) -> List [Integer],它接受一个Integer类型的值列表,并返回一个已排序的Integer列表(升序还是降序现在不重要)。要知道使用了哪种排序算法,您必须查看函数的源代码,在源代码中可能会找到快速排序或插入排序算法的实现,这里只是举几个例子。

程序的意义不仅存在于程序源代码的各个部分——函数名、函数参数、函数体——而且还存在于包含该函数的包名,以及每次函数执行时接收到的函数类型的各种标记,即返回值。每个随机数都是一个符号,表明随机算法正在生成什么样的序列。

回到顶部

结论

程序员可以用这些信息做什么?要明白代码不会“自己说话”,但是在代码内部和外部都有不同的位置来指导解释。这篇简短的文章不能提供关于如何编写更容易阅读或理解的代码的指导,但它可以建议您注意这里提到的代码的每一部分或每一个方面,从而指导您决定使用源代码来传输有关问题域的信息。这为将来处理代码的开发人员在解释代码时提供了许多扶手来指导他们。他们不会只找到一些表示模型的随机单词,还会找到这些单词有意义的上下文。

进一步的探索可以处理程序内部名称中使用的单词之间的关系——函数名、变量名、类型名等等——并解释如何使用它们来构建一种表示现实世界某些过程的词典或DSL(领域特定语言)——就像超市库存的工作方式一样。这有助于理解程序员需要具备什么样的能力才能理解程序的功能。本文的探索仅限于查看该信息在程序中的位置,而不是从语义的角度来看它是如何生成或使用的。

回到顶部

参考文献

1.阿布森,H,萨斯曼,g。J,和萨斯曼,J。计算机程序的结构和解释。麻省理工学院出版社,剑桥,马萨诸塞州,1985年。

2.生态,U。符号学理论。印第安纳大学出版社,布卢明顿,1979年。

3.Genette G。文本:解释的阈值。剑桥大学出版社,英国剑桥,2001年。

4.Knuth D。计算机编程的艺术,第二卷。Addison-Wesley Professional,波士顿,马萨诸塞州,2011年。

5.Steele, G., Lea, D., Flood, C.H.快速可分裂伪随机数发生器。在2014年ACM实习生论文集。面向对象编程系统语言和应用, 453 - 472;https://dl.acm.org/doi/abs/10.1145/2660193.2660195

回到顶部

作者

阿尔瓦罗·威德拉是微软的开发人员倡导者,组织了DuraznoConf。他是RabbitMQ。在推特上找到他@old_sound


版权归所有者/作者所有。授权给ACM的出版权。
请求发布的权限permissions@acm.org

数字图书馆是由计算机协会出版的。版权所有©2022 ACM股份有限公司


没有发现记录

登录为完全访问
»忘记密码? *创建ACM Web帐户
文章内容:
Baidu
map