4

我从 Ruby 编程语言开始,我有兴趣在开始研究 Rails 框架之前深入了解它。

我目前有点失望,因为每个人都只关心 Rails 框架,而语言的其他方面只是没有深入讨论,例如它的类加载机制。

考虑到我是从做一些桌面/控制台实验开始的,我想更好地理解以下事项:

  1. 将每个 Ruby 类放在一个单独的 Ruby 文件中是一种好习惯吗?(*.rb)
  2. 如果我有,假设.. 10 个类.. 并且它们都相互引用,通过实例化彼此并调用彼此的方法,我是否应该在每个文件中添加一个“require”语句来说明该类需要哪些类在那个文件里?(就像我们在每个 Java 类文件中使用“导入”语句一样?)
  3. 在类声明之前或之后(内部)放置“require”语句有区别吗?
  4. 什么可以被认为是合适的 Ruby 程序的“入口点”?在我看来,任何 .rb 脚本都足够了,因为该语言没有像 C 或 Java 这样的约定,我们总是需要方法的“主要”函数。
  5. 类加载是否被视为 Ruby 程序执行中的“阶段”?我们是否应该在一开始就加载应用程序所需的所有类?
  6. 当我们运行需要它们的代码时,解释器本身不应该负责查找和加载类吗?通过搜索 $LOAD_PATH 变量中的路径,就像 Java 使用 $CLASSPATH 一样?

谢谢你。

4

3 回答 3

5

一般来说,.rb为每个 Ruby 类创建一个单独的文件是一种很好的做法,除非这些类具有实用性并且太琐碎而不能保证分离。这种情况的一个实例是自定义的 Exception 派生类,将其放在单独的文件中会比它的价值更麻烦。

传统认为​​类的名称和文件名是相关的。在调用类的地方,调用ExampleClass文件example_class,相同的“下划线”版本。有时你会违反这个约定,但只要你对此保持一致,就不会有问题。如果您遵循惯例,Rails ActiveSupport 自动加载器将帮助您很多,所以很多人都遵循这种做法。

同样,您需要将应用程序组织到文件夹中,lib并将bin命令行脚本与后端库分开。命令行脚本通常没有.rb扩展名,而库应该有。

当涉及到 时require,应该谨慎使用。如果你正确地构建你的库文件,一旦你调用require了顶层文件,它们都可以自动加载。这是通过该autoload功能完成的。

例如,lib/example_class.rb可能看起来像:

class ExampleClass
  class SpecialException < Exception
  end

  autoload(:Foo, 'example_class/foo')

  # ...
end

您可以在单独的目录或文件下组织其他内容,例如lib/example_class/foo.rb可能包含:

class ExampleClass::Foo
  # ...
end

您可以一直保持链接autoloads。这样做的好处是只加载实际引用的模块。

有时您会希望将 a 推迟require到类实现中的某个地方。如果您想避免在一个繁重的库中加载,除非使用特定功能,否则此功能很有用,在一般情况下不太可能使用此功能。

例如,您可能不想加载 YAML 库,除非您正在进行一些调试:

def debug_export_to_yaml
  require 'yaml'

  YAML.dump(some_stuff)
end

如果您查看常见 Ruby gem 的结构,“入口点”通常是库的顶层或包含此库的实用程序脚本。因此,举个例子ExampleLibrary,您的切入点lib/example_library.rb将被构造为按需包含其余部分。您可能还有一个脚本bin/library_tool可以为您执行此操作。

至于什么时候加载东西,如果有很大的机会被使用,那就提前加载它以早点付出代价,即所谓的“急切加载”。如果它被使用的可能性很小,请按需加载它,或者将其“延迟加载”,因为它被称为。

查看一些简单但流行的 gem 的来源,以了解大多数人如何构建他们的应用程序。

于 2013-04-18T21:06:22.797 回答
1

我将尝试帮助您解决第一个问题:

  1. 将每个 Ruby 类放在一个单独的 Ruby 文件中是一种好习惯吗?(*.rb)

归结为这些类的相关程度。让我们看几个例子。看这个类:https ://github.com/resque/resque/blob/master/lib/resque.rb ,它"imports"是几个类的功能,虽然它们一起工作,但它们并没有密切相关,可以捆绑在一起。

另一方面,看看这个模块:https ://github.com/resque/resque/blob/master/lib/resque/errors.rb 。它捆绑了 5 个不同的类,但它们确实属于一起,因为它们本质上都代表相同的。

此外,从设计的角度来看,一个很好的重击规则可能会问自己,还有谁在使用这个类/功能(意味着代码库的哪些其他部分需要它)?

假设您要代表 aClick并由WheelScrolla 执行Mouse。在这个简单的示例中,将这些类捆绑在一起会更有意义:

module ComputerPart
   class Mouse; end
   class WheelScroll; end
   class Click; end
end

最后,我建议您仔细阅读其中一些流行项目的代码,以了解社区通常如何做出这些决定。

于 2013-04-18T21:10:59.147 回答
0

1.)我遵循这种做法,但这不是必需的,如果需要,您可以将一堆类放在一个文件中。

2.)如果类在同一个文件中,不,当您运行脚本时它们都可以访问。如果它们位于单独的文件中,那么您应该要求它们,您还可以要求文件(self)所在的整个目录。

3.)是的,它应该在文件的顶部。

4.) 在 ruby​​ 中,一切都来自 Main 对象,解释器只是为您处理创建它。如果您正在编写 OO ruby​​ 而不仅仅是脚本,那么入口点将是您调用的第一个类的 init 方法。

5.) 是的,在程序运行之前,它会加载所有依赖项。

6.) 我认为它可以做到这一点,您所要做的就是在文件顶部需要正确的文件,之后您可以根据需要使用它们,而无需再次隐式加载它们。

于 2013-04-18T21:00:57.267 回答