Arguments Against Annotations

前端 未结 12 1752
北海茫月
北海茫月 2020-12-23 13:48

My team is moving to Spring 3.0 and there are some people who want to start moving everything into Annotations. I just get a really bad feeling in my gut (code smell?) when

相关标签:
12条回答
  • 2020-12-23 13:51

    I was also initially skeptical about annotations, but seeing them in use, they can be a great thing. They can also be over used.

    The main thing to remember about annotations is that they are static. They cannot change at runtime. Any other configuration method (xml, self-description in code, whatever) does not suffer from this. I have seen people here on SO have issues with Spring in terms of having a test environment on injecting test configurations, and having to drop down to XML to get it done.

    XML isn't polymorphic, inherited or anything else either, so it is not a step backwards in that sense.

    The advantage of annotations is that it can give you more static checking on your configuration and can avoid a lot of verbosity and coordination difficulties in the XML configurations (basically keeping things DRY).

    Just like XML was, Annotations can be over used. The main point is to balance the needs and advantages of each. Annotations, to the degree that they give you less verbose and DRYer code, are a tool to be leveraged.

    EDIT: Regarding the comment about an annotation replacing an interface or abstract class, I think that can be reasonable at the framework boundary. In a framework intended to be used by hundreds, if not thousands of projects, having an interface or base class can really crimp things (especially a base class, although if you can do it with annotations, there is no reason you couldn't do it with a regular interface.

    Consider JUnit4. Before, you had to extends a base class that had a setup and tear down method. For my point, it doesn't really matter if those had been on an interface or in a base class. Now I have a completely separate project with its own inheritance hierarchy, and they all have to honor this method. First of all, they can't have their own conflicting method names (not a big deal in a testing framework, but you get my point). Second of all you have have the chain of calling super all the way down, because all methods must be coupled.

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

    From the point of view of the developers of JUnit, it is a disaster. Much better to have a defined type that you can call setUp and teardown on. But a framework doesn't exist for the convenience of the framework developer, it exists for the convenience of the framework user.

    All of this applies if your code doesn't need to care about the type (that is, in your example, nothing would every really use a Controller type anyway). Then you could even say that implementing the framework's interface is more leaky than putting on an annotation.

    If, however, you are going to be writing code to read that annotation in your own project, run far away.

    0 讨论(0)
  • 2020-12-23 13:51

    I think it depends to some extent on when you started programming. Personally, I think they are horrid. Primarily because they have some quasi-'meaning' which you will not understand unless you happen to be aware of the annotation in question. As such they form a new programming language all by themselves and move you further away from POJOs. Compared to (say) plain old OO code. Second reason - they can prevent the compiler doing your work for you. If I have a large code base and want to refactor something or rename something I'd ideally like the compiler to throw up everything that needs to be changed, or as much as possible. An annotation should just be that. An annotation. Not central to the behaviour of your code. They were designed originally to be optionally omitted upon compilation which tells you all you need to know.

    And yes, I am aware that XML config suffers in the same way. That doesn't make it worse, just equally bad. At least I can pretend to ignore that though - it doesn't stare me in the face in every single method or parameter declaration.

    Given the choice I'd actually prefer the horrible old J2EE remote/home interfaces etc (so criticised by the Spring folks originally) as at least that gives me an idea of whats happening without having to research @CoolAidFrameworkThingy and its foibles. One of the problems with the framework folks is that they need to tie you to their framework in order to make the whole enterprise financially viable. This is at odds with designing a framework well (i.e. for it to be as independant and removeable from your code as possible).

    Unfortunately, though, annotations are trendy. So you will have a hard time preventing your team using them unless you are into code reviews/standards and the like (also, out of fashion!)

    I read that Stroustup left annotations out of C++ as he feared they would be mis-used. Sometimes things go in the wrong direction for decades, but you can hope things will come full circle in time..

    0 讨论(0)
  • 2020-12-23 13:56

    I personally feel that annotations have taken over too much and have blown up from their original and super useful purpose (e.g., minor things like indicating overridden method) into this crazy metaprogramming tool. I don't feel the JAva mechanism is robust enough to handle these clusters of annotations preceding each method. For instance, I'm fighting with JUnit annotations these days because they restrict me in ways that I don't like

    That being said, in my experience the XML based configuration isn't pretty either. So to quote South Park, you're choosing between a giant douche and a t*rd sandwich.

    I think that the main decision you have to make is whether you are more comfortable with having a delocalization of the spring configuration (i.e., maintain two files instead of one), and whether you use tools or IDE plugins that benefit from the annotations. Another important question is whether the developers who will use or maintain your code truly understand annotations.

    0 讨论(0)
  • 2020-12-23 13:58

    Maybe you have a problem with redundant annotations that are all over 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 evolves so slowly people are putting more features that are missing in the language into annotations. This is a good thing Java can be extended in some form and this is a bad thing as most of the annotations are some workaround and add complexity.

    0 讨论(0)
  • 2020-12-23 14:01

    Actually I think that the bad feeling in your gut against has more to do with Annotations like this mixing configuration with code.

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

    I think though that the correct approach here comes down to opinion and which method you prefer - I would predict that half the community would agree with the annotations approach and the other half would agree with the external configuration approach.

    0 讨论(0)
  • 2020-12-23 14:02

    Like many things, there are pros and cons. In my opinion, some annotations are fine, though sometimes it feels like there is a tendency to overuse annotations when a plain old function calling approach might be superior, and taken as a whole, this can unintentionally increase cognitive load because they increase the number of ways to "do stuff."

    Let me explain. For example, I'm glad you mentioned the @Transactional annotation. Most Spring developers probably are going to know about and use @Transactional. But how many of those developers know how @Transactional actually works? And would they know off the top of their head how to create and manage a transaction without using the @Transactional annotation? Using @Transactional makes it easier for me to use transactions in a majority of cases, but in particular cases when I need more fine-grained control over a transaction, it hides those details from me. So in a way it is a double edged sword.

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

    Finally, when annotations don't work, it can be harder to understand why and you can't just put a breakpoint on the annotation. (For instance, if you forgot the @EnableTransactionManagement on your config, what would happen?) You have to find the annotation processor and debug that. With a function calling approach, you can of course just put a breakpoint in the function.

    0 讨论(0)
提交回复
热议问题