Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JVM: most simple way to alter code of a dependency library?

Most of the time, I don't like Javascript and would prefer strict and compiled languages like Scala, Java, Haskell...

However, one thing that can be nice with Javascript is to be able to easily change code of external dependencies. For exemple, if you have a bug and you think it's one of your dependency library you can easily hack around and swap a library method by your own override and check if it's better. You can even add methods to Array ou String prototypes and things like that... One could even go to node_modules and alter the library code here temporarily if he wants to.

In the JVM world this seems to me like an heavy process to just get started:

  • Clone the dependency sources
  • Hack it
  • Compile it
  • Publish it to some local maven/ivy repository
  • Integrate the fixed version in your project

This is a pain, I just don't want to do that more than once in a year Today I was trying to fix a bug in my app, and the lib did not provide me enough information. I would have loved to just be able to put a Logger on one line of that lib to have better insight of what was happening but instead I tried to hack with the debugger with no success (the bug was not reproductible on my computer anyway...)

Isn't there any simple alternative for rapidly altering the code of a dependency?

I would be interested in any solution for Scala, Java, Clojure or any other JVM language.

I'm not looking for a production-deployable solution, just a quick solution to use locally and eventually deployable on a test env.

Edit: I'm talking about library internals that are not intended to be modified by the library author. Please assume that the class to change is final, not replaceable by library configuration, and not injectable by any way into the library.

like image 572
Sebastien Lorber Avatar asked Nov 01 '22 09:11

Sebastien Lorber


1 Answers

In Clojure you can re-bind vars, also from other namespaces, by using intern. So as long as the code you want to alter is Clojure code, that's a possible way to monkeypatch.

(intern 'user 'inc dec)
(inc 1)
=> 0

This is not something to do lightly though, since it can and will lead to problems with other code not expecting this behavior. It can be handy to use during development to temporarily fix edge cases or bugs in other libraries, but don't use it in published libraries or production code.

Best to simply fork and fix these libraries, and send a pull request to have it fixed in the original library.

When you're writing a library yourself that you expect people need to extend or overload, implement it in Clojure protocols, where these changes can be restricted to the extending/overloading namespaces only.

like image 56
NielsK Avatar answered Nov 09 '22 13:11

NielsK