项目规模和语言的严格程度之间是否存在关联?


72

我向我的一位同事解释了语言严格性和范式之间的区别,最后我断言:

  • 诸如动​​态语言和解释语言之类的宽容语言最适合用于原型和小型项目或中型Web应用程序。当选择带有Node.js的优雅动态语言(例如Python或JavaScript)时,其好处是:

    1. 快速发展,

    2. 减少样板代码,

    3. 能够吸引年轻的,有创造力的程序员,他们逃离  Java之类的“企业语言”

  • 静态类型化/编译语言最适合要求更高严格性的应用程序,例如业务关键型应用程序或中型到大型应用程序。

    1. 数十年来发展起来的著名范例和模式,

    2. 易于进行静态检查,

    3. 能够找到许多具有数十年经验的专业开发人员。

  • 严格的语言(例如Haskell,Ada)或技术(例如C#中的代码合同)更适合于优先考虑安全性而不是灵活性(即使Haskell可以非常灵活)的系统,例如生命攸关的系统和预计非常稳定的系统。好处是:

    1. 能够在编译时捕获尽可能多的错误,

    2. 易于进行静态检查,

    3. 易于形式证明。

但是,通过查看大型公司用于大型项目的语言和技术,看来我的主张是错误的。例如,Python已成功用于大型系统,例如YouTube或其他需要大量严格性的Google应用程序。

项目规模与应使用的语言/范例的严格程度之间是否仍然存在关联?

我忘记了要考虑的第三个因素吗?

我哪里错了?


12
严格类型检查和静态类型检查不是同一回事。Python是动态类型的,但比C更严格。静态类型检查的优点并不是严格的本身,而是在构建时而不是运行时检查类型。由于隐式转换,我在职业生涯中处理过许多C / C ++问题。
史蒂芬·本纳普

5
关于生命周期,也许有话要说:从您的第一类开始的软件可以演变为其他软件,并以此来“拖累”语言。

11
关于javascript的唯一优雅之处是它可以在大多数浏览器中运行。
JeffO 2014年

1
@StevenBurnap:关于静态和严格之间的区别,我完全同意。Java是频谱的另一个方面,它是静态的并且过于严格。开发人员经常以使用Java为例来谴责静态类型,但是实际上,大多数批评应该针对Java的过于严格的编译器,而不是通常的静态类型。只需查看同一静态类型的JVM上的Scala,但由于出色的编译器的类型推断功能,其冗长的代码要少得多。
Cornel Masson's

2
“ Python已成功用于大型系统”-“成功”在这里的定义是什么?它主要运行并产生一些结果吗?是否包括所需的测试和劳动力数量?可维护性如何?
书斋

Answers:


39

David Pollak 在Beginning Scala中找到了一个有趣的案例研究,该案例研究了使用动态语言和解释语言的扩展项目问题。

我开始寻找一种以更简单,更直接的方式在我的大脑中表达代码的方法。我找到了Ruby和Rails。我感到解放了。Ruby允许我用更少的代码行来表达概念。与Spring MVC,Hibernate和其他“简化的” Java Web框架相比,Rails的使用要容易得多。使用Ruby和Rails,我必须在更短的时间内表达更多的想法。这类似于我从C ++迁移到Java时的解放...

随着我的Ruby和Rails项目扩展到几千行代码,并且当我向项目中添加团队成员时,动态语言的挑战就变得显而易见。

我们花费了一半以上的编码时间来编写测试,而我们看到的许多生产力提高都损失了测试编写。大多数测试在Java中是不必要的,因为大多数测试旨在确保在我们通过更改方法名称或参数计数来重构代码时更新了调用方。另外,我发现在团队中存在两到四个团队成员之间存在思想融合的团队时,Ruby的工作进展顺利,但是当我们尝试将新成员引入团队时,这种心理联系很难传递给新团队成员

我一直在寻找一种新的语言和开发环境。我一直在寻找一种像Ruby一样具有表现力但又像 Java 一样安全和高性能的语言...

如您所见,作者项目扩展的主要挑战原来是测试开发和知识转移。

特别是,在第7章中,作者将详细解释动态和静态类型的语言在测试编写方面的差异。在“有力地杀死兔子:Dwemthy的台阶”一节中,作者讨论了特定Ruby示例的Scala端口:

为什么Lucky Stiff ...在Dwemthy的Array中引入了Ruby的一些元编程概念,其中,兔子与一系列生物战斗。N8han14更新了该示例以在Scala中工作 ...

与Ruby代码相比,Scala代码的库部分更加复杂。我们必须做很多工作来确保我们的类型正确。我们必须在DupMonster和CreatureCons类中手动重写Creature的属性。这比还要多method_missing。我们还必须做大量的工作来支持我们的生物和武器的不变性。

另一方面,结果比Ruby版本强大得多。如果我们必须为Ruby代码编写测试以测试Scala编译器向我们保证的内容,那么我们将需要更多的代码行。例如,我们可以确定我们的兔子不会挥动斧头。为了在Ruby中获得这种保证,我们必须编写测试以确保|^对Rabbit的调用失败。我们的Scala版本可确保该Creature只能使用为给定Creature定义的武器,而这在Ruby中需要大量的运行时反射。


上面的阅读可以使人认为,随着项目的扩大,测试写作可能变得非常繁琐。正如这个问题中提到的成功的非常大的项目的例子所证明的那样,这种推理是错误的(“ Python成功用于... YouTube”)。

问题是,项目的扩展并非真正简单。大型,长期存在的项目可以使用生产质量测试套件,专业的测试开发团队和其他重量级的东西来“负担”不同的测试开发过程。

与类似Dwemthy的Array之类的小型教程项目中的测试相比,Youtube测试套件或Java兼容性套件的寿命肯定会有所不同。



24

您的主张没有错。您只需要更深入地研究即可。

简而言之,大型系统使用多种语言,而不仅仅是一种语言。可能有些部分是使用“严格”语言构建的,而某些部分是使用动态语言构建的。

至于您的Google和YouTube示例,我听说它们主要将Python用作各种系统之间的“胶水”。只有Google知道这些系统是用什么构建的,但是我敢打赌,许多Google的关键系统都是使用严格的“公司”语言(例如C ++或Java)构建的,或者可能是他们自己创建的诸如Go的语言。

并不是说您不能在大型系统中使用容忍语言。许多人说Facebook使用PHP,但他们忘了提及Facebook必须创建极其严格的编程准则才能有效地大规模使用它。

所以是的,大型项目需要一定程度的严格性。这可能源于语言或框架的严格性,也可能源于编程准则和代码约定。您不能仅仅抓住几个大学毕业生,给他们Python / Ruby / JavaScript,并期望他们编写可扩展到数百万用户的软件。


“您不能仅仅抓住几个大学毕业生”,并期望他们编写可扩展到数百万用户的软件。” 可能就足够了。
dysdyes

值得一提的是,与Google和Python一样,Facebook对PHP的使用在很大程度上是胶水……我的理解是,对于大多数功能,PHP大多只是作为相对简单的客户端使用到通常实现的更复杂的服务器系统上在更传统的“重量级”的语言,例如Java,C ++,Haskell中,OCAML等

“只有Google知道这些系统是用什么构建的。”。我什至对此有些怀疑:)以我的经验,没有任何一个实体(人或其他)可以列出大型系统的所有部分。在许多情况下,Perl,Fortran或KSH脚本执行了“ Magic”操作,这被遗忘在服务器的碗里了。
mattnz

3

有两种类型的错误要检查:类型错误(连接一个整数+浮点数列表)和业务逻辑错误(将钱转移到银行帐户,检查源帐户中是否有钱)。

动态编程语言的“动态”部分只是进行类型检查的地方。在“动态类型”编程语言中,在执行每个语句时进行类型检查,而在“静态类型语言”中,在编译时进行类型检查。您可以为静态编程语言编写解释器(如emscriptem一样),也可以为动态编程语言编写静态编译器(如gcc-pythonshed-skin一样)。

在像Python和Javascript这样的动态编程语言中,您不仅需要编写用于程序业务逻辑的单元测试,而且还需要检查您的程序是否没有任何语法或类型错误。例如,如果将“ +”整数添加到浮点数列表中(这没有意义,并且会发出错误),则使用动态语言,在尝试执行该语句时会在运行时引发错误。在像C ++,Haskell和Java这样的静态编程语言中,这种类型的错误将由编译器捕获。

使用动态检查的编程语言编写的小型代码库更易于查找类型错误,因为更易于100%覆盖源代码。就是这样,您以不同的值手动执行了几次代码,然后就完成了。拥有100%的源代码覆盖率可以清楚地表明您的程序可能没有类型错误

对于使用动态检查的编程语言的大型代码库,很难测试具有每种可能的类型组合的每个语句,尤其是如果您粗心大意并编写一个函数,该函数可能根据其参数返回字符串,列表或自定义对象。

在静态检查的编程语言中,编译器将在编译时捕获大多数类型错误。我之所以这么说是因为除数为零的错误或数组超出范围的错误也是类型错误。

真正的讨论通常不是关于编程语言,而是关于使用这些语言的人们。确实如此,因为例如汇编语言与任何其他编程语言一样强大,但是我们仍在使用JavaScript编写代码。为什么?因为我们是人类。首先,我们都会犯错误,并且使用专用于特定任务的专用工具会更容易且更容易出错。其次,存在资源限制。我们的时间有限,编写汇编网页要花费很多时间才能完成。


3

我在大型系统上的经验是,它们的成败不是取决于语言选择,而是取决于设计/体系结构测试范围的问题。我宁愿在我的大型企业项目中拥有一支才华横溢的Python团队,也不愿使用普通的Java团队。

话虽如此,任何让您编写更少代码的语言都必须值得一看(例如Python vs Java)。也许未来将是具有高级类型推断功能的聪明,静态类型的语言(例如在Scala模型中)。还是混合式的,例如C#正在尝试使用其dynamic限定符...?

而且,别忘了“其他”静态类型输入的好处:正确的IDE代码完成/智能感知,在我看来这是必不可少的功能,而不是一个不错的功能。


1
“代码完成/智能”-自动重构也非常重要。
书斋

@Den绝对。动态语言是否可以帮助您非常快速地编写初始版本(更容易,编写的代码更少),但后来却陷入困境,因为评估变更或重构的影响变得越来越困难(没有自动重构工具)?
康奈尔·马森2015年

0

另一个考虑因素是编写大型应用程序的背后的。我曾在许多地方工作过,这些地方想在某些大型企业风格的项目中使用Ruby或Python,但由于项目的开源性质,它们一直被IT经理和公司安全团队“击倒”。

有人告诉我,“我们不能使用Ruby on Rails,因为它是开源的,有人可以在其中放置黑客来窃取关键或受保护的信息。” 对不起,但是一旦有人对开源==邪恶有了这种想法,几乎就不可能改变它。这种思路是一种共同的疾病。

C#和Java是具有受信任平台的受信任语言。Ruby和Python是不受信任的语言。


2
我不同意最后一行。Java是有史以来最低的信任点之一。整个开源社区都谨慎考虑C#。Ruby被认为是可靠的但很慢(即使不再使用了),而Python是整个行业(机器学习和数据科学,有人吗?)值得信赖的功勋之子。
CodeBeard

1
动态语言对安全性不利,但是“开源”不是很好的理由。也许他们的意思是“很容易从完全不同的部分影响代码的一部分”。见programmers.stackexchange.com/questions/206558/...
欣快

1
注意,确实,“开源”是语言选择的方面之一。例如这就是Jeff Atwood解释Discourse为什么使用Ruby 的三个原因之一
2013年

C#现在是完全开源的,但是它仍然是由专业开发人员策划,计划和开发的,我想这很好。我们希望这里不会发生“ Python 3 vs 2”这类事情。
书斋

Bug和安全漏洞是由程序员而不是语言引入的,为了记录,我为开源项目贡献了许多安全修复程序。我帮了多少个封闭项目???零!
Reactgular 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.