在我看来,静态/强类型编程语言最宝贵的一点是它有助于重构:如果/当您更改任何 API 时,编译器会告诉您该更改破坏了哪些内容。

我可以想象用运行时/弱类型语言编写代码......但我无法想象没有编译器帮助的重构,也无法想象在不重构的情况下编写数万行代码。

这是真的?

有帮助吗?

解决方案

我认为当类型与他们是如何检查检查你混为一谈。运行时类型不一定弱。

静态类型的主要优点正是你说的话:他们无遗。你可以仅仅通过让编译器确信所有调用点符合类型做的事情。

静态类型的主要限制是,他们在他们可以表达的约束限制。此因语言而异,与具有相对简单的类型系统(C,java的),以及其他大多数语言与极其强大的类型系统(Haskell中,辣椒)。

由于自身此限制类型的不充分。例如,在Java类型都或多或少限于检查类型名称匹配。这意味着选中你想要的任何约束的意义已被编码成某种类型的命名方案,间接性和普通Java代码锅炉板,因此过多。 C ++是一个好一点的在模板允许更多的表现,但不来接近你可以依赖的类型做什么。我不知道是什么缺点,以更强大的类型系统,但显然必须有一些或更多的人会在工业上使用它们。

即使你使用静态类型,它就有可能是不够的表现,以检查你所关心的一切,所以你需要编写测试过。无论是静态类型节省你比它需要的样板更多的努力是真实肆虐的年龄,而我不认为辩论对所有的情况下一个简单的答案。

至于第二个问题:

我们如何能够重新因素在安全运行时类型的语言?

答案是测试。你的测试必须涵盖所有重要的案件。工具可以帮助你在衡量你的测试如何详尽的。覆盖检查工具,让你知道的代码阉线由测试或不覆盖。测试突变工具(小丑,诘问)可以让你知道,如果你的测试在逻辑上是不完整的。验收测试让你知道你写的匹配要求,最后回归和性能测试,保证了产品的每个新版本保持最后的质量。

一个关于已具备了正确的测试VS依托精品型间接性的伟大的事情是,调试变得简单多了。当运行测试你的测试中的特定失败的断言,明确表达自己在做什么,而不是钝编译器错误语句(认为C ++模板错误)。

不管你用什么工具:编写代码,你有信心在需要努力。它最有可能需要编写大量的测试。如果惩罚的错误是的非常的高,如航空航天,医疗控制软件,你可能需要使用正规的数学方法来证明你的软件,这使得这样的发展极其昂贵的行为。

其他提示

我完全支持你们的情感认同。该动态类型语言应该是善于非常灵活实际上是什么使代码很难维护。确实,有这样的事情作为继续如果数据类型以非平凡的方式改变其工作,而无需实际改变的代码的程序?

在此同时,你可以检查变量传递的类型,并以某种方式如果它不是预期的类型失败。你仍然需要运行代码来铲除这些情况,但至少东西会告诉你。

我认为谷歌的内部工具实际上做的汇编和可能类型检查自己的JavaScript。我希望我有这些工具。

首先,我是一名本地 Perl 程序员,因此一方面我从未使用静态类型网络进行编程。OTOH 我从未与他们一起编程过,所以我无法谈论他们的好处。我能说的是重构是什么样的。

我不认为缺乏静态类型是重构的问题。我发现问题是缺乏重构 浏览器. 。动态语言的问题是,在实际运行代码之前,您并不真正知道代码到底要做什么。Perl 比大多数语言都更具备这一点。Perl 还有一个额外的问题,那就是它的语法非常复杂,几乎无法解析。结果:没有重构工具(尽管 他们正在非常迅速地开展工作)。最终的结果是我必须手动重构。这就是引入错误的原因。

我有测试来抓住他们......通常。我确实发现自己经常面对一堆未经测试和几乎无法测试的代码,存在先有鸡还是先有蛋的问题,即必须重构代码才能测试它,但又必须测试它才能重构它。恶心。此时,我必须编写一些非常愚蠢的高级“程序输出是否与之前相同”之类的测试,以确保我没有破坏某些东西。

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

经典例子: public static double sqrt(double a) 是个 Java 平方根函数的签名. 。平方根不适用于负数。签名里哪里有这么说?事实并非如此。更糟糕的是,它在哪里说明了该函数的作用?签名仅说明它采用什么类型以及返回什么。它没有说明中间发生的事情,而这就是有趣的代码所在的地方。有些人尝试使用以下方法捕获完整的 API 按合同设计, ,它可以广泛地描述为嵌入函数的输入、输出和副作用(或缺乏)的运行时测试......但那是另一个节目了。

API 不仅仅是函数签名(如果不是,您就不需要 Javadoc 中的所有描述性散文),并且重构也不仅仅是更改 API。

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

我想说的重构已经超出了编译器检查,即使是在静态类型语言中。重构只是改变程序的内部结构,而不会影响外部行为。即使在动态语言,仍然有东西,你可以期望发生和测试,你只是失去的帮助一点点从编译器。

对使用的 VAR 在C#3.0的好处是,你可以经常改变的类型而不断裂任何代码。该类型需要仍然看起来是一样的 - 属性名称相同的必须存在,仍然必须存在具有相同或相似的签名方法。但是,你真的可以改变一个非常不同的类型,即使没有使用像ReSharper的。

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