In general, monkey patching is never a good practice. However, I often use it for very special cases distinct to the application. In all other cases I'd prefer forking the gem or plugin and install the forked gem right into the gems folder of my application.
I'm also having a few tools modules which monkey patch some classes to inject special purpose behaviour into some standard classes for reuse in different application - but these are still special enough to not be useful to the public, or it is just infeasible to create forks.
So in the end it's a decision of specialization and compatibility. Always keep in mind that monkey patching is more likely going to break expected behaviour of other plugins or gems you may use in your project. This may become even more imminent after updating components in your working application ecosystem (or the outer supporting ecosystem, like Rails and its dependencies).
#lib/mongomapper_extensions.rb
module MongomapperExensions
module ProblemClassExensions
alias :old_problem_method :problem method
def problem_method
#guerilla code goes here!
end
end
end
class ProblemClass
include MongoMapperExtensions::ProblemClassExtensions
end
If you practice responsible duck punching, it can be as easy to support as a project specific local copy of a gem. It depends entirely on your diligence documenting upgrade problems with either solution. It's easy to say that either you or a support developer wouldn't recklessly replace that gem in vendor/gems a year from now, but it happens. Forking the project, patching it locally, and then submitting a pull request and having it make it back into the main gem is the ideal situation.
You need to stick to a couple of rules on duck punching though if you elect this route:
The patch has to sit in a blatantly obvious location. lib/[gem_name]_extensions.rb would be where I would first look as a support developer checking out a defect.
The patch should have a large amount of documentation surrounding it. It should outline potential upgrade nightmares.
The patch should be done on a different module that is then included into original module/class ActiveSupport style. This allows a support dev to call problem_method.ancestors and see a monkeypatch in progress.
This would be a way to do it in a way that keeps the old method around (for fun and games) and allows you to trace it more easily with a problem_method.ancestors().
#lib/mongomapper_extensions.rb
module MongomapperExensions
module ProblemClassExensions
alias :old_problem_method :problem method
def problem_method
#guerilla code goes here!
end
end
end
class ProblemClass
include MongoMapperExtensions::ProblemClassExtensions
end
发布评论
评论(2)
一般来说,猴子修补从来都不是一个好的做法。然而,我经常将它用于与应用程序不同的非常特殊的情况。在所有其他情况下,我更喜欢分叉 gem 或插件,并将分叉的 gem 直接安装到我的应用程序的 gems 文件夹中。
我还有一些工具模块,它们对一些类进行猴子修补,以将特殊目的行为注入到一些标准类中,以便在不同的应用程序中重用 - 但这些仍然足够特殊,对公众没有用处,或者创建它是不可行的叉子。
所以最终这是一个专业化和兼容性的决定。请始终记住,猴子修补更有可能破坏您可能在项目中使用的其他插件或 gem 的预期行为。在更新工作应用程序生态系统(或外部支持生态系统,如 Rails 及其依赖项)中的组件后,这种情况可能会变得更加紧迫。
In general, monkey patching is never a good practice. However, I often use it for very special cases distinct to the application. In all other cases I'd prefer forking the gem or plugin and install the forked gem right into the gems folder of my application.
I'm also having a few tools modules which monkey patch some classes to inject special purpose behaviour into some standard classes for reuse in different application - but these are still special enough to not be useful to the public, or it is just infeasible to create forks.
So in the end it's a decision of specialization and compatibility. Always keep in mind that monkey patching is more likely going to break expected behaviour of other plugins or gems you may use in your project. This may become even more imminent after updating components in your working application ecosystem (or the outer supporting ecosystem, like Rails and its dependencies).
如果您练习负责任的鸭子打孔,那么它可以像支持宝石的特定于项目的本地副本一样容易。这完全取决于您对任一解决方案的升级问题进行记录的努力。很容易说,一年后您或支持开发人员都不会鲁莽地替换供应商/宝石中的该宝石,但这种情况确实发生了。分叉项目,在本地修补它,然后提交拉取请求并将其返回到主 gem 中是理想的情况。
如果你选择这条路线,你需要遵守一些关于鸭子拳击的规则:
这将是一种保留旧方法(为了乐趣和游戏)并允许您使用 Problem_method.ancestors() 更轻松地跟踪它的方法。
If you practice responsible duck punching, it can be as easy to support as a project specific local copy of a gem. It depends entirely on your diligence documenting upgrade problems with either solution. It's easy to say that either you or a support developer wouldn't recklessly replace that gem in vendor/gems a year from now, but it happens. Forking the project, patching it locally, and then submitting a pull request and having it make it back into the main gem is the ideal situation.
You need to stick to a couple of rules on duck punching though if you elect this route:
This would be a way to do it in a way that keeps the old method around (for fun and games) and allows you to trace it more easily with a problem_method.ancestors().