【问题标题】:Early binding vs. late binding: what are the comparative benefits and disadvantages?早期绑定与后期绑定:比较优缺点是什么?
【发布时间】:2008-12-15 03:32:03
【问题描述】:

在讨论计算机语言的演变时,Alan Kay 说他的 Smalltalk 的一个最重要的属性是后期绑定。它赋予了语言延展性和可扩展性,并允许随着时间的推移重构不适当的耦合。你同意?早期绑定是否有补偿性优势,可以解释为什么它似乎是两种范式中的主导领域,其中任何一个都可以使用?

我的个人经验(不够广泛或深度不足以成为权威),基于使用 javascript、jQuery、jsext、actionscript、php、java、RoR 和 asp.net 实现 Web 应用程序似乎表明后期之间存在正相关关系绑定和膨胀减少。我确信早期绑定有助于检测和防止一些类型安全错误,但自动完成和良好的 IDE 以及一般的良好编程实践也是如此。因此,在我的风险规避方面恢复我的理性观点之前,我倾向于抓住自己支持后期绑定方面。

但我真的不知道如何权衡取舍。

【问题讨论】:

  • 需要考虑的是,很多语言都提供这两种语言,包括 VB、Objective-C、C++/COM 和 C#。

标签: smalltalk late-binding early-binding


【解决方案1】:

根据我对高性能软件(例如游戏、数字运算)和性能中立软件(网站、大多数其他软件)的经验,后期绑定有一个巨大优势:您提到的延展性/可维护性/可扩展性。

早期绑定有两个主要好处。第一个:

  • 运行时性能

被普遍接受,但通常无关紧要,因为在大多数情况下,将硬件投入到问题上是可行的,这样更便宜。当然,也有例外(例如,如果您不拥有正在运行的硬件)。

早期绑定的第二个好处:

  • 易于开发

似乎被低估了。在开发人员与其他人的组件一起工作的大型项目中,IDE 可以读取早期绑定并使用它们来通知开发人员(通过自动完成、文档等)。这对于后期绑定不太实用,因为绑定是在运行时创建的。如果 IDE 可以从代码中推断结构定义,那么后期绑定语言仍然是可能的,但是由于结构总是可以在运行时更改,所以它不是那么可靠。

易于开发是一件大事。它最大限度地减少了昂贵的程序员时间——而且你的开发团队越大,它就变得越重要。您需要在这一点与后期绑定语言所获得的灵活性之间取得平衡。

【讨论】:

  • 我认为早期绑定的语言实际上更难开发。虽然它们确实从使用编译时信息的工具中获得了优势,但它们也遭受了诸如冗长和冗余之类的损失,以及大量语言复杂性以适应偶尔的动态类型,同时仍符合类型系统的约束。例如。泛型是一个很棒的语言特性,但也是一个相当复杂的问题。动态语言不需要这样的特性,因为无论原作者是否有意,一切都是通用的,不需要任何额外的语法。
【解决方案2】:

传统上,早期绑定的一大优势在于性能:后期绑定语言必须在运行时携带有关其所有数据的类型信息,并且失去了在编译时进行一些优化的机会。不过,随着计算机速度越来越快,以及虚拟机在动态优化方面变得越来越聪明,这种差异已经变得不那么显着了。

【讨论】:

  • 那么您认为我们会越来越多地转向后期绑定语言吗?或者现有的语言会从早到晚发生变化?后期绑定 java 和 C# 是合理的概念吗?
  • @[le dorfier]:硬件越来越快,因此开销变得不那么重要
  • 我知道。但这是所有语言都没有后期绑定的唯一原因吗? 20 年前,Smalltalk 的速度几乎可以接受——现在应该很快,但它并不占主导地位。特别是,我们仍然为早期绑定的 C# 和 java 作为大多数新的非 Web 应用程序的选择语言而背负着沉重的负担。
  • 并且 JITter 将允许一些方法调用/消息发送变成(几乎)早期绑定调用。
【解决方案3】:

Late-binging 允许正在运行的系统扩展自身。例如,系统启动时知道 Wolves。随着时间的推移,evolveDometicate() 方法在 Wolf(?) 中旋转了一个名为 Dog 的新类并将其实例化,现在我们有了 Dogs。 Smalltalk 将保存整个 SYSTEM 映像,因此如果您将其关闭并重新启动,Dogs 将在重新启动后仍然存在。一旦你进化到在特定硬件上运行并连接到网状网络中的对象,整个生态系统就不会真正关闭(直到 Sun 崩溃)。我想这就是艾伦凯所说的后期绑定的优势,成为神。

【讨论】:

    【解决方案4】:

    早期绑定与后期绑定实际上是语言架构的一个功能。早期绑定意味着可以在机器指令跳转到某个地址并从那里开始执行的地方构建代码(可能通过查找表)。后期绑定需要为每次访问查找符号和类型引用(通常是哈希表查找),这会降低语言速度。

    虽然一些基于 VM 的语言(例如 Java)是早期绑定的本地机器代码,但实际上只能直接进行早期绑定。要进行后期绑定,它必须进行与动态语言解释器相同的哈希查找。然后,后期绑定需要执行一段代码来获取地址(这就是 OLE 自动化的工作方式)。它不能直接由 CPU 完成 - 必须执行代码。

    请注意,执行后期绑定的代码实际上将在哈希查找函数等中拥有自己的早期绑定分支目标。因此,从这个角度来看,任何要由 CPU 直接执行的代码都需要早期绑定。后期绑定必须在软件中完成。

    对于相当广泛的代码优化,提前绑定也是必要的。

    C 之类的架构在编写接近于金属的代码方面有一个最佳点,可以说是。在您想要执行此操作的地方,早期绑定方面几乎是语言体系结构所固有的。在 Python 等后期绑定语言中,后期绑定也是固有的。有些语言两者都提供,但使用的特定类型将与正在执行的特定构造相关联。

    【讨论】:

    • 低级语言也可以简单地进行后期绑定。这是因为您只需在最近绑定后通过哈希查找填写跳转表。之后,您可以通过跳转表简单地调用最近绑定的函数,这是低成本的。所以只有一次性后期绑定过程需要时间。
    【解决方案5】:

    我认为有更好的方法/模式来避免不适当的耦合,例如控制反转、依赖注入、工厂......

    但是,我喜欢后期绑定的“易用”版本独立性
    只需使用

    var excel = CreateObject("Excel.Application");
    

    Late binding 会弄清楚,什么样的 Excel.Application,以及从哪里获取它...

    【讨论】:

      【解决方案6】:

      在编译期间执行链接的编译时绑定称为早期绑定

      动态绑定,其中在调用函数时执行期间执行的函数链接称为后期绑定

      【讨论】:

      • 比这更复杂。 DLL 不会在运行时链接,但在大多数 情况下(GetProcAddressdlsym 除外),这仍被视为早期绑定。
      猜你喜欢
      • 2013-02-08
      • 1970-01-01
      • 2016-12-15
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-17
      相关资源
      最近更新 更多