关于Ruby模块的简单介绍

48 阅读3分钟

模块对于高度专业化的代码来说是非常有用的,它可以被注入到其他类中以获得乐趣和利益,或者用于创建命名空间。 一个有趣的方法是使用模块作为经典继承的替代品(没有通常的权衡):其核心思想是共享一个抽象的角色,可以包含在一组不同的类中。

我们应该从角色这个词的最简单的定义开始。

一个人或事物在特定情况下承担的功能或扮演的角色。

"......或事物在特定情况下"是这里的关键,那么我们如何以面向对象的方式特定情况进行编码?我们创建类:蓝图,以后我们可以随意地实例化和使用。下一步:一个事物所承担的功能,即一个被定义好的功能,在特殊情况下被对象使用;更确切地说,不同的对象开始扮演一个共同的角色,当这种情况发生时,很明显,共同的行为可以被提取到一个模块中。

关注点是一个很好的抽象,它简化了使用模块的共享行为。它可以在ActiveSupport::Concern中找到,它只是去掉了一些模板代码,例如.NET:

def self.included(base)
  base.extend ClassMethods
  base.class_eval do
    # ...
  end

  module ClassMethods
    # ..
  end
end

tl;dr : 当我们在一个类中做类似include MyModule 的事情时,included 被调用,base 参数是我们包含模块的对象,即一个Class实例(记住,Ruby中的类是Class的实例--有趣的是,Class的类又是Class,所以一路下来都是乌龟)。

抽象后的代码看起来像这样:

module M
  extend ActiveSupport::Concern
  included do
    # ...
  end

  module ClassMethods
    # this gets included automatically 
  end
end

有点干净,但经典的方式也不坏,只要你知道实际发生了什么。我们都喜欢Rails的 "魔力",但也可以说,在不知道背后发生了什么的情况下使用它是一种徒劳的行为。

回到我们的关注点:我喜欢的是它如何轻松地解决依赖关系--人们可以进一步思考源码--那里正在进行一些有趣的编码。

关注点的一些简单用途?人们可以用它们来应用 提取方法 重构,即 "可以归类的代码片段"。在这篇37signals文章,我们有一个简单的before过滤器的例子,可以做一些cookie的混合。这里唯一的问题是,把before过滤器从控制器中拿出来可能会导致一些难以调试的代码,可以说看到每个控制器的所有过滤器需要的精神转换比解析include Ajax -> "哦,等等,这设置了一个before过滤器"。

一些更好的用法可以在DHH的这篇高度引用的文章中找到:"用关注点来减肥 ",例如,Taggable、Visible和Dropboxed是可以被注入其他类中的功能簇,这样它们就可以共享一个共同的角色。

下一站是DCI范式 ,从鸟瞰来看,这是一种更正式的使用/共享角色的方式,也包括一个用于组织代码的思维框架的支架。我将在一个新的帖子中详细介绍这些细节。