5 ms·
Metaprogramming via reflection is used heavily in the JVM ecosystem, and I can say with confidence that a majority of the bugs I encounter in third party code i
by ulrikrasmussen 6y ago
Metaprogramming via reflection is used heavily in the JVM ecosystem, and I can say with confidence that a majority of the bugs I encounter in third party code is somehow related to reflection. I think the overuse of reflection in Java is a symptom of the language not having adequate support for expression the abstractions that developers need in an affordable way, and hence they turn to reflection to work around these limitations. This leads developers down a path where they can't seem to stop applying reflection until they reach a point where the type system gives you almost no meaningful guarantees and compositionality of your components is ruined.
At least compile time reflection and code generation will catch a large chunk of bugs that would otherwise be deferred to runtime. I will take a puzzling compile time error message over having to debug runtime reflection errors any day.
- tannhaeuser 6y ago> I think the overuse of reflection in Java is a symptom of the language not having adequate support for expression the abstractions that developers need in an affordable way, and hence they turn to reflection to work around these Another explanation is that playing around with annotations and AST decorations/rewriters is an excellent excuse for procrastinating through your day without having to deal with mundane business code :). I also think there's a psychological effect at work here where you're dellusioning yourself into being a "tool developer" and part of an academic discourse when you throw around annotation libs, to deflect from the harsh reality that you're working in cost-center IT. Or maybe a kind of inner migration from an enterprise code base which you can't identify with, and wish to put a fence against, as in "they" (your lib users) vs "us" (elite metaprogrogrammers). As someone else said, today's Spring-heavy Java code bases express behaviour through "anything and everything except actual Java code". C++ developers should take a look at Spring MVC in particular to see if that really is what they want, where the relative sequence of method parameters has significance, and when presented slightly different will result in service request routing 404ing, which you find out only by examining 600-items stack traces with multiple reflection pits.
- ulrikrasmussen 6y agoI think that is a very accurate analysis. There are generally two types of reflection code: the type that aims to achieve modularity and decoupling, and the kind that aims to reduce boilerplate code. I avoid both like the plague, but I think that the latter type in particular is a result of the psychological bias that developers have against writing and maintaining trivial boilerplate code vs. developing fancy tools to reduce it. In the end, you often spend much more time debugging strange issues with the reflection based alternatives than you do actually writing and maintaining the boilerplate. This is also why we have banished all forms of reflection based serialization in favour of hand-written JSON mappings. Yes, they are a bit tedious to write, but it isn't actually that bad. As a plus, you get type errors up front, and you avoid strange errors due to e.g. third party `Map` libraries that the reflection based "magic" cannot figure out how to handle correctly. If the amount of work gets out of hand, you can always turn to code generation later if it is deemed worth it. That being said, I think generic programming and avoidance of boilerplate does have its merits as it can help reduce the cost of abstractions. But it absolutely must be done in a principled way rather than be a result of quick and dirty hacks such as C macros, Java reflection and C++ templates, which all accidentally give you an advanced metaprogramming environment with little safety. An example of an approach that I like is the "Generics SOP" approach in Haskell, although I do recognize that the type-level programming that it involves is not for everyone: https://www.andres-loeh.de/TrueSumsOfProducts/ https://www.andres-loeh.de/TrueSumsOfProducts/
- gpderetta 6y ago> In the end, you often spend much more time debugging strange issues with the reflection based alternatives than you do actually writing and maintaining the boilerplate. It pains me to say that, but I think you are right. A lot of boilerplate elimination ends up being premature generalization.
- jcelerier 6y ago> C++ developers should take a look at Spring MVC in particular to see if that really is what they want, I don't understand why it would be bad to make it impossible to have Spring-like frameworks in C++. A metric ton of useful things have been written in it, and are only written much more painstakingly in C++.
- sgeisler 6y agoRuntime metaprogramming is mighty, but also dangerous. I view compile time metaprogramming as a much saner thing. The type system can still help you avoid potential problems and if in doubt you can just look at the generated code. While it doesn't solve every problem solvable by runtime mp it's good enough in most cases (e.g. building serializers for classes as done with serde in rust).
- mckinney 6y agoIndeed, the JVM sorely lacks in the reflection/metaprogrammaing department. The Manifold framework[1] picks up where Java leaves off. For instance, @Jailbreak is a badass, type-safe alternative to reflection. [1]: https://github.com/manifold-systems/manifold https://github.com/manifold-systems/manifold