在 rails 上的 ruby 中创建和存储泛型方法

Creating and storing generic methods in ruby on rails

我正在 Rails 应用程序的 Ruby 中创建一个名为“print”的方法,它可以接受任何字符串并将其转换为 png。有人告诉我,为基础 ruby classes 制作 class 方法是不好的,比如 String 或 Array 或 Hash 等。所以 "some string to print".print 可能不是我应该做的做。

我正在考虑制作一个名为 Print (class Print < String) 的字符串的子class,并将其存储在我的 lib/assets 文件夹中。所以它看起来像:Print.new("some string to print")。所以我的问题是,我是否在正确的轨道上 1) 从 String 创建一个 sub-class 和 2) 将它存储在 lib/assets?

任何指导将不胜感激!

你的问题的答案必然是主观的,因为“我应该把功能放在哪里?”的答案总是很多,根据喜好、原则、习惯、习俗等。我将列出一些并描述他们,也许会加上一些个人的看法,但最终还是要你自己选择并接受后果。

注意:我通常指的是“丢失命名空间范围”或“与拥有全局方法一样糟糕”的常见退化情况。

Monkeypatch/Extend 字符串

以全局影响应用程序中的所有 String 为代价的方便且非常“面向对象的消息传递”风格。该成本可能很大,因为这样做会打破 Ruby 核心与您的应用程序之间的隐式边界,并且还会将“您的应用程序”的组件分散在外部位置。该功能将具有全局范围,最坏的情况是会无意中与其他不应发生的事情发生交互。

值得一提:Ruby 有一个改进功能,允许您执行“范围内的猴子修补”。

值得一提的 2:Ruby 还可以让您 includes 模块进入现有的 classes,例如 String.class_eval { include MyCustomization } 稍微好一点,因为它更容易告诉定制有制作完成和介绍位置:"foo".method(:custom_method).owner 将揭示它。正常的 Monkeypatching 将使它好像该方法是在 String 本身上定义的。

实用程序模块

通常在所有编程语言中完成,Util 模块只是一个名称空间,其中转储了 class methods/static 方法。这始终是避免全局污染的一个选项,但是如果 Util 最终到处都被使用并且它被不相关的方法填满,那么命名空间的价值就会丢失。在 Util 模块中使用方法往往意味着没有足够的思想来组织代码,因为如果没有维护,在最坏的情况下,它并不比使用全局方法好多少。

私有方法

假设您只需要一个 class -- 那么将它放入一个私有方法中就很容易了。如果你在很多 class 中需要它怎么办?您是否应该将其设为基 class 中的私有方法?如果该功能是 class 固有的,与 class 的身份相关联,那么是。如果使用得当,此消息存在的事实对于 class.

之外的组件是不可见的

但是,如果使用不当,这与 Rails Helper 模块具有相同的缺点。如果下一个添加的功能需要该功能,您将很想将新功能添加到 class 以便访问它。通过这种方式,class 的作用域会随着时间的推移而增长,最终在您的应用程序中变得接近全局。

辅助模块

许多 Rails 开发人员会建议将几乎所有这些实用方法放入 rails Helper 模块中。 Helper 模块介于 Utils Module 和 Private Method 选项之间。 Helpers 是 included 并且可以访问像 Private Methods 这样的 private 成员,并且他们建议像 Utils Modules 这样的独立性(但不保证)。由于这些属性,它们最终往往会无处不在,失去命名空间,并且最终会访问彼此的私有成员,从而失去独立性。这意味着它更强大,但很容易变得比独立的 class/static 方法或私有方法差得多。

创建 Class

如果以上所有情况都退化为“全局作用域”,如果我们通过新的class强行创建一个新的、更小的作用域怎么办?新 class 的目的将只是接收数据并在输出时根据请求进行转换。这是“创建许多小 classes”的常识,因为小 classes 的范围更小,更容易处理。

不幸的是,这种策略走得太远会导致有太多微小的组件,每个组件本身几乎没有任何用处。你避开了泥球,但你最终得到的是一团浓稠的汤,其中每一个微小的东西都与其他每一个微小的东西相连。它就像让全局方法相互关联一样复杂,而且你也好不了多少。

元选项:重构

考虑到以上所有选项都具有相同的退化情况,您可能会认为没有希望,一切最终都会变得可怕地全球化——这不是真的!重要的是要了解 它们都以不同的方式退化

也许功能 1、2、3、4...20 因为 Util 方法是一团糟,但它们作为功能 A.1 ~ A.20 在单个 class A 中紧密地工作。也许class B 完全是一团糟,在 class C 中分解为一个 Util 方法和两个私有方法效果更好。

作为一名工程师,您的崇高目标是将您的应用程序组织在一个配置中,避免系统中每一个功能的所有这些退化情况,使系统作为一个整体只变得尽可能复杂。

我的建议

我不了解你的域的完整上下文,而且你可能无法在 SO 问题中轻松交流,所以我无法确定什么最适合你。

但是,我要指出,组合 事物通常比将它们分开 更容易。我通常建议从 class/static 方法开始。将它放在 Util 中,稍后将其移动到更好的命名空间(Printer?)。或许在未来您会发现这些单独的方法中的许多经常对相同的输入进行操作,在它们之间来回传递相同的数据——这可能是 class 的一个很好的候选者。这通常比从 class 开始或继承其他 class 并稍后尝试拆分功能更容易。