To (monkey)patch or not to (monkey)patch, that is

2019-04-26 16:01发布

问题:

I was talking to a colleague about one rather unexpected/undesired behavior of some package we use. Although there is an easy fix (or at least workaround) on our end without any apparent side effect, he strongly suggested extending the relevant code by hard patching it and posting the patch upstream, hopefully to be accepted at some point in the future. In fact we maintain patches against specific versions of several packages that are applied automatically on each new build. The main argument is that this is the right thing to do, as opposed to an "ugly" workaround or a fragile monkey patch. On the other hand, I favor practicality over purity and my general rule of thumb is that "no patch" > "monkey patch" > "hard patch", at least for anything other than a (critical) bug fix.

So I'm wondering if there is a consensus on when it's better to (hard) patch, monkey patch or just try to work around a third party package that doesn't do exactly what one would like. Does it have mainly to do with the reason for the patch (e.g. fixing a bug, modifying behavior, adding missing feature), the given package (size, complexity, maturity, developer responsiveness), something else or there are no general rules and one should decide on a case-by-case basis ?

回答1:

Patching is the "right thing" to do for a reason: With open source software, if you've discovered a genuine bug, or need a feature that you suspect others may need as well, patching and submitting the patch upstream is a way to give back to the community, and contribute to making the software better, as a whole. If the patch is accepted, it's a free +1 to you or your company's reputation. Nobody was ever sad because they had too many examples of useful, open source code they've contributed to the community on their resume ...

Not that we always do the right thing, at the time, in the trenches. But if we're going to have an abstract discussion about best practices, if seems that the right order of precedence would be "patch and submit" > clever workaround > finding a package that works better > ugly monkeypatch ;-)



回答2:

One piece of information we're missing is whether the unexpected behaviour you describe is a bug, pure and simple, or if it's behaviour some consumers of the package want.

As has been stated by others here, it's the trade off of risk and effort. I can't make any definite assertions without knowing your specific circumstances.

However my gut feeling is that patching and push upstream will result in less risk and effort in the long run, assuming you think your patch will be accepted. Regardless of whether you hard patch or monkeypatch, you're going to have a cost from it - every time you update the version of the package you use, you're going to have to test your patch still works, and possibly update it depending on the changes in the package. With a hard patch, you're going to have also have to reapply the patch, but that'll be less work than the testing/updating you'll need to do with either option, most likely.

There are two wins for patching in this scenario, as I see it.

If you forgot about the patch when you upgrade, with a hard patch, your patch will disappear entirely, causing a catastrophic and visible failure, most likely. Whereas with a monkey patch, your patch will still be there, but you will not have tested it still has the same effect, which to my mind is a much more dangerous state of affairs than the hard-patch being missing entirely.

The other win for hard patching is that, with a hard patch, eventually it should be integrated in the package, and the cost disappears. Whereas a monkey patch will hang around indefinitely, until the issue is somehow resolved independently.

If the unexpected behaviour is something other package consumers want, and not simply a bug, this complicates the picture I paint. In this case the monkey patch solution would simply have to remove the behaviour. The hard patch, however, would have to maintain the behaviour for those who want it.

This analysis ignores any moral obligations you may have to the package maintainers and other consumers.

Also, I'm philosophically opposed to the whole concept of monkey patching, but that's not relevant to this discussion :-)



回答3:

in my opinion:

If 'unexpected/undesired behavior' != bug, then monkeypatching (or duckpunching) would be indicated.

If you believe it to be a bug in the lib, the hard patching and pushing the patch upstream makes sense.

If I understand you definition of 'working around' to be adding complexity to your app to compensate for a lib behavior, I would have to say that monkeypatching is definitely a better idea.

my .2 pesos.



回答4:

Well, it's the fairly classical risk vs benefit.

Is the patch risk-free? and heavy in benefits? monkeypatch it. If there is a bit of risk, and only a bit of benefit, I'd not monkeypatch it, and just plug the fix into your typical release process.