代码之家  ›  专栏  ›  技术社区  ›  Gandalf

反对注释的论据

  •  50
  • Gandalf  · 技术社区  · 15 年前

    我的团队将迁移到Spring3.0,有些人希望开始将所有内容都迁移到注释中。我只是有种很糟糕的感觉(代码味道?)当我看到一个类有这样的方法时:(只是一个例子-不是所有真正的注释)

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

    我是落后于时代,还是其他人都觉得这是一个可怕的想法?而不是使用继承和多态等OO概念,现在一切都是通过约定或注释实现的。我就是不喜欢。必须重新编译所有代码来更改IMO的配置,这似乎是错误的。但似乎一切(尤其是春天)都是这样。我是应该“克服它”,还是应该向后推并尽量保持代码的注释自由?

    11 回复  |  直到 6 年前
        1
  •  20
  •   Koray Tugay    7 年前

    实际上,我认为您的直觉中的不良感觉更多地与注释有关,比如将配置与代码混合在一起。

    就我个人而言,我和您的感觉一样,我更喜欢将配置(如事务定义、路径元素、控制器应该映射到的URL等)放在代码基本身和外部SpringXML上下文文件之外。

    我认为,尽管这里的正确方法归结为观点和您更喜欢的方法——我预测一半的社区会同意注解方法,另一半会同意外部配置方法。

        2
  •  12
  •   Thomas Jung    15 年前

    也许你有问题 冗余注释 这些都在代码中。用 meta-annotations 可以替换多余的注释,并且您的注释至少是干的。

    从春季博客:

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

    因为Java发展的如此缓慢,人们把更多缺少语言的特征添加到注释中。这是一个很好的东西 扩展的 在某种形式下,这是一件坏事,因为大多数注释都是一些 解决办法 增加复杂性。

        3
  •  7
  •   Yishai    15 年前

    最初我也对注释持怀疑态度,但是看到它们在使用,它们可能是一件伟大的事情。它们也可以过度使用。

    关于注释,要记住的主要内容是它们是静态的。它们不能在运行时更改。任何其他配置方法(XML,代码中的自我描述,随便什么)都不会受到影响。我在这里看到过一些人,所以在注入测试配置的测试环境方面,Spring存在一些问题,并且必须使用XML来完成这项工作。

    XML既不是多态的,也不是继承的,或者其他任何东西,所以从这个意义上说,它不是后退的一步。

    注释的优点是,它可以让您对配置进行更多的静态检查,并且可以避免XML配置中的冗长和协调困难(基本上保持干燥)。

    就像XML一样,注释也可以被过度使用。主要是平衡每一种需求和优势。注释,在某种程度上,它们给了你更少的冗长和枯燥的代码,是一个需要利用的工具。

    编辑:关于注释替换接口或抽象类的注释,我认为这是合理的。 在框架边界。 在一个被成百上千个项目使用的框架中,如果不是成千上万个项目,那么拥有一个接口或基类确实会使事情变得复杂(尤其是一个基类,尽管您可以用注释来完成它,但是没有理由不能用常规接口来完成它。

    考虑JUnit4。以前,您必须扩展一个具有设置和下拉方法的基类。就我而言,那些是在接口上还是在基类中并不重要。现在我有了一个完全独立的项目,它有自己的继承层次结构,它们都必须遵守这个方法。首先,它们不能有自己冲突的方法名(在测试框架中没有什么大不了的,但你明白我的意思)。其次,您有一条调用super的链,因为所有方法都必须是耦合的。

    现在有了JUnit4,您可以在层次结构中的不同类中拥有不同的@before方法,并且它们可以相互独立。没有注释就没有同样干燥的方法来完成这一点。

    从JUnit开发者的角度来看,这是一场灾难。最好有一个定义好的类型,您可以调用安装程序和拆卸程序。但是框架的存在并不是为了框架开发者的方便,而是为了框架用户的方便。

    如果您的代码不需要关心类型(也就是说,在您的示例中,没有任何东西会真正使用控制器类型),那么所有这些都适用。然后,您甚至可以说实现框架的接口比添加注释更容易泄漏。

    然而,如果您要编写代码来在自己的项目中读取注释,那么请远离这里。

        4
  •  3
  •   Community Navdeep Singh    7 年前

    检查这些类似问题的答案

    What are the Pros/Cons of Annotations (non-compiler) compared to xml config files

    Xml configuration versus Annotation based configuration

    基本上可以归结为:两者都用。他们都有使用案例。不要为那些不需要重新编译任何东西就应该保持可配置的东西使用注释(尤其是那些你的用户不需要重新编译所有东西就可以配置的东西)。

        5
  •  3
  •   Uri    15 年前

    我个人认为注释已经接管了太多,并且已经从它们的原始和超级有用的目的(例如,指示重写方法等小事情)扩展到这个疯狂的元编程工具中。我觉得Java机制不够健壮,无法处理每种方法之前的注释群集。 例如,最近我正和JUnit注释作斗争,因为它们以我不喜欢的方式限制我。

    也就是说,根据我的经验,基于XML的配置也不是很好。所以引用南方公园的话,你可以在大灌肠和T*RD三明治之间做出选择。

    我认为您必须做的主要决定是,您是否更愿意对Spring配置进行非局域化(即,维护两个文件而不是一个),以及是否使用从注释中受益的工具或IDE插件。另一个重要的问题是,使用或维护代码的开发人员是否真正理解注释。

        6
  •  3
  •   aperezymadrid    13 年前

    我认为注释如果与度量一起使用是很好的。像@webservice这样的注释在部署和运行时做了很多工作,但它们不会干扰类。@cachexxx或@transactional显然会通过创建代理和大量工件来进行干扰,但我认为它们处于控制之下。

    当使用带有注释和CDI的Hibernate或JPA时,事情开始变得混乱起来。注释会增长很多。

    imo@service和@repository是应用程序代码中Spring的干扰。它们使您的应用程序依赖于弹簧,并且仅用于弹簧。

    Spring数据图是另一个例子。@例如,nodeEntity在构建时向类中添加方法以保存域对象。除非您有Eclipse和Spring插件,否则您将出错,因为这些方法在源代码中不存在。

    对象附近的配置有其优点,但也只有一个配置点。注释对度量值很好,但它们并不是对所有东西都有好处,而且当注释行和源代码行一样多时,它们绝对是不好的。

    我认为春天的道路是错误的,主要是因为在某些情况下,没有其他方法来做这种有趣的事情。这就好像Spring想要进行Xtreme编码,同时他们将开发人员锁定到Spring框架中。也许Java语言需要另一种方式来做一些事情。

        7
  •  3
  •   Scott Dagastino    12 年前

    注释必须谨慎使用。它们对一些人有好处,但对所有人都没有好处。至少XML配置方法将配置保存在一个文件(或多个文件)中,而不是分散在各处。这将引入(我喜欢称之为)糟糕的代码组织。如果配置分布在数百个文件中,您将永远看不到配置的完整图片。

        8
  •  2
  •   gx0r    8 年前

    像许多事情一样,也有利弊。在我看来,有些注释是很好的,尽管有时感觉在一个简单的旧函数调用方法可能更优越的情况下有过度使用注释的倾向,作为一个整体,这可能会无意中增加认知负荷,因为它们增加了“做事情”的方法的数量。

    让我解释一下。例如,我很高兴您提到了@transactional注释。大多数Spring开发人员可能会了解并使用@transactional。但有多少开发人员知道@transactional实际上是如何工作的?而且,他们是否会完全了解如何在不使用@transactional注释的情况下创建和管理事务?在大多数情况下,使用@transactional使我更容易使用事务,但在某些情况下,当我需要对事务进行更细粒度的控制时,它会将这些细节隐藏起来。所以在某种程度上,它是一把双刃剑。

    另一个例子是Spring配置类中的@profile。在一般情况下,可以更容易地指定要加载弹簧组件的配置文件。但是,如果您需要比仅仅指定一个要为其加载组件的概要文件列表更强大的逻辑,那么您必须自己获取环境对象并编写一个函数来实现这一点。同样,大多数Spring开发人员可能会熟悉@profile,但其副作用是他们对它如何工作的细节越来越不熟悉,比如环境。例如,profiles)函数。

    最后,当注释不起作用时,可能很难理解为什么,而且不能在注释上放置断点。(例如,如果您忘记了配置中的@EnableTransactionManagement,会发生什么情况?)您必须找到注释处理器并调试它。使用函数调用方法,您当然可以在函数中放置一个断点。

        9
  •  1
  •   matt    13 年前

    我认为这在某种程度上取决于您何时开始编程。就个人而言,我觉得他们很可怕。主要是因为它们有一些准“意义”,除非您碰巧知道所讨论的注释,否则您将无法理解。因此,它们自己形成了一种新的编程语言,使您远离Pojos。与(说)普通的OO代码相比。第二个原因-它们可以阻止编译器为您工作。如果我有一个很大的代码库,并且想要重构或者重命名一些东西,理想情况下,我希望编译器能够抛出所有需要更改的东西,或者尽可能多的改变。注释应该就是这样。注释。不是代码行为的中心。它们最初设计为在编译时可以选择性地省略,编译时会告诉您需要知道的所有信息。

    是的,我知道XML配置也受到同样的影响。这并没有使情况更糟,只是同样糟糕。不过,至少我可以假装忽略这一点——在每个方法或参数声明中,它都不会直视我的脸。

    考虑到这个选择,我实际上更喜欢那些可怕的旧J2EE远程/家庭接口等(最初受到春天人们的批评),因为至少这让我了解了发生了什么,而不必研究@CoolaidFrameworkThingy及其弱点。 框架人员的一个问题是,他们需要将您与他们的框架联系起来,以便使整个企业在财务上可行。这与设计一个好的框架是不一致的(也就是说,框架要尽可能独立和可从代码中移除)。

    然而,不幸的是,注释是时髦的。因此,除非您对代码评审/标准等有兴趣,否则很难阻止您的团队使用它们(同样,过时!)

    我读到斯特劳斯把C++注释掉了,因为他担心它们会被误用。有时候几十年来事情都是朝着错误的方向发展的,但是你可以希望事情能及时得到全面的发展。

        10
  •  1
  •   sweetjonnie    7 年前

    注释通常引入不属于此类依赖项的依赖项。

    我有一个类,碰巧有一些属性类似于RDBMS模式中表中的属性。该类是在创建时考虑了此映射。类和表之间显然存在关系,但我很高兴让类不包含声明该关系的任何元数据。这个类在完全不同的系统中引用表及其列是否正确?我当然不反对将二者联系起来并使彼此不受理解的外部元数据。我得到了什么?它不像源代码中的元数据提供类型安全性或映射一致性。任何可以分析JPA注释的验证工具都同样可以很好地分析Hibernate映射文件。注释没有帮助。

    在一个合同中,我创建了一个Maven模块,其中包含一个现有包中的接口实现包。不幸的是,这个新包是一个整体构建中许多目录中的一个;我把它看作是与其他代码不同的东西。尽管如此,团队使用的是类路径扫描,所以我必须使用注释才能将组件连接到系统中。这里我不需要集中配置;我只需要外部配置。XML配置不完美,因为它将依赖连线与组件实例化合并在一起。考虑到RodJohnson不相信基于组件的开发,这是公平的。尽管如此,我还是觉得注解对我没有帮助。

    让我们将它与一些不困扰我的东西进行对比:testng和junit测试。我在这里使用注释是因为我编写这个测试时知道我使用的是testng或junit。如果我用一个替换另一个,我理解我将不得不执行一个代价高昂的转换,这将接近于重写测试。

    无论出于什么原因,我接受testng、junit、qunit、unittest和nunit拥有我的测试类。在任何情况下,JPA或Hibernate都不拥有那些恰好映射到表的域类。在任何情况下,Spring都不拥有我的服务。我控制我的逻辑和物理包装,以便隔离依赖于两者的单元。我想确保离开一个人不会因为他留下的所有依赖而使我残废。说再见总比离开容易。在某些时候,离开是必要的。

        11
  •  0
  •   Sridhar Sarnobat    6 年前

    现在是2018年,这一点仍然相关。

    我对注解最大的问题是你不知道注解在做什么。你切断了一些代码,把它藏在别的地方。

    为了使语言更具声明性和程序性,引入了注释。但是,如果您要将大部分功能转移到注释中,那么您实际上是在将代码切换到另一种语言(而不是一种非常好的语言)。编译时检查很少。本文也提出了同样的观点: https://blog.softwaremill.com/the-case-against-annotations-4b2fb170ed67

    “把所有东西都转移到配置中,这样人们就不必学习如何编码”的整个启发式已经失控了。工程经理没有思考。

    例外情况:

    • 朱尼特
    • JAX-RS