aka: Are Extension Methods stable enough for productive use?
Hi,
one of the features I miss the most in good old Java is extension methods. Although in the end it's just syntactic sugar, it is such incredible useful syntactic sugar, that I really don't know how anyone can live without it.
So I was incredible excited when I found that Lombok provides exactly those. And it works in Eclipse, which unfortunately is the IDE I am stuck with for historical reasons.
So why am I writing this post? Well, after almost two months now of playing around with Lomboks extension methods, I wonder, is this really something which is ready to be used for real development?
I ask for the following three reasons:
a) It is still in experimental. And has been there for a long time, and it doesn't look like it's being promoted anytime soon. Not a good sign.
b) Nobody seems to be using it. Given how useful it is, one would think there were several projects on Github, where people would post their collection of static methods that are useful as extension methods. I found nothing whatsoever.
c) Within the first two days of using it, I stumbled upon at least 5 problems (which is another hint that no one is really using it):
1) default methods in interfaces are not supported
2) clashes in a bad way with methods that might already exist in sub classes
3) can not handle methods with the same name, which differ only in their parameter types (overloading)
4) val and extension methods do not work together (in javac only)
5) delombok does not rewrite all extension method calls
1) was easy enough to fix in Lombok sources and works perfectly well. But I now need to keep a patched Lombok around. I wonder why such an easy change was never implemented. Default methods in interfaces exist since 8 years. There isn't even a bug report about it. Another sign that no one is really using it.
2) is somewhat limiting. Basically blocks you from extending Object with anything useful, unless you can come up with method names that no one else uses. Otherwise there will be errors in unexpected places. The one single example, that Lombok provides, the or() method on Object, already blows up in my code base.
3) is scary. I cannot implement let's say Stream.map(BiFunction), because then every single normal map(Function) invocation wants to use my new implementation and fails. It get's even scarier when I added the normal map(Function) version as well, then the compiler goes completely berserk, and spits out errors on all kinds of unrelated places.
4) was quite annoying. Everything was fine in Eclipse, I was busy changing things around, and when I commit after several hours, the CI build fails. Turns out, that javac cannot figure out the type of the rhs of a declaration, when an extension method is part of the expression, but Eclipse is totally fine with it.
Stuff like this is almost a show stopper for me. We are using
immutables.io library as well, which also had a bug like this, where javac and Eclipse behave in completely different way. We lost two days of work or so, because a colleague did a big refactoring, only to find out after she was done, that it would not compile on CI, although everything worked fine in Eclipse. I do not want to go there again.
5) I never had to use delombok, and I hope I never need to, but I tried it nonetheless, and it left me with code that didn't compile, because it did not rewrite all extension method calls to their static form.
Conclusion:
After these initial problems, it works quite well now. But that might be because I now know what I should and should not do, and I am careful. I don't know what others might do with it, and I don't know if I want them to use a tool which potentially might break under real world use.
Apart from these, there are other small inconveniences as well, like "Open Declaration"/"Open Call Hierarchy" not working, and hovering over a method does not show anything useful in the tooltip. I think I can live with that, but others might not like that at all.
Until now I'm keeping this in an experimental branch. So before I unleash this on the rest of the team, I would like to get some feedback from the community. Do you use it? Are you happy with it? Is the payoff worth the problems and limitations? Or should I avoid it, and wait until Java gets their act together and finally implements extensions methods (aka: never)? Or switch to Kotlin?
Thanks,
Marc
PS: Just reported most of these as bugs, and also the PR for the annotation on interfaces.