我正在探索开发新系统(Web应用程序)的几种可能性。
我是一个“老式的”有点人,面向对象(多年前从程序转换而来)。我玩过Python并学习了一点Ruby,但坦率地说,我被吸引回使用微软的工具(C#,ASP.NET MVC)。所有这些运行时键入,基本内容上没有编译器错误等等,只会让我在构建大型复杂应用程序时更加艰难。
我经常听到人们谈论你可以用动态语言做的伟大事情,但除了狗,猫的例子以及你能用多快的方式编写一个很酷的方式来计算事物,Visual Studio的“工业实力”似乎消除动态语言提供的那些整洁的小东西,特别是现在你有免费的快速版本的VS和完整版本可供初创公司免费使用。
我觉得我在这里遗漏了一些东西,因为大型应用程序确实是用动态语言开发的,那么在查看大型复杂应用程序时,这些语言能让您做些什么呢?什么能让你放弃VS的力量?
答案 0 :(得分:19)
“你能以多快的速度编码”,所以完全担心我,我很高兴通过编译来放弃漫长而缓慢的困境。
动态语言的优点。
没有编译,没有构建。只需编码和测试,然后部署到生产。
立刻满足。没有时间花在API调用可能的上面。只需在Python>>>中以交互方式输入它提示并查看实际的内容。
非常非常短的设计周期。我不是精心制作具有奖励界面定义和适当的抽象声明和覆盖的类层次结构,而是可以对类进行编码,对它们进行单元测试并完成。
更少的代码。动态语言自省减少了源的数量。我不会在我的应用程序中写这些东西;我依靠框架来为我做这件事。但基于框架的代码通常很短;没有在Java中如此常见的重复声明,您必须在XML配置中重复这些声明。
没有神秘感。正如我们在Python社区中所说:“使用源代码,Luke。”框架的功能或API的真正含义并不含糊。
绝对灵活性。随着我们的要求发生变化,我们不必为破坏整个架构的破坏性变革而苦苦挣扎。我们可以 - 平凡地 - 对几个类进行更改,因为Python的Duck Typing消除了在我们认为不需要它们的情况下改进缺少的接口定义的需要。他们只是不是;我们没有编写的代码是我们无需修复或维护的代码。
韧性。当我们的精算师有脑屁时,我们不必花费数月时间来弄清楚如何将这种新的,更复杂的承保模型整合到应用程序中。几乎任何东西都可以被挤进去。再次,这完全是鸭子打字的结果。我们从一个无法预测新商业模式的架构中解脱出来。
由于源 应用程序,源可以是它自己的配置文件。我们在某些外来语法中没有XML或INI配置文件。我们在Python中有配置文件。 Django框架做到了这一点,我们跟随他们的领导。我们为销售演示和单元测试提供了非常复杂的模拟数据声明。超复杂数据实际上是来自数据库的Python对象的集合 - 除了 - 我们省略了加载数据库。只调整Python对象构造函数而不是加载SQL数据库更简单。
[顺便说一句。经过30多年的Cobol,Fortran,PL / I,Java,C,C ++软件开发,我只是厌倦了大多数编译语言所需的相对低级的手工优化。几年前,我读到了大多数编译器效率低下的评论:它引导我们创建精细的构建系统来解决编译器的限制。我们只需要make
因为cc
太慢了。]
修改强>
动态编程不会让你成为天才。它只是节省了很多时间。您仍然需要管理学习过程。你不知道的事情在所有语言中都很难。动态语言允许您逐步进行,一次发现一件新事物,而不需要进行大量的设计工作,只是为了发现您的假设是错误的。
如果您想根据误解的API编写大量代码,那么动态语言可以提供帮助。您可以自由编写大量以语言崩溃和烧毁的代码:C#,VB,C ++,Java或Python。你总是可以编写无效的代码。
编译器会提前警告代码不起作用。通常,不编译是一个很大的暗示。但是,您仍然可以编写大量编译并失败所有单元测试的代码。编译器只检查语法,而不检查语义。
Python可以预先警告代码不起作用。通常,您无法以交互方式运行它。但是,您仍然可以编写大量未通过所有单元测试的代码。
答案 1 :(得分:6)
静态类型是一种过早优化的形式。当你可能没有制作它们的知识时,它会迫使你事先做出详细的决定。除非您创建足够的类型以使其符合逻辑,否则它对程序的正确性没有特别的帮助。这使得很难动态改变数据结构。
你从中得到的是非常有限的正确性检查:非常有限,因为它没有分开使用int的方式,例如。假设我们正在处理行和列;两者都可能是整数,但行和列变量不应互换使用。你也得到了优化,这可能是一个非常有用的东西,但是不值得放慢初始开发的速度。您可以通过编写适当的测试来弥补正确性检查。
Common Lisp类型系统对此有好处。所有数据对象都知道它们的类型,如果愿意,您可以明确指定该类型。
eval循环类型的执行模型使您可以在编写例程时轻松测试它们。您不必事先明确地编写测试(尽管没有什么可以阻止您这样做);您可以编写它们并在运行中执行它们(然后您可以将其改进为测试套件 - 将其视为增量测试开发)。
没有很长的构建步骤可以更容易地进行测试驱动的开发,因为运行测试要快得多。每次想要测试时,你都不必分解你正在做的事情。
当我听到有人抱怨动态语言时,我会想起有人抱怨没有独占锁的版本控制系统。移动到现代VCS需要很长时间才能意识到他们获得了什么,同样需要很长时间来欣赏动态语言。
答案 2 :(得分:5)
总的来说,我更喜欢谈论“交互式”语言而不是“动态”语言。当您只有编辑/编译/运行周期时,任何周转都需要很长时间。好吧,至少按照“需要保存,编译,检查编译报告,测试运行,检查测试结果”的顺序。
使用交互式语言,通常很容易修改一小部分,然后立即测试结果。如果您的测试运行仍然需要一段时间,那么您没有赢得那么多,但您通常可以测试较小的情况。这有利于快速发展。一旦你有一个已知正确的实现,这也有助于优化,因为你可以快速开发和测试新的,改进的函数,并尝试不同的表示或算法。
答案 3 :(得分:3)
以下是my answer与之前类似问题(I know C#. Will I be more productive with Python?)的部分内容:
我自己来自C#/ .NET背景。在abt开始用.NET编程。 2001年,几乎同时被引入Python。 2001年,我花在C#vs. Python上的时间约为90%C#/ 10%Python。现在,这个比例是5%C#/ 95%Python。在我的公司,我们仍然维护一个基于.NET的产品线。但是所有新东西都基于Python。
我们在Python中创建了非平凡的应用程序。
根据我的经验,使我在Python与C#方面更有效率的是:
web.config
文件更少的代码行创建基于WSGI的Python Web框架: - )答案 4 :(得分:2)
互动外壳! 这是一个巨大的生产力增益。只需启动irb / python就可以坐在交互式shell之前 (分别用于ruby和python)。然后,您可以交互式地测试您的类,函数,表达实验(非常适合正则表达式),不同的语法和算法。这是真正的程序员游乐场和调试的好工具。
关于错误我只有两分钱:
所有这些运行时键入,没有编译器 基本的东西等错误就是这样 谈到我的生活更加艰难 建立大型复杂的应用程序。
编译器可检测错误是指您在执行各种自动测试(单元,功能等等)时应检测到的错误以及您应该编写的错误。 可能Linus Torvalds可以说:回归测试“?那是什么?如果它编译,那就好了,如果它启动它是完美的但他有成千上万的测试人员会做的工作 他。啊,并且使用交互式shell,您可以获得有关语法的自动反馈,例如编译应用程序但代码执行到位时。
答案 5 :(得分:1)
我也喜欢静态打字。但是当我编写Python时,我并没有发现我多么想念它(只要我正在使用的类都有很好的文档记录 - 而且我认为没有任何语言功能可以帮助我们避免错误的文档) 。在编写C ++时我也不会错过Python的大部分动态特性(lambdas,我想念:即使语法很糟糕,也要带上C ++ 0x。并列出清单。)
对于错误检测,大多数“错误类型传递”和“错误方法调用”错误不是很微妙,因此主要区别在于异常会替换编译器错误。您必须确保实际执行每个代码路径和所有重要数据路径,但当然,无论如何,您都要为严肃的项目执行此操作。我怀疑测试可以分配给给定变量的所有类很难。主要问题是习惯于C ++的人已经学会依赖编译器,并且不要努力避免编译器将捕获的大类错误。在Python中,您可以选择在编码时考虑它,或者等待测试运行以找出它。同样,如果你想找到所有的调用站点,那么“更改参数并查看无法编译的内容”的C ++“自动重构”操作需要在Python中进行一些修改。
因此,您必须确保运行正确的测试子集,因为大型Python应用程序的完整单元测试运行所需的时间远远超过当前C ++代码/编译的“编译”阶段所能接受的时间。 / code / compile / code / compile / test cycle。但这完全是同样的问题,因为不想在C ++中重建所有东西。
当实际上很难运行代码时(例如嵌入式设备,或者特别是无法在本地重现的奇怪的服务器环境),静态类型会获胜,因为在您遇到问题之前会发现更多错误串行电缆和rsync。但这就是为什么你想要一个模拟器而不管你正在编写什么语言,以及为什么对于严肃的服务器代码,如果开发人员的机器无法模拟生产,你就有一个合适的测试环境。
另外值得记住的是,许多C ++编译器错误和警告实际上并不是关于你的设计,他们认为有很多不同的方法来编写看起来正确的代码但行为完全错误。 Python程序员不需要警告他们不小心插入了三字符或者类型化了指针,因为他们没有精神病预处理器,或基于严格别名的优化。
答案 6 :(得分:1)
我和两个人一起工作过,大概都是十年左右。
我有点花费远更多时间尝试使静态类型语言了解我想要做的事情(可能是数周 - 可能是几个月)而不是我修复错误由动态类型错误引起的(可能一年一两个小时?)。
人们已经非常努力地获得证据证明其中一个或者另一个在程序员生产力方面更好,但是我最近的一篇评论表明,两者都没有强有力的证据。
静态类型分析在某些情况下很有用。我不认为它本身不应该用你的语言。它应该是您的交互式计算环境中的工具,以及您的测试,REPL,您的重构,您的文档,您的文字编码等。
静态类型系统可以让你思考有用的东西。在类似Classes和Monads的Haskell这样的语言中尤其如此(我承认我还没有真正得到)。这是一件好事,但我觉得相信它总是是一件好事是极权主义的。你应该在适当的时候考虑一下。一种语言不应该让你思考它,也不应该从开发开始就意识到这一点。
未完成图像的静态类型系统具有有限的表现力。为什么只是为了讨论类型而使用一种新的特殊领域特定语言将其烘焙到语言中?现在,您的语言设置了您可以访问的精确表达水平。想要更多?您需要重新编写代码或更新语言。想少点?你运气不好 - 用另一种语言。
相反,为什么不在需要时使用基本动态语言来描述类型和类型系统?作为一个图书馆。它更具表现力;更强大(如果愿意);更灵活;并且意味着较小的基本语言。
静态类型语言似乎鼓励样板或代码生成。我不确定这是否是固有的。也许一个足够强大的宏观系统会克服它。我将Swift测试的模拟状态与目标c的模拟状态进行了比较。
静态类型的语言似乎鼓励单一的应用程序 - 这是一种观点和观察,我无法支持,但似乎有......他们或他们带来的工具似乎鼓励单片应用程序和思维。
相比之下,在交互式计算环境中,您不构建新的应用程序,而是扩展系统以使其执行更多操作。我所知道的系统(Lisp机器,Smalltalk和Unix--它们之间的工具有一个动态类型的接口)使用动态类型将部件组装在一起。
我们应该构建一个整体的微小扩展,而不是开始构建新的整个应用程序,所以这种整体趋势(如果存在的话)是有害的。
最快的动态跟踪JIT编译器可以生成快速代码,而且它们仍然是一种相当年轻的技术。仍然 - 您也可以使用静态类型语言来完成此操作。
我怀疑从长远来看,我们最终会得到支持强大静态分析的环境,您可以在其中声明类型和协议,系统将帮助您查看是否满意,或帮助向您显示隐含类型。但是你不会需要来做到这一点。
答案 7 :(得分:0)
考虑你有一个带有一个参数的子程序的情况:
sub calculate( Int $x ){ ... }
现在您的要求发生了变化,您必须处理多个参数:
multi sub calculate( Int $x ){ ... }
multi sub calculate( Int @x ){
my @ret;
for @x -> $x {
push @ret, calculate( $x );
}
return @ret;
}
请注意,不同版本之间的变化非常小。
现在如果你发现你真的应该使用浮点数怎么办:
multi sub calculate( Num $x ){ ... }
multi sub calculate( Num @x ){
my @ret;
for @x -> $x {
push @ret, calculate( $x );
}
return @ret;
}
这是一个比以前更小的变化,请注意,调用这些子例程的任何代码都可以继续工作而不需要进行任何更改。
这些示例是用Perl6
答案 8 :(得分:-1)
我知道它已经有一段时间了但是接受的答案列出了不限于动态类型语言的属性。例如,#4(代码较少)也适用于Scala(如果我没记错的话)。对于Groovy(它建立在Java之上,因此技术上的groovy既是静态的又是动态的)确实如此。我同意的唯一一个是#7(韧性)
来自维基百科,
动态编程语言是一种高级编程语言,它在运行时执行静态编程语言在编译期间执行的许多常见编程行为。这些行为可以包括程序的扩展,添加新代码,扩展对象和定义,或者修改类型系统。动态编程器还可以包括动态类型。
根据我的经验,动态语言的优势在于更少的代码/更高效的代码和更好的“最佳”实践(如强大的测试文化)......不是特定于动态语言的东西。
说到测试文化,某些动态语言爱好者(特别是Ruby)声称他们编写的所有测试(测试感染)都允许他们轻松地重构应用程序。我倾向于不买这种说法 - 写得不好(非常,非常容易写)的测试往往会成为维护的噩梦。
总结一下:动态语言倾向于快速交付产品,应用程序可能很容易维护,也可能不容易维护,但对于高性能应用程序来说却很糟糕(静态编译的应用程序方式更快)