Arguments against annotations

My team has moved to Spring 3.0, and there are some people who want to move everything in annotations. I get a very bad feeling in my gut (smell of code?) When I see a class that has methods like this: (just an example - not all real annotations)

@Transaction @Method("GET") @PathElement("time") @PathElement("date") @Autowired @Secure("ROLE_ADMIN") public void manage(@Qualifier('time')int time) { ... } 

Am I just behind, or does it all seem like a terrible idea to someone else? Instead of using OO concepts such as inheritance and polymorphism, everything is now by agreement or through annotations. I do not like it. All code must be recompiled to change what the IMO configuration seems to be wrong. But it seems like everything (especially Spring) is coming. Should I just “handle it” or do I need to step back and try to save our code as an annotation as soon as possible?

+51
java coding-style annotations
Nov 04 '09 at 18:02
source share
12 answers

Actually, I think that the bad feeling in your gut versus is more related to annotations, such as this mix setting with code.

Personally, I feel the same as you, I would prefer to leave the configuration (for example, transaction definitions, path elements, URLs to which the controller should be mapped, etc.) outside the code base itself and in the external Spring XML context files.

I believe that the right approach here comes down to the opinion and the method that you prefer - I would predict that half of the community will agree with the annotation approach, and the other half will agree with the external setting method.

+20
Nov 04 '09 at 18:08
source share

You may have a problem with redundant annotations that are found throughout the code. With meta annotations, redundant annotations can be replaced, and your annotations are at least DRY.

From the Spring Blog:

 @Service @Scope("request") @Transactional(rollbackFor=Exception.class) @Retention(RetentionPolicy.RUNTIME) public @interface MyService { } @MyService public class RewardsService { … } 

Because Java is developing so slowly, people add more features that are not in the language to the annotation. It is good that Java can be extended in one form or another, and this is bad, since most annotations are a workaround and complexity.

+12
Nov 04 '09 at 18:16
source share

I was also skeptical of annotations, but seeing them in use can be great. They can also be used.

The main thing to remember about annotations is that they are static. They cannot change at runtime. Any other way of customization (xml, self-description in code, regardless) does not suffer from this. I have seen that people here at SO have problems with Spring in terms of having a test environment when injecting test configurations and having to dump it to XML in order to do this.

XML is not polymorphic, inherited, or anything else, so this is not a step backward in that sense.

The advantage of annotations is that it can give you a more static check of your configuration and can avoid a lot of detail and difficulties with coordination in XML configurations (basically saving DRY stuff).

As with XML, annotations can be used. The main thing is to balance the needs and benefits of each of them. Annotations, to the extent that they give you less verbose and DRY code, are a tool that you can use.

EDIT: Regarding the comment on annotation replacing an interface or an abstract class, I think this might be reasonable at the border of the frame. Within the framework intended for use by hundreds, if not thousands of projects, having an interface or base class can really distort things (especially the base class, although if you can do this with annotations there is no reason why you could not do it with normal interface.

Consider JUnit4. Previously, you had to extend the base class, which had a tuning and disruption method. In my opinion, it really doesn't matter if they were on the interface or in the base class. Now I have a completely separate project with my own inheritance hierarchy, and they all must follow this method. First of all, they cannot have their own conflicting method names (not a big deal in testing, but you understand my point). Secondly, you have a chain of calling super everything down, because all methods must be connected.

Now with JUnit4 you can have different @Before methods in different hierarchy classes, and they can be independent of each other. There is no less DRY way to do this without annotations.

From the point of view of developers, JUnit is a disaster. It is much better to have a specific type, which you can call setUp and teardown. But the framework does not exist for the convenience of the developer of the framework, it exists for the convenience of the user of the framework.

All this applies if your code does not need to care about the type (that is, in your example, nothing will still use the controller type). Then you can even say that the implementation of the framework interface is more impenetrable than overlaying the annotation.

If, however, you intend to write code to read this annotation in your own project, run far.

+7
Nov 04 '09 at 18:12
source share

I personally believe that annotations intercepted too much and exploded from their original and overly useful purpose (for example, minor things, such as specifying an overridden method) into this crazy metaprogramming tool. I don’t feel that the JAva mechanism is strong enough to handle these clusters of annotations prior to each method. For example, I struggle with JUnit annotations these days because they limit me in ways I don't like

Given that, in my experience, the XML-based configuration is not very good. Therefore, to quote South Park, you choose between a giant shower and a t * rd sandwich.

I think the main decision you need to make is how much more convenient it is for you to have a spring configuration delocation (i.e. support two files instead of one), and whether you use IDE tools or plugins that benefit from annotations. Another important question is whether the developers who will use or maintain your code really understand the annotations.

+4
Nov 04 '09 at 18:13
source share

Check out these answers to similar questions.

What are the advantages / disadvantages of annotations (not a compiler) compared to xml configuration files

Xml configuration and annotation-based configuration

It basically boils down to: Use both. Both have their own affairs. Do not use annotations for things that should remain configurable without recompiling everything (especially what your user might need to be configured without having to recompile everything)

+3
Nov 04 '09 at 18:09
source share

I think annotations are good if they are used with measure. Annotations like @WebService work a lot during deployment and runtime, but they don't interfere with the class. @Cachexxx or @Transactional clearly prevent the creation of proxies and a lot of artifacts, but I think they are under control.

The thing starts to go bad when using Hibernate or JPA with annotations and CDI. Annotations grow a lot.

IMO @Service and @Repository are the hindrances of Spring in your application code. They make your Spring application dependent and Spring-only.

The case of the Spring Data Graph is another story. @NodeEntity, for example, add methods to a class at build time to save a domain object. If you do not have Eclipse and Spring plugins, you will be mistaken because these methods do not exist in the source code.

The configuration next to the object has its advantages, but also one configuration point. Annotations are good with measure, but they are not good for everything, and ultimately bad when there are as many lines of annotation as there are lines of source code.

I think the Spring path is going wrong; mainly because in some cases there is no other way to do such fun things. It is as if Spring wants to do xtreme coding and at the same time blocks developers in the Spring framework. The Java language probably needs a different way to do some things.

+3
May 28 '11 at 14:48
source share

Annotations should be used sparingly. They are good for some, but not for everyone. At least the xml configuration approach saves the configuration in a single file (or several) instead of spreading all over the place. That would represent (as I like it) the organization of crap code. You will never see a complete picture of the configuration if it spreads over hundreds of files.

+3
Nov 08 '12 at 13:33
source share

I think it depends on when you started programming. Personally, I think they are terrible. First of all, because they have some quasi-radiation that you will not understand if you are not aware of this annotation. Thus, they form a new programming language on their own and push you away from POJO. Compared to (say) the regular old OO code. The second reason is that they can prevent the compiler from doing your work for you. If I have a large code base and want to reorganize or rename something, I would ideally want the compiler to select everything that needs to be changed, or as much as possible. Annotations should be just that. Annotations. Not central to the behavior of your code. They were originally designed to be optionally omitted when compiling, which tells you everything you need to know.

And yes, I know that the XML configuration works the same. It does not make it worse, just as bad. At least I can pretend to ignore it, but it does not look me in the face in every declaration of a method or parameter.

Given the choice, I would prefer the terrible old J2EE remote / home interfaces, etc. (people from

Unfortunately, annotations are trendy. Thus, it will not be easy for you to prevent the use of your command if you are not in code reviews / standards, etc. (Also out of fashion!)

I read that Stroustup left annotations from C ++, fearing that they would be misused. Sometimes things go in the wrong direction for decades, but you can hope that everything will be in full on time.

+2
Jan 25 2018-11-11T00:
source share

Like many things, there are pros and cons. In my opinion, some annotations are good, although sometimes it seems that there is a tendency to abuse annotations when a simple approach to calling an old function may be higher, but in general it can inadvertently increase the cognitive load, because they increase the number of ways to “do things”.

Let me explain. For example, I'm glad you mentioned the @Transactional annotation. Most Spring developers are likely to know and use @Transactional. But how many of these developers know how @Transactional works? And do they know how to create and manage a transaction without using the @Transactional annotation? Using @Transactional simplifies the use of transactions in most cases, but in some cases, when I need finer-grained control over a transaction, it hides this data from me. Thus, it is a double-edged sword.

Another example is @Profile in Spring config classes. In general, it is easier to specify which profiles you want to load into the Spring component. However, if you need more powerful logic than just specifying the list of profiles for which you want to load the component, you would have to get the Environment object yourself and write a function for this. Again, most Spring developers are likely to be familiar with @Profile, but a side effect of this is that they become less familiar with the details of the work, such as the Environment.acceptsProfiles (String ... profiles) function, for example.

Finally, when annotations do not work, it can be harder to understand why, and you cannot just put a breakpoint in the annotations. (For example, if you forgot @EnableTransactionManagement in your config, what will happen?) You should find the annotation handler and debug it. When approaching a function, you can, of course, just put a breakpoint in the function.

+2
Mar 30 '16 at 22:05
source share

In annotations, dependencies are often introduced in which such dependencies do not belong.

I have a class that coincidentally has properties that resemble attributes from a table in an RDBMS schema. The class was created with this mapping in mind. Obviously, there is a relationship between the class and the table, but I am happy to keep the class free from any metadata declaring this relationship. Is it correct that this class refers to a table and its columns in a completely different system? Of course, I do not mind the external metadata that connect the two and leave each free from the understanding of the other. What did I get? This is not the case as if the metadata in the source code provided type safety or mapping matching. Any validation tool that could parse JPA annotations could parse hibernate mapping files equally well. Annotations did not help.

Under one contract, I created a maven module with a package of interface implementations from an existing package. Unfortunately, this new package was one of many directories in a monolithic assembly; I saw this as something separate from other code. However, the team used class scanning, so I had to use annotations to connect my component to the system. Here I do not need a centralized configuration; I just need an external configuration. The XML configuration was not ideal, as it combined dependency postings with component creation. Given that Rod Johnson did not believe in component development, this was true. However, I again felt that annotations did not help me.

Contrast this with something that doesn't bother me: TestNG and JUnit tests. I use annotations here because I am writing this test knowing that I am using TestNG or JUnit. If I replace one with the other, I understand that I will have to perform an expensive transition that will deviate from overwriting the tests.

For some reason, I accept that TestNG, JUnit, QUnit, unittest, and NUnit belong to my test classes. Under no circumstances will JPA or Hibernate own these domain classes, which, as it turns out, are mapped to tables. Under no circumstances does Spring own my services. I control my logical and physical packaging to isolate units that depend on them. I want to ensure that the transition from one does not leave me crippled due to all the addictions that he left. Saying goodbye is always easier than leaving. At some point it is necessary to leave.

+1
Sep 26 '17 at 20:42 on
source share

This is 2018 and this moment is still relevant.

My biggest problem with annotations is that you have no idea what annotations do. You turn off some code and hide it somewhere else.

Annotations were introduced to make the language more declarative and less programmatic. But if you move most of the functionality into annotations, you actually switch your code to another language (and not very good at the same time). There is very little verification at compile time. This article does the same: https://blog.softwaremill.com/the-case-against-annotations-4b2fb170ed67

The whole heuristic "move everything to the configuration so that people do not need to learn to code" got out of control. Engineering managers do not think.

Exceptions:

  • Junit
  • Jax-rs
+1
Oct. 25 '18 at 0:22
source share

In my experience, annotations are bad:

  • Inability to provide type safety in annotations
  • Serialization Issues
  • Cross-compiling (e.g. for JavaScript) can be a problem.
  • Libraries / structures requiring annotations exclude unannotated classes from external libraries.
  • not replaceable or interchangeable
  • Your projects end up becoming highly dependent on a system that requires annotation

If Java had something like “method literals,” you could annotate the class in the corresponding annotation class. Something like this: for example, javax.persistence and the following annotated class:

 @Entity class Person { @Column private String firstname; public String getFirstname() { return firstname; } public void setFirstname(String value) { firstname = value; } @Column private String surname; public String getSurname() { return surname; } public void setSurname(String value) { surname = value; } } 

Instead of annotations, I would suggest a mapping class like this:

 class PersonEntity extends Entity<Person> { @Override public Class<Person> getEntityClass() { return Person.class;} @Override public Collection<PersistentProperty> getPersistentProperties() { LinkedList<PersistentProperty> result = new LinkedList<>(); result.add(new PersistentProperty<Person>(Person#getFirstname, Person#setFirstname); result.add(new PersistentProperty<Person>(Person#getSurname, Person#setSurname); return result; } } 

The fictitious “#” sign in this pseudo-Java code represents a method literal that, when invoking an instance of this class, invokes the corresponding delegate (signed "::" starting with java 8) of this instance. The PersistentProperty class must be able to enforce method literals that reference this generic argument, in this case the Person class.

This way, you get more benefits than annotations can provide (for example, creating a subclass of “annotation” -class), and you don't have any of the above disadvantages. . , , /. Java (, - /, Protocolbuffers)

0
17 . '19 11:09
source share



All Articles