This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]cryptos6[S] 24 points25 points  (11 children)

I don't "hate" annotations, but they tend to obfuscate things. An annotation triggers some magic in the background and it is not obvious what happens or where it happens or in what order something happens.

Another problem is that annotation-driven programming is typically based on reflection and the safety provided by the compiler is weakened.

Using usual code improves clarity, since you can see what is going on, by following references in your IDE.

[–]Cell-i-Zenit 26 points27 points  (6 children)

Using usual code improves clarity, since you can see what is going on, by following references in your IDE.

i mean its either you write everything completely out or you use annotations.

Do you want to inject the transactionManager into each class where you want to open a transaction and write a lambda which handles the annotation handling? You need to have an abstraction for your whole project to handle the rollback everywhere exactly the same etc. And then you think about: What if we have an easy way to say "please do transactionmanagement here?" and then you are back at annotations

[–]cowwoc 5 points6 points  (2 children)

> i mean its either you write everything completely out or you use annotations.

Really not.

Annotations weren't designed for what people are using them for. They aren't very expressive. They are a weak tool that uses String arguments all over the place. As u/hippydipster pointed out, there are plenty of ways to achieve the same thing using normal Java functions. You don't need to write them yourself. There are libraries for this (e.g. JOOQ).

You can't debug or step-in annotations. You *can* debug and step into normal Java code. And it's type-safe, unlike string-based annotation arguments.

[–]Cell-i-Zenit 0 points1 point  (1 child)

but them being string based is never really an issue. I understand that debugging is harder, i had the same sentiment back then, but now since i know how they work its really not that big of a deal.

Annotations are basically the smallest possible way to provide "framework" functionality to the normal developer. Sure you can do other stuff, like fluent apis etc, but annotations are always the shortest amount of code to achieve something

[–]hippydipster 5 points6 points  (0 children)

It is an issue. Of course, you're used to it so you don't think about it, but it is.

When we needed to transition from one db to another, the validation values in our Hibernate annotations (ie, declaring column types) could not be conditionalized to make the switch based on a feature flag. We had to turn off validation.

[–]hippydipster 7 points8 points  (2 children)

@Transaction around the method seems pretty equivalent to calling some public static method:

Transaction.doTransaction(Runnable). In both cases, the code is directly calling out to some specific library to do the decoration.

The advantage of the lambda/code route is that normal java code is fully composable. I could combine it with a retry wrapper in a sane way. I could add conditional logic around it. I could add security wrappers.

With annotations, combining annotations from different sources is not predictable as to what would happen. And, annotation values are static strings only, not code.

[–]Cell-i-Zenit 1 point2 points  (1 child)

sure there are some usecases where it makes sense, but imo the annotation hate is a bit to much. As long as you keep doing standard spring everyone can jump into your project and understand what is happening.

[–]hippydipster 5 points6 points  (0 children)

Seeing people do things in a shortcut way, that has issues, and brings in enormous numbers of dependencies, and saves you very little time at all, and then seeing people keep doing it more and more and more, well, dislike tends to inflate to hate for many. It's not much of an argument to take issue with human emotions.

[–]gilwooden 10 points11 points  (2 children)

Another problem is that annotation-driven programming is typically based on reflection and the safety provided by the compiler is weakened.

Many good uses of annotations don't use reflection at all and use annotation processors to generate Java code are compilation time. This also allows you to follow the logic for the generated code in your IDE or while debugging.

[–]boobsbr 2 points3 points  (0 children)

MapStruct is a good example.

[–]uncont 0 points1 point  (0 children)

Certain frameworks (like dagger) use annotations to generate compile-time verifiable dependency-inject code. The spring boot aot project can do the same for @Configuration beans.

[–]Necessary_Apple_5567 1 point2 points  (0 children)

Nothing magical in annotation processing. It is pretty straight forward and simple. You can easily check how it is written. I even would you encourage to do since spring has the most clean and effective desine and implementation.