【问题标题】:What is a dynamic typing bug?什么是动态类型错误?
【发布时间】:2012-02-11 06:26:05
【问题描述】:

在编程方面,我对功能 x 与功能 y 没有强烈的看法。我认为各有各的用途。

而且我一直在阅读尽可能多的编程语言的所有内容,以便我可以提取出最好的想法并比较它们(从 Haskell 到 Lisp 到 C 到 Erlang)。

但是有些事情一直困扰着我,基本上就是当我读到静态类型和动态类型之间的比较时,动态类型的一个缺点是会出现“错误”,因为编译器不是能够检查变量的类型。

现在,我在编程时遇到了很多错误,但我从来没有因为这样的事情而遇到过错误,而且我实际上很难想象这样的例子是什么错误将是。就像可能忘记在某处使用整数而不是字符串一样?这似乎太做作了......

我编程是为了一种爱好,而不是为了谋生,所以也许这些类型的错误只有在具有不同思考方式的人聚在一起时才会出现。我真的只是在寻找一些真实的例子。

【问题讨论】:

  • 假设我给你一个函数作为我的 API 的一部分,看起来像这样:function foo(datablob1, id, args)。你认为我希望你通过什么?你会猜到 id 是一个字符串还是一个整数?你会猜到 args 是一个数组吗?什么数组?什么是数据块?它可能有什么属性?如果没有好的文档,你怎么知道?
  • 我通常只是在文档中查找该功能。这不是大多数人的做法吗?
  • “没有好的文档”
  • 我看到了——我只是觉得没有好的文档很奇怪。这可能是对与打字无关的一系列错误的解释。
  • 在专业领域中,使用完全没有文档记录的正在进行的系统或文档记录不充分的遗留代码并与对您来说是黑盒的服务进行交互的情况并不少见,您无法打开源代码以查看它打算使用的内容。这并不是说强类型可以解决问题,但无类型的动态语言会加剧问题。

标签: dynamic types static


【解决方案1】:

例如,当您将变量从一种类型更改为另一种类型时:

setType(String type)

然后你决定将类型更改为更有效的枚举:

setType(SomeEnum type)

当您使用强类型语言执行此操作时,无论在哪里调用 setType,您都会收到错误消息。这使您可以快速修复它们并确保您没有遗漏任何东西。在动态类型语言中,您不会遇到此类错误,您必须自己查找这些实例。

强类型语言通常也更快,因为它们可以以更有效的结构存储数据(因为类型在编译类型中是已知的)。一个例子是 C 数组与 PHP 数组。 C 数组是紧凑的,但 PHP 数组在管理它们包含的动态数据方面有相当大的开销。

【讨论】:

  • 啊,这是一个好点。所以基本上任何时候你有很多代码,然后你回过头来改变它的一些基本结构,你可能会错过很多其他地方需要修复的东西。
  • 经过一番思考,在我看来,可以开发某种系统来跟踪这些类型的大规模程序更改。 “尝试编译并纠正错误”对我来说似乎有点混乱。也许是将变量类型与数据库联系起来并描述它们的关系的东西。有这样的系统吗?
  • 在任何正在开发的实际系统中,非正式文档几乎总是不完整、不同步,甚至是完全错误的。另一方面,类型是经过机器检查的文档。
  • 很有趣,虽然看到这种情况有点难过。这种情况在现实世界的编程中是否比其他工作更常见? (即,我是一名化学工程师——如果系统没有最新的文档和彻底、频繁的检查,将会导致灾难)。我的意思是,我知道你在每个领域都有熟练和不熟练的员工——我只是想知道在软件开发中是否存在不保持文档最新的更高趋势?
【解决方案2】:

@Laurent 很好地回答了您的问题。我想补充一点,例如,有一个用于 JavaScript(一种动态类型语言)的测试/动态错误查找工具,名为 TypedJS。它只是为了防止由于动态编程而发生的错误。

TypedJS 试图防止的示例错误可以在此屏幕截图中看到:

【讨论】:

  • 这很有趣。所以它基本上是在产品发货之前而不是在发货之后发现人为错误?
  • @Nick 没错。 (1、2、3 这样就不会抱怨我的评论太长了...... :)
【解决方案3】:

关于类型及其对编程的价值有很多可以说的。例如,这是 CACM 最近的一篇文章,其中讨论了(除其他外)功能语言 OCaml 中发现的高级类型系统的轶事优势:

http://cacm.acm.org/magazines/2011/11/138203-ocaml-for-the-masses/

以下经典论文的前几页更符合原则,对程序错误的种类进行了分类,并解释了类型系统的一些基本优点:

http://www.lucacardelli.name/Papers/TypeSystems.pdf

由于后一篇论文比较老,我补充两点。

首先,类型化语言与需要(显式)类型声明之间存在差异。一些现代语言,尤其是来自函数式阵营的语言,具有复杂的类型系统,但大多数时候不需要您写下单一类型。所有类型均由编译器推断。

其次,类型系统本质上是一种逻辑。表达程序某些属性的逻辑,然后由编译器检查。原则上,这种逻辑的强大程度是没有限制的。有些语言的类型系统足够强大,您可以使用例如表示排序列表的类型和排序函数的类型,以便该函数仅对它是否确实是排序算法的正确实现进行类型检查。显然,如果编译器可以像这样实际检查程序的正确性,那将非常有用。然而,在类型系统的表达性和易用性之间存在权衡,因此在实践中,大多数主流语言最终都趋于简单化。但特殊领域可以极大地受益于更复杂的类型系统。

【讨论】:

    猜你喜欢
    • 2011-11-15
    • 2015-01-03
    • 1970-01-01
    • 2021-05-19
    • 1970-01-01
    • 2011-07-03
    • 2014-09-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多