ruby – “扩展自我”是实用程序模块的反模式吗?
史蒂夫·克拉夫尼克(Klabnik)最近在
pull request年的一个实用模块中说:
>创建实用程序模块(例如,为数学)时,声明方法的最佳方式是什么? 解决方法
他不会说1)为什么他认为这是一种反模式(除了模糊你所定义的课程方式的事实),或者2)为什么,考虑到这一点,这是一个例子他认为不应该使用它,所以很难专门反驳他的任何论点.
但是,我不相信延伸自我是一种反模式.一个实用程序模块似乎是一个很好的例子.我也使用它作为测试夹具的容易存储. 我认为值得研究什么是自我扩展,什么可能存在的问题,以及什么替代方案. 它是核心,它只是一种避免写自己的方式.在模块中的每个方法定义之前,您从未打算混合到一个类中,因此永远不会有自己创建的“实例”,所以可以通过定义只有“类”方法(如果您想要能够调用他们,就是). 它是否掩饰了您打算将方法用作类方法的事实?嗯,是的,如果你不看文件的顶部,它说,扩展自己,这是可能的.不过,我会认为,如果你有可能使这个混乱,你的课程可能太复杂了. 从你的班级 – 从它的名字和内容来看,它应该是很明显的 – 它是作为一个效用函数的集合.理想情况下,它不会比屏幕高出多少,所以延长自我几乎永远不会看不见.正如我们将看到的,替代品也遭受几乎完全相同的问题. 一种替代方案是使用类<<自己这样: module Utility class << self def utility_function1 end def utility_function2 end end end 我不是这个的粉丝,尤其是因为它引入了一个额外的缩进层.这也很丑(完全主观,我知道).它同样也遇到与“定义类”方法完全相同的问题. 您也可以使用此方法来定义类之外的实例方法<<自我阻挡 - 这可能导致这样的诱惑(尽管我希望它不会),所以我认为延长自我在这方面是优越的,消除了这种混乱的可能性. (当然,使用def self.utility_function的“长手”风格也是一样的.) 另一种方法可能是使用单例对象.我不认为这是一个好主意,因为一个单身对象是一个对象的原因 – 它的意图是保持状态和做事情,而且也是唯一存在的对象.这对于一个实用程序模块来说根本没有意义,它应该是一系列独立的无状态函数.你不希望MathUtils.cos(90)根据MathUtils的内部状态返回一个不同的值,对吧? (我知道你当然可以在一个模块中执行所有这些操作,但是对于我来说,它比一个技术方面更符合语义划分). 它也导致了同样的问题,可以说是模糊了这个方法被称为类方法(类)的事实.它们被定义为实例方法,并将它们称为实例方法,但首先通过调用类方法实例获取类的单个实例. class MathSingleton include Singleton def cos x end end MathSingleton.instance.cos x 为了这个目的,这将是一个可怕的替代方案.但是,看来,唯一表明这些方法将被用作单例实例的方法的只是一行刚刚在顶端,就像扩展自身一样. 那还有什么其他可能的缺点呢?我不知道有什么,但如果有其他人,我有兴趣听到他们. 我会认为,扩展自我导致更短的代码,从而避免了无关的自我,并允许您专注于其方法的名称和含义. 它还有一个很好的属性,如果你正在编写另一个使用很多实用功能的类,例如,你可以混合它们,并且它们将可用,而不必每次使用模块名称.很像静态导入工作在其他语言. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |