If you want to program in better language, just go and use better language.
The most important strength of Java and basically the only reason it is being used is that the code is simple to understand (simplistic!), everything is easily trace-able and debuggable and that you get fantastic tools that know everything about code and can provide you safe operations on huge code bases (refactoring, finding usages, tracing and understanding code paths, etc.)
Lombok and new Java features decrease reliability of tools removing Java's biggest strength.
There is tons of boilerplate in a simple Java bean, so when you have 3 pages of getters/setters, equals, hashcode, toString etc... and someone introduces something hacky it doesn't jump out at you.
To be fair, it doesn't have to be a hack, but it's doing something weird that's unexpected.
Then if I use @Data and I still see a Getter/Setter defined it calls it to my attention since odds are i'm doing something different.
ie. Oh, you're parsing a string get a numeric value and then setting it with a fallback value/exception. Okay good to know. If it screws up at least I know there is a special behavior here.
Lombok makes these patterns much easier to read though I prefer to only use it for repeat code. Saving one line so you can have @Cleanup doesn't seem worth it to me. It hides too much as you said above, but it varies on the use case.
Record types for Java are being worked on, and we should be getting them hopefully at some point in the (near) future.
IMO saving one line with @Cleanup is not worth it but if the class doesn't implement AutoClosable, I think it makes code more readable too.
Actually I was thinking about different approach last year, didn't get to implement it. Something like declare abstract class with getX() setX() methods and let library to implement missing methods. Now it's one line per method, no trivial code and able to generate other nice things, e.g. I really want to have fast initializeable properties (like getX throws exceptions until I call setX).
Oh, the wonders of using widespread mutable state! Did you remember to call this other method here before trying to call me??? No?!?! Oh, here's a nasty Exception for you then.
Edit: The kotlin service was one internal service that I experimented with. Our other 17 production services were standard java spring.
> There is little gotcha when using Java’s try-with-resource syntax. The resource has to implement AutoCloseable interface, so the compiler can use void close() method for closing a resource. Lombok’s @Cleanup, it doesn’t have to implement this interface. The resource just needs to have some closing method which by default is void close() (but you can specify your own method name responsible for closing resource).
Specifically, I don't agree with this approach in a compiled language like Java. We need to have a standard writing code in Java and AutoCloseable is the way to go. If the library doesn't support it, just create a proxy class and implement the interface there. It may be a bit verbose (we switched to Kotlin later on) but it will be much easier to catch the bugs. I don't want to spend 4 hours trying to find the root cause of a strange bug in favor of writing less code.
Kotlin is indeed far superior and an extremely easy drop in solution on pretty much any Java project. A lot of what Lombok tries to achieve via code generation triggered by annotations is just built-in to Kotlin. E.g. a large part of what Lombok does is making java beans less painful by generating setters/getters and lots of other stuff. That's useful. However, Kotlin's data classes are way better.
For things that are Closable/Autoclosable, Kotlin injects a use extension function that takes a block where you use the resource and it cleans up after you. You just do a stream.use {...} and it does the right things. Kotlin adds tons of useful stuff like this to existing Java APIs.
Whether you use Java or Kotlin, any half decent static code analysis tool should be able to help you spot shoddy resource handling. Same for Kotlin; it has a lot of this built into the compiler. For Java, use spotbugs or similar. IMHO that's not optional.
Regarding IDE support - I was once on a project using Lombok where some developers used Eclipse and others used IntelliJ. The Eclipse devs wanted to use this new @Builder annotation, which didn't work on IntelliJ but worked fine on Eclipse - for interesting reasons.
I attempted to patch the IntelliJ Lombok plugin to support @Builder - but gave up on it for reasons of time, priority and the fact that I wasn't certain it would work as Lombok continued to change. Also this was an experimental feature at the time that wasn't even certain to become mainline. I learnt a bit in the process.
Lombok works by passing certain switches as arguments to javac, which alters the class files that it writes out based on the annotations. It "confused the hell out of IntelliJ", because IntelliJ's intellisense/auto-complete plugin ecosystem works as so: IntelliJ exposes AST _from source_ to plugins, like the Lombok plugin, which hook in and let IntelliJ know, for instance, there's another method here due to this annotation. So it's constant effort to ensure the plugin's injections line up with what the compiler is actually spitting out.
Eclipse on the other hand is always aligned. I can only infer that it generates its autocompletion etc from the _compiler's output_. So whatever version of Lombok you're using, the autocompletion features will always be aligned.
So far I've observed with libraries like Lombok there is a smaller community (compared to language community) that vets the idea; and the features are opinionated to that particular community. Which results into fragmentation; just as example https://immutables.github.io/ and https://github.com/google/auto are two libraries providing features like factories and immutable value classes. Then you get articles like https://codeburst.io/lombok-autovalue-and-immutables-or-how-... for improving your code.
This in my opinion doesn't hurt as long as you are a small company. But when your code is going to be used across teams with different opinions, and language doesn't enforce a single way to define construct these kind of byte-code mangling ideas fall apart. I've personally people complain about Lombok and they hate it every bit. Doing these constructs at language level removes debate, and unifies how people in larger community. I hope newer versions of Java move fast enough to make something simple like `@Cleanup` a thing of past. I will highly encourage everyone to try Kotlin too; it's almost transparent drop-in with better syntax.
This caused a problem for me because we would write very lean code with low cyclomatic complexity and having these missed branches would screw up our code coverage numbers, causing us to miss our standards. I would just do it the old way, with the finally. I wish I knew about this @CleanUp. For some reason a lot of code i am writing nowadays does not have me messing with streams directly, but when it comes up again I will use this annotation.
This seems like a perverse criticism. Fix your code coverage analysis?
OutputStream out = new BarOutputStream();
in.transferTo(out);
if (out != null) ...
Can someone explain how `out` could possibly be null here?If the `in` stream init throws, the entire try-block isn't run at all. If `out` stream init throws, the following try/finally block isn't run either.
Lombok's docs get this wrong too. Unless I'm going crazy.