代码之家  ›  专栏  ›  技术社区  ›  ChrisW

静态/强类型和重构

  •  6
  • ChrisW  · 技术社区  · 15 年前

    在我看来,静态/强类型编程语言最有价值的地方在于它有助于重构:如果/当您更改任何API时,编译器将告诉您该更改破坏了什么。

    我可以想象用运行时/弱类型语言编写代码。。。但是,我无法想象没有编译器的帮助进行重构,也无法想象没有重构就编写成千上万行代码。

    这是真的吗?

    5 回复  |  直到 15 年前
        1
  •  12
  •   Jason Watkins    15 年前

    静态类型的主要优点正是您所说的:它们是详尽的。您可以通过让编译器做它自己的事情来确信所有调用站点都符合该类型。

    静态类型的主要限制是,它们只能表达约束。这因语言而异,大多数语言具有相对简单的类型系统(c、java),而其他语言具有非常强大的类型系统(haskell、cayenne)。

    由于这种限制,仅靠类型本身是不够的。例如,在java中,类型或多或少只限于检查类型名是否匹配。这意味着您要检查的任何约束的含义都必须被编码到某种命名方案中,因此java代码中有过多的间接指令和通用模板。C++有点好,因为模板允许更具表现力,但不能接近依赖类型的处理。我不确定更强大的类型系统的缺点是什么,尽管很明显,一定会有一些或更多的人在工业中使用它们。

    即使您使用的是静态类型,也可能无法充分表达您所关心的所有内容,因此您也需要编写测试。静态键入是否比样板文件中所需的节省更多的精力,这是一个争论已久的问题,我认为并不是所有情况都有一个简单的答案。

    关于你的第二个问题:

    我们如何在运行时类型的语言中安全地重新考虑因素?

    答案是测试。你的测试必须涵盖所有重要的案例。工具可以帮助您衡量测试的详尽程度。覆盖率检查工具让您知道测试是否覆盖了代码行。测试变异工具(jester、heckle)可以让您知道您的测试在逻辑上是否不完整。验收测试让您知道所编写的内容符合需求,最后回归和性能测试确保产品的每个新版本都保持了上一版本的质量。

    与依赖复杂的类型间接相比,在适当的位置进行适当的测试的一个好处是调试变得更加简单。在运行测试时,在测试中明确明确的断言,这些测试明确地表达了他们正在做的事情,而不是钝化的编译器错误语句(认为C++模板错误)。

    无论您使用什么工具:编写您自信的代码都需要努力。它很可能需要编写大量的测试。如果对bug的惩罚是 非常 高,如航空航天或医疗控制软件,您可能需要使用正式的数学方法来证明您的软件的行为,这使得此类开发极其昂贵。

        2
  •  6
  •   Matthias Wandel    15 年前

    我完全同意你的看法。动态类型语言所擅长的灵活性实际上使代码很难维护。真的,如果数据类型以一种非平凡的方式更改,而不实际更改代码,那么是否存在这样一种程序可以继续工作的情况?

    我认为Google的内部工具实际上是对Javascript进行编译和类型检查的。我希望我有那些工具。

        3
  •  2
  •   Schwern    15 年前

    首先,我是本地Perl程序员,因此一方面我从未使用静态类型网络编程。奥托,我从来没有和他们一起编程过,所以我不能谈论他们的好处。我能说的是重构是什么样的。

    我不认为缺少静态类型是wrt重构的问题。我发现一个问题是缺少重构 浏览器 they're working very rapidly on that )最终的结果是我不得不手工重构。这就是引入bug的原因。

    我有测试来抓他们。。。通常我确实发现自己经常面对一大堆未经测试、几乎不稳定的代码,面临着鸡/蛋的问题:必须重构代码以进行测试,但必须测试代码以进行重构。哎呀。在这一点上,我必须编写一些非常愚蠢的高级测试,“程序是否输出了与以前相同的东西”之类的测试,以确保我没有破坏某些东西。

    如java或C++或C语言中所设想的静态类型,只解决了一小部分编程问题。它们保证向您的接口传递带有正确标签的数据位。但仅仅因为你得到了一个集合并不意味着这个集合包含了你认为它包含的数据。因为你得到一个整数并不意味着你得到了正确的整数。您的方法接受用户对象,但该用户是否已登录?

    经典例子: public static double sqrt(double a) signature for the Java square root function . 平方根对负数不起作用。签名在哪里写的?没有。更糟糕的是,它在哪里说这个函数到底做了什么?签名只说明它需要什么类型和返回什么。它没有说明中间发生了什么,这就是有趣的代码所在。有些人试图通过使用 design by contract ,可以广义地描述为嵌入函数输入、输出和副作用(或缺少)的运行时测试。。。但那是另一场演出。

    API不仅仅是函数签名(如果不是的话,您就不需要Javadocs中所有的描述性文字),重构远远不止是更改API。

    静态类型、静态编译、非动态语言的最大重构优势是能够编写重构工具为您执行相当复杂的重构,因为它知道对方法的所有调用都在哪里。我很羡慕你 IntelliJ IDEA .

        4
  •  1
  •   Andy White    15 年前

        5
  •  1
  •   John Saunders    15 年前

    使用 可以 经常在不破坏任何代码的情况下更改类型。类型需要看起来仍然相同-必须存在具有相同名称的属性,必须仍然存在具有相同或类似签名的方法。但是,即使不使用诸如ReSharper之类的工具,您也可以真正更改为非常不同的类型。