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



我正在RubyonRails应用程序中制作一个名为";打印";它可以接受任何字符串并将其转换为png。有人告诉我,为String、Array或Hash等ruby基类创建类方法是不好的,所以"some string to print".print可能不是我应该做的事情

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

如有任何指导,我们将不胜感激!

你的问题的答案必然是主观的,因为"总是有很多答案;我应该把功能放在哪里&";,根据偏好、原则、习惯、习俗等,我会列出一些并描述它们,也许还会添加一些我的个人意见,但最终你必须选择并接受后果。

注:我通常指的是";失去名称空间作用域";或";与具有全局方法一样糟糕";。

Monkeypatch/Extend字符串

方便且非常";OO消息传递";以全局影响应用程序中的所有String为代价。这种成本可能很大,因为这样做打破了Ruby核心和应用程序之间的隐含边界;您的申请";在外部的地方。该功能将具有全局范围,最坏的情况是会无意中与其他不该交互的东西交互。

值得一提的是:Ruby有一个Refinements功能,可以让你做";scoped monkeypatching";。

值得一提的是2:Ruby还允许您将includes模块放入现有的类中,比如String.class_eval { include MyCustomization },它稍微好一点,因为它更容易判断定制已经完成以及它在哪里引入:"foo".method(:custom_method).owner会显示它。普通的Monkeypating会让它看起来像是在String本身上定义的方法。

Utils模块

Util模块通常在所有编程语言中完成,它只是一个类方法/静态方法转储的单一命名空间。这始终是避免全球污染的一种选择,但如果Util最终在任何地方都被使用,并且被不相关的方法填满,那么名称空间的价值就会丧失。在Util模块中有一个方法往往意味着没有对组织代码进行足够的思考,因为在没有维护的情况下,最坏的情况是,它并不比有全局方法好多少。

私有方法

假设您只需要在一个类中使用它,那么很容易将它放入一个私有方法中。如果你在很多课堂上都需要它怎么办?是否应该将其作为基类中的私有方法?如果功能是类固有的,与类的标识相关联,则为"是"。如果使用得当,则该消息的存在对于该类之外的组件是不可见的。

然而,如果使用不正确,这与Rails Helper模块有相同的缺点。如果下一个添加的功能需要该功能,你会很想将新功能添加到类中以便访问它。这样,类的范围会随着时间的推移而扩大,最终在你的应用程序中变得接近全局。

Helper模块

许多Rails开发人员会建议将几乎所有这些实用程序方法都放在railsHelper模块中。Helper模块介于Utils Module和Private Method选项之间。帮助者包括,并可以访问私有成员,如private Methods,他们建议像Utils模块一样独立(但不保证)。由于这些属性,它们最终往往会出现在的任何地方,失去名称空间,并最终访问彼此的私人成员,失去独立性。这意味着它更强大,但很容易变得比独立的类/静态方法或私有方法糟糕得多。

创建类

如果以上所有情况都退化为";"全局范围";,如果我们通过一个新类的方式强行创建一个新的、更小的作用域会怎样?新类的目的只是接收数据,并在输出时根据请求进行转换。这就是";创建许多小类";,因为小类将具有较小的作用域,并且将更容易处理。

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

元选项:重构

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

也许作为Util方法的功能1、2、3、4…20是一个完整的烂摊子,但它们在单个类a中作为功能a.1~a.20协同工作。也许类B是一个完全烂摊子,在类C中分解为一个Util方法和两个私有方法效果更好。

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

我的建议

我没有你的领域的完整背景,你可能无论如何都无法在SO问题中轻松沟通,所以我不能确定什么对你最有效。

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

最新更新