Dav*_*man 9 ruby encapsulation monkeypatching
在Ruby中,程序员可以更改预定义的类.所以一个非常糟糕的程序员可以做类似的事情:
class String
def ==(other)
return true
end
end
Run Code Online (Sandbox Code Playgroud)
显然,几乎没有人会这么愚蠢,但是对于预定义类的更微妙的改变可能会导致已经工作的代码出现问题的想法在我看来违反了封装原则.
四个问题:
我知道这是一个有点主观的问题,但我真的想知道更广泛的编程社区对这个所谓的"猴子修补"的看法.
Jör*_*tag 10
首先,这实际上是否违反了OO封装原则?
是.
第二,作为一名程序员,我是否有办法在我的代码中保证我正在使用未修改版本的类?
还没.Ruby 2.0中的类框(希望)将成为解决方案.
第三,我是否应该出于任何原因在我的代码中"打开"类?
只作为最后的手段.
你永远不应该修补自己的课程.没有意义.你控制它们,你可以让它们做你想做的事情.
你永远不应该在库中修补类.(这个规则的例外是图书馆,其唯一的目的是修补一些东西,例如Marc-AndréLafortune的backports图书馆,它修补了Ruby 1.8.6,1.8.7,1.9.0 和1.9.1. Ruby 1.9.2中可能提供的功能.)您可以提供一个附加库,它提供了猴子补丁,使您更容易使用您的库(例如,您有一个加密库,它提供了一种Kryptonite.encrypt(str)方法,并且您提供了一个附加组件String#encrypt方法),但该附加组件应位于用户需要显式 的单独库中require.它应该是完全可选的.
你不应该修补核心类.这是指像类Array或SymbolRuby中,但对于Rails的图书馆,我也包括类,如ActiveRecord::Base在"核心"的标签.(与上面的注意事项相同.例如,在3.0之前的Rails版本中,没有明确定义的插件API,猴子修补是扩展Rails 的唯一方法.如果没有违反此规则的人,就永远不会有任何插件,并且Rails永远不会像现在这样.)
首先尝试继承.首先尝试合成(包装,代理,外观,适配器......).首先尝试重构.首先尝试辅助对象.只有当它不起作用时,转向猴子修补.
猴子补丁时要尊重:如果你要添加一个新方法,请确保它不存在,如果确实存在则处理它(例如从你的方法调用它).如果你要包装一个现有的方法,请确保如果其他人已经包装它,它们的包装器会被调用,并且当有人想要在之后包装它时,你的包装器允许这样做.(特别是,这意味着您必须保留方法的现有合同.)
如果可能的话,将你的猴子补丁放入混合物中.这样,它们就会出现在继承链中,这将使任何试图调试代码的人有机会弄清楚发生了什么.将您的猴子补丁放在单独的,明显命名的文件中.
最后,在大规模的生产编码环境中如何处理这类事情?换句话说,编程行业的人们是否真的在其他人会使用的代码中执行此操作?或者即使他们不这样做,你如何确保一些插件作者在某个地方没有做到这样会破坏你程序的重要部分呢?
不要像"真正糟糕的程序员"那样工作,就像你打电话给他们一样.
这听起来很简单,这基本上就是归结为它.是的,当然,您可以编写测试,执行代码审查,练习结对编程,使用静态分析工具,在启用警告的情况下运行代码(例如,您在问题中发布的代码将生成代码warning: method redefined; discarding old ==).但是对我而言,无论如何,这都是一个非常糟糕的程序员所做的事情.
| 归档时间: |
|
| 查看次数: |
734 次 |
| 最近记录: |