Heim  >  Artikel  >  Java  >  Warum ich glaube, dass Lombok aus Java-Projekten ausgeschlossen werden sollte

Warum ich glaube, dass Lombok aus Java-Projekten ausgeschlossen werden sollte

PHPz
PHPzOriginal
2024-09-03 14:01:08720Durchsuche

Hallo, der heutige Artikel befasst sich mit einer scheinbar unpopulären Sichtweise und ich bin sicher, dass sie auf einigen Widerstand stoßen wird. Nur weil etwas technisch machbar ist, bedeutet das nicht automatisch, dass es nützlich oder geeignet ist. Daher werde ich versuchen zu begründen, warum ich glaube, dass die Verwendung von Lombok Ihren Code nachteilig beeinflussen könnte.

Die Magie enthüllen: Projekt Lombok verstehen

Bevor ich mich mit den weniger beliebten Details befasse, möchte ich kurz und prägnant erläutern, wie die Lombok-Bibliothek funktioniert.

Project Lombok fungiert als Bibliothek, die zur Kompilierungszeit Code in eine Klasse einfügt, was fast magisch erscheinen könnte. Um die Funktionsweise zu verstehen, ist es wichtig, den Java-Kompilierungsprozess zu verstehen. Die Java-Kompilierung umfasst drei Hauptphasen (Abbildung 1): Parsen und Eingeben, Annotationsverarbeitung sowie Analysieren und Generieren, wie im folgenden Diagramm dargestellt:

Why I Believe Lombok Should Be Discarded from Java Projects

Abbildung 1 – Abstrakter Syntaxbaum (AST)

  1. Parsen und eingeben:
    Dabei wandelt der Compiler Quelldateien in einen Abstract Syntax Tree (AST) um. Fehler werden nur bei ungültiger Syntax ausgegeben, nicht bei falscher Klassen- oder Methodenverwendung.

  2. Anmerkungsverarbeitung:
    In dieser Phase validieren benutzerdefinierte Annotationsprozessoren Klassen oder generieren neue Ressourcen wie Quelldateien. Dies kann einen neuen Kompilierungszyklus auslösen, wenn neue Quellen generiert werden.

  3. Analysieren und generieren:
    In dieser letzten Phase erzeugt der Compiler Bytecode aus dem AST, prüft auf fehlerhafte Referenzen, verifiziert logische Abläufe, führt eine Typlöschung durch und entzuckert syntaktischen Zucker.

Projekt Lombok fungiert als Annotationsprozessor und modifiziert den AST durch das Einfügen neuer Methoden, Felder oder Ausdrücke. Im Gegensatz zu typischen Prozessoren, die neue Quellen generieren, verändert Lombok bestehende Klassen, ein Unterschied, der es ihm ermöglicht, den generierten Bytecode direkt zu beeinflussen.

Der in J2SE 1.5 eingeführte AnnotationProcessor kann keine Änderungen an vorhandenen Dateien vornehmen. Es konnten nur neue Dateien oder Bytecode erstellt werden. Dies macht die Implementierung von Lombok interessant, da sie AnnotationProcessor verwenden, um die vorhandenen Java-Klassendateien während der Kompilierungsphase zu ändern. Hier finden Sie eine Übersicht über die
Kompilierungsprozess mit Lombok (Abbildung 2).

Why I Believe Lombok Should Be Discarded from Java Projects

Abbildung 2 – Kompilierungsprozess und Lombok

Der Fall gegen Lombok

Nachdem wir die Magie hinter Lombok verstanden haben, wollen wir uns mit den Gründen befassen, warum ich glaube, dass es Ihrer Codebasis schaden könnte.

Erhöhte Kompilierungszeit

Lomboks Vorgänge zur Kompilierungszeit verlängern zwangsläufig den Kompilierungsprozess, was in größeren Codebasen aufgrund der erhöhten erforderlichen AST-Verwaltung besonders ausgeprägt ist.

Fehlgeleitetes Sinn für Nutzen

Lombok bietet verschiedene Anmerkungen, die den Eindruck erwecken können, grundlegende Programmierherausforderungen gelöst zu haben. Ich werde einige dieser Anmerkungen besprechen, die mir häufig in der Codebasis begegnen.

  • @Builder-Anmerkung

Die @Builder-Annotation in Lombok vereinfacht die Objekterstellung durch das Builder-Muster und fügt eine Ebene der Bequemlichkeit hinzu, die zunächst ansprechend ist. Betrachten Sie dieses Beispiel:

@Data
@Builder
public class Course {
    public enum Type {
        ONLINE,
        ONSITE;

        @JsonValue
        @Override
        public String toString() {
            return super.toString().toLowerCase();
        }
    }

    private long id;
    private Type type;
}

Und seine Verwendung:

public class CourseCreator {

    public static Course createCourse(Enrollment enrollment, Registration registration) {
        Course.Type courseType = enrollment.getVenue().equals(registration.getVenue()) ? Course.Type.ONSITE : Course.Type.ONLINE;

        return Course.builder()
            .id(enrollment.getId())
            .type(courseType)
            .build();
    }

     public static void main(String[] args) {

        Registration registration = new Registration(); 
        Enrollment enrollment = new Enrollment();
        Course course = createCourse(enrollment, registration);
        System.out.println(course);
    }
}

Während das Builder-Muster effizient implementiert wird, werden entscheidende Fragen zur Integrität und Gültigkeit der erstellten Objekte aufgeworfen.

Welche Art von Kurs instanziieren wir, wenn wir .type() im Builder weglassen?

Diese Codezeile lässt sich kompilieren, aber wir fragen uns: Welche Art von Kurs haben wir eigentlich erstellt? Ist das eine gültige Kursinstanz?

Course.builder().id(1L).build();

Diese Bedenken deuten darauf hin, dass Entwickler, die möglicherweise von der Bequemlichkeit von Annotationen beeinflusst werden, möglicherweise die gründliche Domänenmodellierung übersehen, die für die Aufrechterhaltung der Integrität der Geschäftslogik erforderlich ist. Anstatt Lombok unser Design diktieren zu lassen, ist ein durchdachterer Ansatz von entscheidender Bedeutung, der die Ausrichtung auf die Geschäftsanforderungen gewährleistet.

Erwägen Sie eine Anpassung der Implementierung, um sicherzustellen, dass jede Kurserstellung klar und auf den Geschäftskontext beschränkt ist:

@Data
public class Course {
    private enum Type {
        ONLINE,
        ONSITE;

        @JsonValue
        @Override
        public String toString() {
            return super.toString().toLowerCase();
        }
    }

    public static Course online(long id) {
        return new Course(id, Type.ONLINE);
    }

    public static Course onsite(long id) {
        return new Course(id, Type.ONSITE);
    }

    private long id;
    private Type type;

    public boolean isOnline() {
        return Type.ONLINE.equals(this.type);
    }

    public boolean isOnsite() {
        return Type.ONSITE.equals(this.type);
    }
}

Durch Neugestaltung der Klasse:

public class CourseManagement {
    public static Course createAppropriateCourse(Enrollment enrollment, Registration registration) {
        return enrollment.getVenue().equals(registration.getVenue()) ? 
            Course.onsite(enrollment.getId()) : 
            Course.online(enrollment.getId());
    }

    public static void main(String[] args) {
        Registration registration = new Registration();
        Enrollment enrollment = new Enrollment();
        Course createdCourse = createAppropriateCourse(enrollment, registration);

        System.out.println(createdCourse);
    }
}

Das überarbeitete Design stellt sicher, dass die Erstellung von Kursobjekten explizit und narrensicher ist, indem es die eingeschränkten Auswahlmöglichkeiten der Domäne widerspiegelt und Mehrdeutigkeiten beseitigt.

Darüber hinaus stellen wir sicher, dass nur gültige Zustände offengelegt und manipuliert werden, indem wir die Type-Enumeration privat machen und klare, explizite Methoden wie isOnline() und isOnsite() bereitstellen, wodurch die Domänenintegrität gewahrt bleibt.

Through this thoughtful restructuring, we demonstrate that while tools like Lombok can significantly reduce boilerplate, they are not substitutes for careful design and a deep understanding of the domain. It underscores that Lombok should be employed judiciously, complementing rather than overshadowing robust architectural practices. This ensures that the elegance of our code does not come at the expense of its correctness and clarity.

  • Overreliance on @Setter and @Getter

The argument that getters and setters reduce boilerplate falls short when Java offers alternatives like the Record classes from Java 14.

@Data
public class Movie {
    private String title;
    private int releaseYear;
}

// Can be replaced with:
public record Movie(String title, int releaseYear) {}
  • Superintendent @NonNull

Having null in your code - aside from inputs is generally considered problematic and is often indicative of deeper design issues. The prevalent advice is to avoid returning null whenever possible. Instead, opt for alternatives such as returning non-null collections, utilizing null objects, or throwing exceptions to signify unusual or exceptional conditions. This strategic avoidance means null checks become redundant in most parts of your code.

To distance from Lombok's @NonNull annotation and ensure robustness in Java natively, the Objects.requireNonNull() method from the java.util.Objects class is incredibly useful.
This method streamlines null checking by ensuring that an object is not null, and it throws a NullPointerException with a clear message if it is. This explicit exception-throwing mechanism prevents latent null-related bugs from surfacing in runtime, promoting earlier detection during the development cycle. Here’s an example showing how this method can replace Lombok's functionality

Using Lombok's@NonNull:

public class NonNullExample {
    private Student student;

    public NonNullExample(@NonNull Student student) {
        this.student = student;
    }
}

Equivalent pure Java approach:

import java.util.Objects;

public class NonNullExample {
    private Student student;

    public NonNullExample(Student student) {
        this.student = Objects.requireNonNull(student, "Student cannot be null");
    }
}

This transition to native Java handling enhances code transparency by making the null-check explicit, which is advantageous for code maintenance and understanding.

Constructor Flexibility and Reusability

Constructors play a critical role in how classes interact within your software architecture. A well-designed class should have a variety of constructors that accommodate different use cases, promoting reusability and flexibility. If your constructors merely replicate field assignments, the underlying issue isn't the need to write boilerplate code; rather, it's the risk of fostering a non-reusable and inflexible design that Lombok cannot rectify. Proper constructor design allows a class to be integrated and utilized in a multitude of scenarios, enhancing the overall robustness and adaptability of your codebase.

Evaluating Boilerplate Code: The Lure of Lombok versus Modern Java Features

Lombok's popularity predominantly stems from its ability to reduce boilerplate code, particularly in domain-specific classes like transfer and data objects. While Lombok effectively diminishes the visible clutter by auto-generating necessary code like getters, setters, equals, hashCode, and toString methods, this convenience might obscure potential pitfalls. However, with the advent of Java Records introduced in Java 14, there is a preferable alternative that natively supports the concise declaration of immutable data carriers. Most integrated
development environments (IDEs) are also equipped to automatically generate these boilerplate codes with minimal user input, offering a balance between Lombok’s automation and the control of traditional Java coding.

Compatibility Concerns

Project Lombok's dependency on the underlying Java version poses a significant compatibility risk. As Java evolves, the Abstract Syntax Tree (AST) structure and its interpretation could change, necessitating continuous updates to Lombok to ensure compatibility. This creates a fragile dependency where upgrading to a newer Java version could potentially break your build if Lombok is not simultaneously updated to support these changes. The reliance on unofficial or private APIs to modify class definitions further exacerbates this issue because these APIs could be restricted or altered in future Java releases, threatening Lombok’s long-term viability.

Java-Standards

Die Verwendung von Lombok kann zu Komplikationen führen, wenn Projekte mit Tools erstellt werden, die nur Standard-Java-Compileroptionen verwenden. Wenn Ihr Code beispielsweise von Lombok generierte Getter und Setter verwendet, kann das direkte Kompilieren mit javac ohne Lombok-Vorverarbeitung zu Fehlern führen, die auf fehlende Methoden hinweisen. Auch wenn manche Lomboks Fähigkeit, Code einzuschleusen, für einen cleveren „Trick“ halten, ist es wichtig, die damit verbundenen Risiken und Alternativen kritisch zu bewerten. Der Kern des Problems liegt in der Tatsache, dass die Annotationsverarbeitungsspezifikation von Java das Ändern vorhandener Klassen während der Kompilierung offiziell nicht unterstützt. Der Einsatz dieser inoffiziellen Techniken macht Lombok anfällig für zukünftige Java-Updates, die möglicherweise seine Funktionen stören oder deaktivieren könnten.

Letztendlich unterstreichen diese Überlegungen, wie wichtig es ist, nicht nur die unmittelbaren Vorteile von Tools wie Lombok zu bewerten, sondern auch ihre langfristigen Auswirkungen auf Wartbarkeit, Kompatibilität und Ausrichtung auf Java-Standards. Da sich Java ständig weiterentwickelt, wird die Abhängigkeit von stabilen, standardisierten Funktionen immer wichtiger, um die Nachhaltigkeit und Zuverlässigkeit Ihrer Softwareprojekte sicherzustellen.

Abschluss

Lombok mag wie eine praktische Abkürzung für die Java-Entwicklung erscheinen, aber es verschiebt Java-Code in eine domänenspezifische Version, die ich gerne „Lombok Java“ nenne. Es ist wichtig zu erkennen, dass eine übermäßige Abhängigkeit von Lombok die Essenz von Java verschleiern kann, was möglicherweise zu Code führt, der weniger robust und ohne Lomboks Krücken schwieriger zu verwalten ist.

Wenn eine übermäßige Abhängigkeit von Lombok die Lösung für die Verwaltung Ihrer Codebasis ist, ist es möglicherweise an der Zeit, die zugrunde liegende Architektur und Praktiken neu zu bewerten. Die wahre Stärke von Java liegt in seiner Klarheit und Struktur, nicht in den von externen Bibliotheken bereitgestellten Verknüpfungen.

Wenn ich die Chance hätte, würde ich Lombok aus meinen Projekten streichen.

Das obige ist der detaillierte Inhalt vonWarum ich glaube, dass Lombok aus Java-Projekten ausgeschlossen werden sollte. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

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