【问题标题】:Can you have too much of “dynamic” in dynamic languages?你能在动态语言中有太多的“动态”吗?
【发布时间】:2009-12-09 20:53:44
【问题描述】:

在过去的几个月里,我一直在从 Java 过渡到 Groovy,我可以体会到它带来的许多好处:更少的代码、闭包、构建器、MOP,最终使像 Grails 这样的框架成为可能,在编写测试等。

但是,我的同事“指责”我的代码不够时髦。也就是说,我仍然为我的参数和字段声明类型,倾向于使用继承和多态而不是鸭子类型等。在我看来,在这些情况下,它不仅是动态与静态的,而且是动态与面向对象的范例一种困境。在这些情况下,我仍然倾向于选择 OO。我认为 OO 范式在其基本前提方面具有很大的价值,它允许您将代码构造抽象并与特定的现实世界概念相关联。

所以,这里有一些我需要帮助的特殊问题:

  1. 我应该为我的参数、字段等声明类型吗?

  2. 我应该在简单方法的情况下将代码块声明为闭包吗?

  3. 什么时候应该使用鸭子类型而不是多态动态调度。例如,在 groovy 中我可以做 animal."$action"() 或 def animal; animal.action() ,而不是 Animal animal = new Dog();动物.action()。我可以在 Open-Closed 原则的上下文中看到问题,但还有其他原因更喜欢 OO 风格的多态性吗?

  4. 什么时候应该在 groovy 中使用接口(如果有的话)?

我确信还有一些其他类似的困境我没有写下来。我还认为这些问题不仅适用于 groovy,而且适用于任何其他动态语言。 你有什么意见?

【问题讨论】:

  • 声明类型的另一个原因是在编写 SOAP Web 服务时,生成的 WSDL 可以包含一些类型信息...

标签: java groovy dynamic-languages paradigms


【解决方案1】:

这并不总是一种流行的观点,但我认为你的代码越明确越好。

我不喜欢让你猜测发生了什么的结构......

我在 Ruby 工作了一年,但我一点也不喜欢它。我并不是说它没有擅长的地方,我只是说我真的很喜欢保持干净和明确,并且不觉得 Ruby 有这个目标。

有一件事我确实弄清楚了——你的打字量并不等于整体开发速度。确实,包含大量重复代码的复杂代码库会导致开发速度非常慢,但简单地减少键入的内容而不消除重复是没有用的,键入更长、更清晰、更明确的代码通常会更快(超过项目的长度)而不是用简洁、不太正式的语言编写的相同代码。

如果您不认为打字与开发速度无关,那么下次发布项目时,请计算代码行数并除以所花费的人工天数(包括调试和测试)。换句话说,每天输入多少代码。你会发现结果是一个非常小的数字——实际上输入代码只是任何软件项目的一小部分。

【讨论】:

  • 我喜欢 C#(例如)采用的动态选择方法 - 尽可能静态,在需要或有明显好处时动态。
  • 大部分情况下,我认为您的代码取决于团队。一个好的团队可以用任何语言编写好的代码。一个糟糕的团队可以用任何语言编写糟糕的代码——但令人惊讶的是,糟糕的代码需要一个糟糕的团队、一种灵活的语言和一个非常有才华的程序员...... ” 或“富有表现力”的代码在他学会从下一个程序员的角度查看他的代码之前可能是一种语言可以做的最好的事情。
【解决方案2】:

我认为对于 Groovy,您应该支持最简单的做事方式,并且仅在情况需要时才使用 groovier 功能。 (就像在 Clojure 中编写宏或创建多方法时一样,如果您发现自己经常使用这些工具,您应该质疑自己。)您谨慎的方法对我来说似乎很好,可能您的同事对他们新发现的力量有点陶醉. (这不会是第一次。)

拥有像 Groovy 这样灵活的语言的好处是,您可以从谨慎的方法开始,就像您喜欢知道在需要时可以使用更强大的替代方案一样。你知道,“最简单的事情可能会奏效。”

更具体地说,更喜欢鸭子类型而不是接口,而不是为参数类型而烦恼似乎是一件好事,它可能会使为测试提供模拟变得容易得多。

【讨论】:

  • 我通常会在有意义的地方使用静态类型(我的代码设计用于特定情况,我不想提供任何进一步的保证),并允许在其他任何地方使用动态类型(或至少,就像我同意支持的那样充满活力)。这更多是一个问题,即您的代码“承诺”它所做的事情与它的所有潜在(错误|ab)用途。
  • 在你的签名中添加静态类型是“最简单的做事方式”吗?
  • @Chuck - 也许;约束可以极大地简化事情,因为当应用了约束时,您可以让编译器推断代码库中表示的类型,而不必将这些信息保留在您的脑海中。
【解决方案3】:

.1。我应该为我的参数、字段等声明类型吗?

我倾向于在用作公共 API 的一部分的类上声明类型,这是其他开发人员会大量使用的东西,或者我希望 IntelliJ 提供一些额外的自动完成帮助。否则我会“定义”事物。

.2。当简单方法可以使用时,我应该将代码块声明为闭包吗?

我使用方法,除非它是我计划作为变量传递的东西。尽管有 "foo.&bar" 方法解引用运算符,但大多数开发人员并不知道这一点,并且在遇到它时会被它弄糊涂。当一小段代码明确保留在更大的方法中而不是出于描述目的而放入它自己的方法时,我也会使用闭包。

.3。我什么时候应该使用鸭子类型而不是多态动态调度。例如,在 groovy 中我可以做 animal."$action"() 或 def animal; animal.action() ,而不是 Animal animal = new Dog();动物.action()。我可以在 Open-Closed 原则的上下文中看到问题,但是还有其他原因更喜欢 OO 风格的多态性吗?

我只在需要这种间接级别时使用 animal."$action"() 形式,因为方法名称会根据代码执行路径而变化(最常见于繁重的元编程期间)。我使用 Animal 动物 = new Dog();当我需要 IDE 的自动完成帮助时,或者该级别的文档有助于代码清晰(并且不会因可能明显或限制的额外冗长而受到伤害)时,请使用 animal.action()。

.4。我什么时候应该在 groovy 中使用接口(如果有的话)?

我很少使用它们。我可以看到将它们主要用作公共 API 调用的预期字段的文档,或者可能用作标记接口,以帮助从元编程的角度区分一组类。它们在 groovy 中的用处远不如在 java 中有用。

【讨论】:

    【解决方案4】:

    这取决于人们对什么感到满意。我喜欢使用类型声明和方法调用,因为我对 Java 很熟悉。我编写的代码必须由没有太多动态编程经验的人维护,所以我保持它接近普通 Java 代码,除非有充分的理由使用高级 groovy 功能​​。听起来您的团队应该创建编码标准,试图解释一般何时应该使用 Groovy 的特定功能。

    【讨论】:

    • 我必须恭敬地不同意。类似“whatever”的答案是非答案。未能将参数类型放入方法定义中会使代码更难被新的一双眼睛阅读。拥有编码标准很重要,但更重要的是拥有需要最佳编码实践的标准。最佳编码实践始终将代码可读性作为最重要的标准。
    【解决方案5】:

    有两种主要类型的面向对象语言。

    Simula 67 系列中的语言(例如 C++ 和 Java)支持静态类型变量、编译器和链接器以及方法 vtable。

    Smalltalk 系列中的语言(例如 Ruby)支持动态类型变量、解释和消息传递,而不是函数指针表。

    两者都是面向对象的,但在面向对象的概念上却截然不同。

    【讨论】:

      【解决方案6】:

      是的

      --

      没有

      你知道这个问题没有真正的答案吗?

      【讨论】:

      • 而我的应该是评论?
      • 我不认为所有的点都取决于个人喜好。例如 animal."$action"() 打破 OCP;一个足够喜欢多态性的理由。
      猜你喜欢
      • 2011-01-13
      • 1970-01-01
      • 2022-11-24
      • 2018-01-24
      • 2010-10-16
      • 1970-01-01
      • 2014-03-31
      • 1970-01-01
      • 2011-02-16
      相关资源
      最近更新 更多