2

When defining a module in Ruby, I have seen examples where the module expects the class(es) it is to be included in to have particular definitions and functionality.

For example, the module might call a method that itself doesn't contain expecting that the class its included in contains that method definition.

To me, this is a different paradigm from my background of strongly typed languages lacking the ability to include an arbitrary set of logic (Ruby as a whole is a totally different paradigm for that matter).

Is this an acceptable style per the ruby standards or at least seen often enough in mature code-bases that be considered "ok"?

I realize this is a somewhat subjective question, however I'm looking to see if this is something that occurs often enough that one would be considered within the "norm" if they were to construct a module as such.

4

2 回答 2

2

由于 Ruby 的类型非常松散,更多地依赖于响应方法的能力,即所谓的鸭子类型,而不是类,因此很难对这些事情负责。

如果你的模块包含在一个不兼容的上下文中,那么你作为一个模块的工作就不是对它做任何事情。您无法提前知道任何给定的方法调用是成功还是失败,因为在包含您的模块之后,可能会发生其他事情,这会使进行某种验证为时过早。

鉴于这些限制,重要的是要尝试构建事物以避免这种歧义。

Enumerable为例。为了使其在包含时正常工作,必须在包含它的上下文中定义许多方法。如果这些没有定义,模块将无法工作,但是这个失败的责任不是 Enumerable,而是包含它的模块。

基本上,在您之前,include SomeModule您应该确定包含该模块的依赖项(如果有)得到满足。作为包含者,您还对由此可能导致的任何冲突承担全部责任。

其他语言有更严格的方法来验证完整性,例如 Objective C 的协议特性或 C++ 中基类的存在。由于 Ruby 没有这个,为了确保一切正常工作,使用了自动化测试套件。您可能会注意到 Ruby 社区非常面向测试,而这种模棱两可是导致这种情况的众多原因之一。

于 2013-05-03T00:29:56.963 回答
1

是的,这是可以接受的。你经常看到这种事情,即使在核心库中,也有诸如Comparable和之类的模块Enumerable,它们都希望在包含类中实现某些方法。

这种期望可以与 Java 中的接口进行比较,只有鸭子类型与结构类型。

除了这些广泛适用的模块之外,您还可以看到很多复杂的类被分解成更小的模块化关注点。模块仍然希望在包含类的上下文中运行,但是代码被分解成多个部分,使关注点保持可插入性,并且包含类的大小更易于管理。

这种模式:

lib/
  someclass.rb
  someclass/
    concern_a.rb
    concern_b.rb

... where concern_aand concern_bare modules included in someclass, 很常见,而且我认为它足够直观,您不会想知道其中的方法在concern_a做什么。

当然,这种灵活性并非没有代价。特别是在 Rails 中,考虑到大量动态定义的方法(避开 grep)和神奇的自动加载,有时很难找到您正在寻找的代码,尤其是在处理您继承的不那么出色的遗留代码时,例如。

于 2013-05-03T00:37:43.000 回答