Rating 26 years of Java changes
neilmadden.blog229 points by PaulHoule a day ago
229 points by PaulHoule a day ago
Definitely underrates the impact of annotations. I'm personally not a fan of the way annotations are used to implicitly wire together applications, but I have to admit the impact. Maybe 5/10 is fair in light of the wide range of positive and extremely negative ways annotations can be used.
So many of these features were adopted after they were proven in other languages. You would expect that since Java took such a slow and conservative approach, it would end up with extremely polished and elegant designs, but things like streams ended up inferior to previous developments instead of being the culmination. Really disappointing. Java is now a Frankenstein's monster with exactly as much beauty and charm.
I used to joke that the direction spring was heading was that you’d have an application be a boilerplate main method with a dozen lines of annotations. Then I actually encountered this in the wild: we had an app that sent updates from db2 to rabbitmq, and the application literally was just configuration via annotations and no actual Java code other than the usual spring main method.
Is that strictly bad, though? Being able to run an enterprise service by setting configuration values declaratively, and get all the guarantees of a well-tested framework, seems like a pretty good thing.
Yes, it’s weird how that’s still Java, but using standard components and only using code as glue where it’s absolutely necessary seems very similar to other engineering disciplines to me.
I think the general adversity against this specialized configurations is that they often tend to be fairly limited/rigid in what they can do, and if you want to customize anything you have to rewrite the whole thing. They effectively lock you into one black box of doing things, and getting out of it can be very painful.
Spring boot just provides what they think are reasonable defaults and you provide some specifics.
You can always inject your own implementation if needed right?
Spring is written by a committee of junior developers trying to implement the ideas from a committee of slightly less junior developers. Which is to say it's a huge unintelligible mess. As the other commenter attest, it works really well if you need the one thing it does - unfortunately the moment you need something slightly different you are forced to dig deep into the insane internals and it is a disaster. This moment comes very quickly too in every project because it was written by people with no experience in real projects.
In theory, yes. In practice, I've found that things get really complicated as soon as you start trying to interact with the spring lifecycle. Figuring out how to customize things and manage priority is the trickiest thing in Spring, IMO.
Please use the facilities of the framework for debugging any lifecycle issues. I was surprised when I found out that people did not use `--debug` for example or enabled logging of application startup events.
If you prefer GUI, Intellij even has a Spring Debugger: https://www.jetbrains.com/help/idea/spring-debugger.html
I stopped using Spring Debugger because for some inexplicable reason enabling it makes breaking at the breakpoint take minutes instead of seconds. For quite a while I didn't realize this was the problem, as IntelliJ started having it turned on by default at some point.
Oh, I think it’s quite wonderful really. There are cases where the limited nature of some configuration-based things ends up being a mess (one that comes to mind is a feature in Spring Data where you can extend a DAO bean into a rest service through annotations, but it turns out that this feature (at least when I last tried working with it), is so rigid as to be nearly useless in actual practice. But our codeless application was a bit of brilliance, I think.
this is exactly why spring succeeded. I need to run a scheduled job, @EnableScheduling then @Scheduled(cron = “xxxxxx”) - done. I need XYZ, @EnableXYZ the @XYZ… sh*t just works…
And then I realize I need to change that schedule. And would like to do it without recompiling my code. Oh, and I need to allow for environment specific scheduling, weekdays on one system, weekends on others. And I need other dependencies that are environment specific.
I much prefer Spring's XML configuration from the old days. Yeah, XML sucks and all that. But still, with XML, the configuration is completely external from the application and I can manage it from /etc style layouts. Hard coding and compiling in dependency injection via annotations or other such behaviors into the class directly has caused me grief over the long term pretty much every time.
I do realize you were intending to give examples of why you don't think annotations aren't very extensible, but it is an odd example as all those things can still be achieved via annotation, since the annotations can accept values loaded from env specific properties.
Exactly this, it’s great fun to have a surface level understanding of a topic and post derisively for internet points; rather then spend the time and effort to actually learn about the subject at hand!
I'm not digging for "internet points". Yes, superficial replacement values can be retrieved from the environment. But I guess we have to give you a more imagined or sophisticated example then to make the point to you?
How about varying implementations of a service interface. Let's say I have a Scheduler interface and I want to have multiple implementations; maybe one is CronScheduler, another is RandomScheduler, another is BlueMoonScheduler. Each of these schedulers have their own properties and configuration values. I might want to choose, per environment or deployment context, which service implementation to use.
Annotation configuration makes this (near?) impossible to dynamically wire and configure these scenarios and make them tailored to the environment or deployment scenario. Annotations are generally "static" and do not follow a configuration-as-code approach to application deployment.
An external configuration file, as offered by Spring's original (less "favored") XML style, allowed a more composable and sophisticated configuration-as-code approach. Maybe that's a negative, putting that much power into the hands of the service administrator. But as I stated originally, in my experience, having statically defined annotation driven configuration and/or dependency injection has caused more problems than it has solved.
> env specific properties
And then if you want to change a value at runtime you have to restart the executable?
Most web application servers work this way. It also works really well in practice using modern CD tools - update your configuration and perform a gradual rollout of all your application servers to reflect the updated configuration.
The only real-world usage I see for annotations are in GSON (the @Expose) and JUnit with @Test.
Never really came across with any other real cases where it solves a pressing issue as you mention. Most times is far more convenient to do things outside the compiled code.
Agreed. These are good examples where annotations seem like a good fit. Being able to tell a processor that a method or field is "special". Test methods, serializable hints, etc.
It's kind of like, when annotations were delivered to Java, lots of projects thought they were just the next greatest thing. I followed right along at the time, as well.
But over time, finding the value in the configuration-as-code approach to application deployment, I definitely feel that annotations have been abused for many use cases.
Yeah, it works until it isn't. And they good luck debugging it. I'd prefer simple obvious linear code calling some functions over this declarative magic any day.
cronService.schedule("xxx", this::refresh);
This isn't any harder than annotation. But you can ctrl+click on schedule implementation and below easily. You can put breakpoint and whatnot.never had any issues debugging as I am never debugging the scheduler (that works :) ) but my own code.
and what exactly is “cronService”? you write in each service or copy/paste each time you need it?
`cronService` is an injected instance of some class, probably provided by framework. My point is to demonstrate alternative, imperative way of defining cron tasks, as compared to declarative one.
A better name would probably be CronScheduler or something else. “Service” is always overused and doesn’t actually describe or mean anything.
You can write your own libraries?
My goodness. What a question!
Whole point of spring is so you don't have to write your own libraries. Batteries included and all.
What if I told you - you can use a batteries-included framework, and still write your own libraries specifically only for things you want your own version of and want to share across projects?
The problem isn't that I don't know how to use a batteries included framework. The problem is that you guys don't know there is even an option to reuse your code by writing libraries.
Why are you assuming you cannot write your own library and use it with Spring? It's not an either/or, just like most frameworks are. You are framing it as if there is only one way to do it in spring.
Please do not project things like "you guys don't even know..". I'm one of "you guys" , and have built production code in a variety of languages and frameworks. So this "you guys" knows exactly what he/she is talking about.