Heim  >  Artikel  >  Java  >  Die bösesten Anmerkungen in Java

Die bösesten Anmerkungen in Java

黄舟
黄舟Original
2017-02-20 10:09:341521Durchsuche

Dieser Artikel wurde ursprünglich von MaNong.com – Sun Tenghao übersetzt. Bitte lesen Sie die Nachdruckanforderungen am Ende des Artikels, um an unserem kostenpflichtigen Beitragsplan teilzunehmen.

Als Java 1.5 Annotationen einführte, hatten Unternehmensentwickler große Erwartungen, die Entwicklung von EJB und anderen Unternehmensprodukten zu vereinfachen. Sie können sich einen Artikel aus derselben Zeit ansehen: Simplifying Enterprise Java Development with EJB 3.0.

Seitdem hat der Einsatz von Annotationen in Java-Unternehmen jedoch einige unvorhergesehene Konsequenzen und Nebenwirkungen gehabt, von denen einige heute noch nicht einmal bemerkt werden. Glücklicherweise bleiben nicht alle Nebenwirkungen unbemerkt. Es gibt viele wertvolle Kommentare zu StackOverflow mit dem Titel „Warum Java-Annotationen?“ und „Magie ist böse?“. „Anmerkungen … gut, schlecht oder schlechter?“

Die bösesten Anmerkungen in Java

Nicht alle Anmerkungen sind gleich

Während viele der obigen Diskussionen wertvolle Punkte enthalten, sind nicht alle Anmerkungen gleich das gleiche.

Es gibt zwei Arten von Anmerkungen. Der Unterschied besteht darin, ob sie das Programm zur Laufzeit beeinflussen. Lassen Sie uns zunächst über die harmlosen sprechen, die zur Laufzeit keine Auswirkungen auf den Code haben. Die anderen sind die schädlichen, die das Laufzeitverhalten verändern. Zu den harmlosen Anmerkungen gehören @Deprecated, @Override, @SuppressWarnings usw. Zu den schädlichen Annotationen gehören @Entity, @Table, @PostConstruct, @ApplicationScoped usw.

Unter den harmlosen Anmerkungen gibt es eine kleine Reihe von Anmerkungen, die sehr nützlich sind. Einige ermöglichen das Abfangen von Fehlern während der Kompilierung (statische Überprüfung) oder bieten Sicherheitsgarantien. Einige nützliche Anmerkungen sind: @Override, @NonNull/@Nullable from (Checker Framework) usw.

Warum sind schädliche Anmerkungen schlecht?

Wir haben einige schädliche Anmerkungen definiert. Warum sollten wir deren Verwendung vermeiden?

Stellen Sie sich eine Standard-Java-Datenklasse mit einer @PostConstruct-Methode vor. Diese Annotation gibt an, dass die annotierte Methode aufgerufen werden soll, nachdem das Objekt erstellt wurde. Diese Funktionalität wird von der JVM nicht übernommen, daher ruft die Date-Klasse implizit unbekannte Frames und Container ab, ohne semantisch etwas zu unternehmen. Was passiert, wenn dieser Code in keinem Container läuft, sondern nur in der JVM? Diese Annotation verringert die Wiederverwendbarkeit dieser Klasse erheblich. Darüber hinaus werden Unit-Tests überall dort, wo Date verwendet wird, zu einem Albtraum, da Sie jedes Mal sicherstellen müssen, dass die Nachkonstruktion korrekt gebunden wird, und ein kompatibler Container verspottet werden muss. Das ist ein bisschen lächerlich, eine Date-Klasse braucht einen Container, um ausgeführt zu werden, aber das ist tatsächlich die schädliche Auswirkung von Annotationen auf Klassen, Methoden und Parameter.

Es ist unbestreitbar, dass Geschäftslogik oft komplex ist und mehr Abhängigkeiten und Beziehungen erfordert als nur eine einfache Date-Klasse. Es gibt jedoch keinen Grund, einer Klasse explizit oder implizit unnötige Abhängigkeiten oder Einschränkungen hinzuzufügen. Schädliche Annotationen sind genau das: Abhängigkeiten und Einschränkungen.

Unternehmensfallen

Leider werden in Java Enterprise 5 in großem Umfang schädliche Behauptungen legitimiert. Um frühe Usability-Probleme mit Unternehmens-APIs zu beheben, wurden Annotationen verwendet, um redundante und schwer zu verwendende Teile des Systems zu verbergen. Der neue JEE 5 wurde als „leicht“ und „einfach“ gelobt, und das scheint auch oberflächlich betrachtet so zu sein. Doch ein kleiner, aber entscheidender Missbrauch breitete sich aus.

@Stateless
public class DocumentRepository {
   public Document getDocument(String title) {
      ...
   }
   ...
}


Wenn Sie ein Stateless EJB erhalten möchten, müssen Sie „nur“ die Annotation @Stateless für die Klasse deklarieren. Tatsächlich sind zum Schreiben dieser Klasse nur wenige Klicks erforderlich. Beachten Sie jedoch, dass die schädlichen Anmerkungen in dieser Klasse an Hunderte von Seiten Dokumentation gebunden sind und nur auf einem Megabyte-Anwendungsserver ausgeführt werden können. Wie kann man das „leicht“ nennen? Daher ist diese Annotation nur ein Platzhalter für den Java-Code, der tatsächlich geschrieben werden muss, und der Code muss noch in irgendeiner Form vorhanden sein. Jetzt ist es nur noch unter Anmerkungen versteckt.

Leider ist dieser Workaround als Muster bekannt und schädliche Annotationen sind mittlerweile weit verbreitet: JPA, CDI, Common Annotations, JAXB usw.

Schädliche Anmerkungen erscheinen manchmal an den falschen Stellen

Da Anmerkungen häufig als Entwicklungsumgebung verwendet werden, werden schädliche Anmerkungen manchmal als Prinzip der Einzelverantwortung (Prinzip der Einzelverantwortung) behandelt. oder Best Practices für die Trennung von Belangen.

Betrachten wir das folgende CDI-Beispiel:

@ApplicationScoped
public class DocumentFormatter {
   ...
}


Die obige Anmerkung beschreibt, dass diese Klasse ein CDI-Bean sein sollte, was bedeutet, dass sie Can sein sollte nur von CDI instanziiert werden, wodurch sichergestellt wird, dass nur eine Instanz pro Anwendung vorhanden ist.

Diese Nachrichten gehören nicht zu dieser Kategorie. Dieser Dienst hat keinen funktionalen Einfluss auf seine Rolle in der aktuellen Anwendung. Hier gibt es zwei offensichtliche Bedenken.

Ein einfaches Beispiel für JPA:

@Entity
@Table("PERSON")
public class Person {
   ...
}


问题在于这种类往往是”领域对象(domain objects)”,它们直接将领域模型持久化。更糟的是,数据传送对象(DTO)用来在对象之间传送数据,使得整个构造变得脆弱,因为对象间耦合过于紧密。不管怎样,这是一种错误的方式。

所有的这些附加的功能和(或)信息应该从这些类中分离出来,但是它们却悄悄混在一起,因为它们”只不过”是注解。

有害的注解有时蔓延

注解有时会传染其他对象。回顾上面那个CDI Bean。每个使用它的对象,每个依赖它的对象现在都拥有一个CDI注解,否则依赖关系树就不会构建成功。

@Entity注解也一样。因为对象之间的关系,其他对象也通过注解持久化,很快所有的持久化对象都会有这个注解。我们无法使用原生的第三方对象(除非序列化或包装它们),我们无法使用其他持久化机制(比如用NoSQL DB存放对象)。

这些注解使得这些对象无法复用。它们只能在一个严格的、受控制的、不透明的环境中使用,不能和任何东西整合。

有什么替代品?

是XML吗?当然不是,至少对于上面的例子来说不是。

Spring框架使用配置来管理对象,因此可以用XML当做配置文件。然而,是否某个依赖需要在运行期改变,而不通过重新编译?如果不需要,那么很难说配置应该用另一门语言来表示,尤其重构困难、测试困难、管理需要特殊工具。

真正的替代品当然是好的Java代码,正确封装并解耦的。是的,用代码来管理对象,尽管有时被当做样板(boilerplate),但并不算糟糕。它带来一些好处,比如让代码可读、可调试、可重构。只有那些长片的、复杂的、冗余的样板是糟糕的,比如“关于EJB 2.0”。但是解决方案并不是摆脱所有的样板或用另一种语言隐藏样板,而是简单干净的架构,直接而不多余的信息,简单并合适的方式来面向对象。

这也适用于JPA、Spring和其他东西。误用注解来表示功能会发生Stcakoverflow上这个问题“Arguments Against Annotations”,为什么不用已有的工具呢:比如Java语言本身和编译器,来解决这类问题,面向对象和软件最佳实践。

总结

如果注解在代码运行期加上了额外功能和约束,那它是有害的。这很糟糕,因为它隐藏了类或方法的切面,使之难懂、难复用、难重构、难测试。

不幸的是Java Enterprise不理睬Java开发者社区中发对注解的声音。所以企业级Java和其他”官方”框架更不可能重视这类问题。

至少我们可以持续关注有害的注解,如果可能尽量避免使用,编写新的框架和软件替换掉注解,不会出现有害注解所带来的问题。

 以上就是Java中万恶的注解 的内容,更多相关内容请关注PHP中文网(www.php.cn)!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn