4 ms·
No, he shows real issues with Java code base littered with annotations that do "magic". The example with email validation really hits the homebase really well.
by krzyk 4y ago
No, he shows real issues with Java code base littered with annotations that do "magic".
The example with email validation really hits the homebase really well.
Also dependency on old java versions (without records) is really troubling.
Fortunately Spring 6 will depend on JDK 17.
- pjmlp 4y agoThe poster child of AOP, I guess that isn't magic.
- krzyk 4y agoAOP is magic, you don't know what, where and how. AOP should end at `@Override`, all the rest turns Java into some kind of DSL which makes it unreadable (similar to what some people do to Scala, because it is too easy to make it into a DSL). Poster child of AOP is logging, you log stuff, don't change the code (e.g. adding validation).
- kaba0 4y agoYou can’t change code either in Java — annotation processors are explicitly unable to do that — Spring’s magic works through loading new classes up that either implement the same static interface you use, or extending the class, and injecting this new proxy instead. In short, if you want to log certain methods at enter and exit time with AOP (not manually adding it everywhere), you just create a proxy object and do a logEnter(); targetedObj.method(); logExit(); That’s why some people dislike Lombok as that actually changes byte code at compile time.
- samus 4y agoThe bytecode format is well-documented. If Lombok would just augment these, then there would be no major problem with it. But it actually does something worse: it uses reflection and other tricks to extend the Abstract Syntax Tree, which is purely an implementation detail of the Java compiler. And it must do the same with every tool that touches Java Sources.
- mike_hearn 4y agoEmail address validation isn't magic and nor is annotating fields to give more context about what they're meant to contain. The article author believes everything should be done with types. But Java has always been able to represent an EmailAddress type. It's not like the Quarkus guys don't know about strong static typing! Bean Validation exists because: 1. Every tool knows what a string is. Very few know what your custom email address type is. In theory you can solve this with sub-typing, or duck typing, etc. But in Java the String class is final, so you can't extend from it. This has definitely had big advantages over the years - there's no proliferation of custom utility string types, and new Java versions could optimize the internal representation aggressively. It's not at all clear that Java would be better if String was an open class. 2. Bean Validation lets you validate every field at once and collect the errors together. This is extremely helpful for user interfaces where you want to be able to copy user data into an object, validate it, and then return all the problems to the UI for rendering next to the form. With the type approach he gives you'd get exactly one problem followed by an exception. The user would fix it, re-submit the form or re-execute the tool, and then get the next problem. Painful! Ditto for APIs where you want to de-serialize JSON into objects, validate them all in one go and return a single error response if there are issues. 3. Bean Validation is designed to be applied to both database entity and GUI model (e.g. config) objects, though it can be used for anything. Immutable types are useless for this use case because the database and GUI are both fundamentally about mutable state. The DB layer can generate far more optimized SQL and thus far more optimal DB resource usage if it can record what's changing (which requires some sort of "clever" stateful object), and for the UI you need to be able to hold invalid data somewhere - ideally in your model object, so the user's data can both be held in the model and also trigger validation errors. 4. It can also be used with parameters and return types on methods (with sufficient framework support from your implementation). This lets you add constraints to implementations in an API compatible way. Changing types wouldn't allow for that. The author should really just read the intro to the Jakarta Bean Validation spec, which lays out the rationale quite clearly: https://jakarta.ee/specifications/bean-validation/3.0/jakarta-bean-validation-spec-3.0.html#introduction https://jakarta.ee/specifications/bean-validation/3.0/jakart... Does anyone worry about whether reading a value out of a config object will launch rockets? No. The type system could express this, but the value of doing so would be very low. It is obvious from context. The reason it uses interfaces is because, if we check the docs: "Under some circumstances, some data sources may change dynamically. The changed values should be fed into the client without the need for restarting the application" If you implement config handling in the FP way he wants then a change to any part of the config requires rebuilding the entire object graph representing the entire configuration, and then re-plumbing that all through the rest of your (presumably immutable) set of objects. What you'd intuit should be a very fast operation with little memory overhead can suddenly require re-initializing large chunks of your app. A functional programmer might simply assert that being able to mutate configuration at runtime is a bad feature, but in the real world we do this sort of thing all the time and being able to handle it well is a useful feature of a config library. The core disagreement here isn't actually anything to do with Java. More or less any imperative language would attract the ire of this author. What he's upset about is the existence of libraries and frameworks designed for mutability. But, mutability is inherent to the world. You can try to manage and constrain it but you can't remove it and sometimes you have to embrace it. That's not "Java culture", it's just life.
- oaiey 4y agoCode Annotations are data (code = data). Data which is used in a function (side-effect-free) which validate a record. I do not know how more functional a generic purpose validation function can be. The problem for people, is that they do not like the place where the function is called and side effects are applied. In your typical Java/C#/... OO framework, this function is called two or three stack frames down into the framework. And here the author's point of Java/C# culture has its point.
- josefx 4y agoInstead he expects interfaces to do magic. AutoClosable isn't even one of Javas pre annotation marker interfaces and the documentation makes it clear that just because the interface is present doesn't mean that a call to close makes sense.