| Ok, I hear you. I agree somewhat, but not totally :) To me, the most important aspect of programming is to retain full control. I for instance want to be able to register my HTTP endpoints based on some data read from a file. I want to be able to start my app in server mode and run requests against it in any way I want during testing. What many of these frameworks do is to remove this power. Bytecode modification is not too bad IMO, as long as it's within reason. I use a notnull annotation weaver to add notnull assertions. Not Lombok, that's too much for me as well. Should be another language really, like Kotlin. Metaprogramming does have utility. But it has a tendency to go overboard. I actually find Jersey to be a good example of a nice and clean API for defining resources. I recently tried to integrate it into a small app where we do all the wiring manually for clarity. The problem is that it's hard to stay in programmatic control. You define a resource. You realize you need a Service in your resource. You realize that the only way of getting it into your object is to inject it with the JAX-RS annotations. And so suddenly your service has to be a JAX-RS @Singleton service. You have to make your whole app JAX-RS compatible. The framework takes control. This is really bad IMO. A library which requires control over your program. This is not an intrinsic problem of metaprogramming, but IMO it's a big problem of Java as it stands today. We need to give up on frameworks, make sure that all libraries are combinable and that they don't take control of your app. Doing so would make everything a lot better. I wish I could just do: new Jersey(config).addRoutesIn(new HelloWorldResource(new MyBackendService(dbDriver))).addSerializer(new JsonSerializer()).start(); This would then utilize some reflection when routing requests, but not take over my entire app. Regarding the libraries, my point was not that you get conflicting classes (DLL hell sort of thing), but that we're building multiple products which want to take over the world. JUnit wants to be in control, and so does Spring. So when you try to combine them, you end up with a problem. Can you start Spring programmatically from a JUnit test? Well, not really. You can, but it's very involved. So they want to provide you with a Spring-JUnit integration. This is a really bad idea, since every linear combination of libs has to get an integration, like the link I included in my post. If all these libraries just tried to stay out of the way of the programmer and just provide a programmatic API, there would be no need for such integrations. |
That makes me prefer minimal, magic-free tools, because even if it's sometimes a source of extra effort, at least I won't have to spend time fighting the framework. The fear of boilerplate seems strange to me. I'd much rather spend the extra ten seconds of adding a route manually through a line of code than no time at all if it spares me having to spend an hour figuring out why my ContextProvider isn't being registered by the classpath scanner.