Warum sollte ich nicht unveränderliche POJOs anstelle von JavaBeans verwenden?

Lesezeit: 9 Minuten

Benutzer-Avatar
Jonas

Ich habe jetzt ein paar Java-Anwendungen implementiert, bisher nur Desktop-Anwendungen. Ich ziehe es vor, unveränderliche Objekte zum Weitergeben der Daten in der Anwendung zu verwenden, anstatt Objekte mit Mutatoren (setters und Getter), auch JavaBeans genannt.

Aber in der Java-Welt scheint es viel üblicher zu sein, JavaBeans zu verwenden, und ich kann nicht verstehen, warum ich sie stattdessen verwenden sollte. Persönlich sieht der Code besser aus, wenn er sich nur mit unveränderlichen Objekten befasst, anstatt den Zustand ständig zu mutieren.

Unveränderliche Objekte werden auch in empfohlen Punkt 15: Veränderlichkeit minimieren, Effektives Java 2ed.

Wenn ich ein Objekt habe Person umgesetzt als JavaBean es würde so aussehen:

public class Person {
    private String name;
    private Place birthPlace;

    public Person() {}

    public setName(String name) {
        this.name = name;
    }

    public setBirthPlace(Place birthPlace) {
        this.birthPlace = birthPlace;
    }

    public String getName() {
        return name;
    }

    public Place getBirthPlace() {
        return birthPlace;
    }
}

Und das gleiche Person als implementiert unveränderlich Objekt:

public class Person {
    private final String name;
    private final Place birthPlace;

    public Person(String name, Place birthPlace) {
        this.name = name;
        this.birthPlace = birthPlace;
    }

    public String getName() {
        return name;
    }

    public Place getBirthPlace() {
        return birthPlace;
    }
}

Oder näher an einem struct in C:

public class Person {
    public final String name;
    public final Place birthPlace;

    public Person(String name, Place birthPlace) {
        this.name = name;
        this.birthPlace = birthPlace;
    }
}

Ich könnte auch Getter im unveränderlichen Objekt haben, um die Implementierungsdetails zu verbergen. Da ich es aber nur als struct Ich ziehe es vor, die “Getter” zu überspringen und es einfach zu halten.

Ich verstehe einfach nicht, warum es besser ist, JavaBeans zu verwenden, oder ob ich mit meinen unveränderlichen POJOs weitermachen kann und soll?

Viele der Java-Bibliotheken scheinen JavaBeans besser zu unterstützen, aber vielleicht wird mehr Unterstützung für unveränderliche POJOs im Laufe der Zeit immer beliebter?

  • ich denke du meinst Punkt 15: Veränderlichkeit minimierennicht *Unveränderlichkeit minimieren”

    – matt b

    18. August 2010 um 11:16 Uhr

  • @matt: Danke =) Ich habe es jetzt aktualisiert.

    – Jonas

    18. August 2010 um 11:21 Uhr

  • Ihr Ansatz zur Unveränderlichkeit ist großartig und erspart Ihnen viele Thread-Probleme. +1

    – Whiskysierra

    18. August 2010 um 17:38 Uhr

  • Sie benötigen einen Standardkonstruktor, wenn Sie JPA verwenden

    – Neil McGuigan

    8. Oktober 2013 um 18:24 Uhr

Benutzer-Avatar
NUR MEINE richtige MEINUNG

Bevorzugen Sie JavaBeans Wann

  • Sie müssen mit Umgebungen interagieren, die sie erwarten
  • Sie haben viele Eigenschaften, für die es unpraktisch wäre, die gesamte Initialisierung bei der Instanziierung durchzuführen
  • Sie haben einen Zustand, der teuer oder aus irgendeinem Grund unmöglich zu kopieren ist, aber eine Mutation erfordert
  • Sie denken, dass Sie irgendwann ändern müssen, wie auf Eigenschaften zugegriffen wird (z. B. Wechsel von gespeicherten zu berechneten Werten, Zugriffsberechtigung usw.)
  • Sie möchten sich an Codierungsstandards halten, die gedankenlos darauf bestehen, dass die Verwendung von JavaBeans irgendwie “objektorientierter” ist

Bevorzugen Sie unveränderliche POJOs, wenn

  • Sie haben eine kleine Anzahl einfacher Eigenschaften
  • Sie müssen nicht mit Umgebungen interagieren, die JavaBean-Konventionen übernehmen
  • Es ist einfach (oder zumindest möglich), den Zustand beim Klonen Ihres Objekts zu kopieren
  • Sie haben überhaupt nicht vor, das Objekt zu klonen
  • Sie sind sich ziemlich sicher, dass Sie nie ändern müssen, wie auf Eigenschaften wie oben zugegriffen wird
  • Es macht Ihnen nichts aus, sich darüber zu jammern (oder höhnisch zuzuhören), dass Ihr Code nicht ausreichend “objektorientiert” ist.

  • +1 für die Auflistung und fast -1 für Ihren Namen 🙂 Schließlich weiß jeder, dass es so ist mein Meinung, die richtig ist. Jeder wird natürlich im Discworld-Sinne definiert.

    – Extraneon

    18. August 2010 um 11:05 Uhr

  • Begrenzungsprüfung und Eingabevalidierung können im Konstruktor durchgeführt werden. Wenn die Eingabe ungültig oder außerhalb der Grenzen liegt, möchte ich kein Objekt erstellen.

    – Jonas

    18. August 2010 um 11:19 Uhr

  • Ihr zweiter Punkt in Bezug auf Bohnen ist nicht zugunsten von Bohnen, sondern zugunsten des Builder-Musters. Sie können immer noch ein unveränderliches Objekt konstruieren.

    Benutzer23743

    26. Oktober 2010 um 20:42 Uhr

  • Sie erwähnen das Threading mit den unveränderlichen POJOs nicht, was bei weitem einer der wichtigsten Gründe ist, sie zu verwenden. Ein weiterer wichtiger Punkt ist die Einfachheit – wenn sich ein Objekt nicht ändert, ist es auf lange Sicht einfacher, damit zu arbeiten. Außerdem müssen Sie sich bei unveränderlichen POJOs keine Gedanken über das Klonen des Objekts im Allgemeinen machen, Sie können es einfach weitergeben.

    – Abschreckung

    28. Oktober 2011 um 18:12 Uhr

  • Viele der Punkte, die hier zugunsten von Mutable sprechen, können, wie andere kommentiert haben, mit dem Builder-Pattern angegangen werden, und viele der Frameworks wurden kürzlich verbessert, um unveränderliche Objekte zu unterstützen. Meiner Meinung nach sind unveränderliche Objekte für die meisten Problemdomänenobjekte objektiv besser. Die Barriere für die Einführung ist die Java-Sprache selbst. Das Builder-Muster erfordert für die meisten Entwickler zu viel Wartungsaufwand. Dies kann mit “lombok project” etwas abgemildert werden, aber Sprachen mit umfassender Strukturierung und Destrukturierung auf der Grundlage von Mustervergleichen sind besser.

    – Schmied

    20. September 2016 um 19:57 Uhr

Benutzer-Avatar
Benjamin Wootton

Ich war überrascht, dass das Wort Faden tauchte in dieser Diskussion nirgendwo auf.

Einer der Hauptvorteile von unveränderlichen Klassen besteht darin, dass sie von Natur aus Thread-sicherer sind, da kein veränderlicher, gemeinsam genutzter Zustand vorhanden ist.

Dies erleichtert nicht nur Ihre Codierung, sondern bietet Ihnen als Nebeneffekt auch zwei Leistungsvorteile:

  • Weniger Synchronisierungsbedarf.

  • Mehr Spielraum für die Verwendung von Final-Variablen, was spätere Compiler-Optimierungen erleichtern kann.

Ich versuche wirklich, mich eher auf unveränderliche Objekte als auf Klassen im JavaBean-Stil zuzubewegen. Das Offenlegen der Eingeweide von Objekten über Getter und Setter sollte wahrscheinlich nicht die Standardwahl sein.

Benutzer-Avatar
Andrej Fierbinteanu

Nun, es hängt davon ab, was Sie versuchen zu tun. Wenn Sie mit einer persistenten Schicht arbeiten und einige Zeilen aus der Datenbank in ein POJO abrufen und eine Eigenschaft ändern und zurückspeichern möchten, wäre die Verwendung des JavaBean-Stils besser, insbesondere wenn Sie viele Eigenschaften haben.

Bedenken Sie, dass Ihre Person viele Felder wie Vor-, Zweit- und Nachname, Geburtsdatum, Familienmitglieder, Ausbildung, Beruf, Gehalt usw. hat.

Und diese Person ist zufällig eine Frau, die gerade geheiratet und akzeptiert hat, dass ihr Nachname geändert wird, und Sie müssen die Datenbank aktualisieren.

Wenn Sie unveränderliches POJO verwenden, rufen Sie ein Person-Objekt ab, das sie darstellt, dann erstellen Sie ein neues Person-Objekt, an das Sie alle Eigenschaften übergeben, die Sie nicht geändert haben, sowie den neuen Nachnamen, und speichern Sie es.

Wenn es sich um eine Java-Bean handelt, können Sie einfach setLastName() ausführen und speichern.

Es ist ‘Veränderlichkeit minimieren’ und nicht ‘Veränderliche Objekte niemals verwenden’. Einige Situationen funktionieren besser mit veränderlichen Objekten, es ist wirklich Ihre Aufgabe zu entscheiden, ob es besser zu Ihrem Programm passt, ein Objekt veränderbar zu machen oder nicht. Sie sollten nicht immer sagen „muss unveränderliche Objekte verwenden“, sondern sehen, wie viele Klassen Sie unveränderlich machen können, bevor Sie anfangen, sich selbst zu verletzen.

  • Aber Ihr Beispiel ist fast nie das, was in “echten” Anwendungen getan werden muss. Normalerweise muss Ihr aktualisiertes Datenobjekt an ein Validierungsframework (Hibernate Validator, Spring Validator usw.) übergeben werden, wo das Objekt verschiedenen Operationen unterzogen wird, die möglicherweise von verschiedenen Entwicklern geschrieben wurden. Wenn das Objekt veränderlich ist, wissen Sie nicht, ob Sie mit denselben Daten arbeiten, die übergeben wurden (wenn eine vor Ihrer durchgeführte Validierung das Objekt an Ort und Stelle verändert hat). Es macht den Validierungsprozess weniger bestimmend, abhängiger von einer strengen Ordnung und unvergleichbar.

    – Schmied

    20. September 2016 um 20:24 Uhr


  • Darüber hinaus verfügt eine “echte” Anwendung wahrscheinlich über eine Art In-Memory- oder verteilten Cache (EHCache usw.), der Ihre Domänenobjekte enthält. Wenn Sie wissen, dass Ihre Objekte unveränderlich sind, müssen Sie sich nicht den Overhead von Copy-on-Read leisten. Sie können das In-Memory-Objekt sicher abrufen und verwenden, ohne sich Gedanken über die Cache-Integrität machen zu müssen. IMHO, für Geschäftsdomänenobjekte dieser Art möchten Sie immer unveränderliche Objekte. Veränderliche Objekte sind für den lokalen Geltungsbereich und einige andere Spezialfälle in Ordnung, auf die ich hier nicht eingehen kann.

    – Schmied

    20. September 2016 um 20:46 Uhr


Benutzer-Avatar
helios

Zusammenfassend andere Antworten denke ich, dass:

  • Unveränderlichkeit erleichtert Korrektheit (Strukturen können als Referenz übergeben werden und Sie wissen, dass nichts durch einen fehlerhaften/böswilligen Client zerstört wird) und Code-Einfachheit
  • Veränderlichkeit erleichtert Homogenität: Spring und andere Frameworks erstellen ein Objekt ohne Argumente, legen Objekteigenschaften fest und voi la. Machen Sie auch Schnittstellen einfacher, indem Sie dieselbe Klasse zum Übergeben von Daten und Speichern von Änderungen verwenden (Sie brauchen nicht get(id): Client und save(MutableClient)wobei MutableClient ein Nachkomme von Client ist.

Wenn es einen Zwischenpunkt gäbe (erstellen, Eigenschaften festlegen, unveränderlich machen), würden Frameworks vielleicht eher einen unveränderlichen Ansatz fördern.

Wie auch immer, ich schlage vor, in unveränderlichen Objekten als “schreibgeschützte Java Beans” zu denken, um den Punkt zu betonen, dass, wenn Sie ein guter Junge sind und diese gefährliche setProperty-Methode nicht berühren, alles in Ordnung sein wird.

Ab Java 7 können Sie unveränderliche Beans haben, das Beste aus beiden Welten. Verwenden Sie die Anmerkung @ConstructorProperties für Ihren Konstruktor.

public class Person {
    private final String name;
    private final Place birthPlace;

    @ConstructorProperties({"name", "birthPlace"})
    public Person(String name, Place birthPlace) {
        this.name = name;
        this.birthPlace = birthPlace;
    }

    public String getName() {
        return name;
    }

    public Place getBirthPlace() {
        return birthPlace;
    }
}

Ich glaube ehrlich gesagt nicht, dass unveränderliche Objekte allzu populär werden.

Ich sehe zwar die Vorteile, aber Frameworks wie Hibernate und Spring sind derzeit sehr im Trend (und das aus gutem Grund), und sie funktionieren wirklich am besten mit Beans.

Ich denke also nicht, dass Unveränderlichkeit schlecht ist, aber es würde sicherlich Ihre Integrationsmöglichkeiten mit aktuellen Frameworks einschränken.

BEARBEITEN Die Kommentare veranlassen mich, meine Antwort etwas zu präzisieren.

Es gibt sicherlich Problembereiche, wo Unveränderlichkeit sehr nützlich ist und auch genutzt wird. Aber ich denke, der aktuelle Standard scheint veränderlich zu sein, da dies meistens erwartet wird, und nur unveränderlich, wenn dies einen klaren Vorteil hat.

Und obwohl es tatsächlich möglich ist, Konstruktoren mit Argumenten in Spring zu verwenden, scheint es als eine Möglichkeit gedacht zu sein, Legacy- und/oder Drittanbieter-Code mit Ihrem schönen, brandneuen Spring-Code zu verwenden. So habe ich es zumindest der Dokumentation entnommen.

Benutzer-Avatar
Rohitdev

Unveränderlich in Bezug auf die Programmierung in Java: Etwas, das einmal erstellt wurde, sollte niemals eine Zustandsänderung aufweisen, weder erwartet noch unerwartet!

Diese Technik ist bei der defensiven Programmierung nützlich, bei der eine andere Entität keine Änderung des Zustands herbeiführen kann.

Beispiele, bei denen Sie keine Änderung erwarten: Externe Systeme (Single- oder Multi-Threading), die Referenzen von Ihrer Ebene erhalten und auf das Objekt einwirken und es wissentlich oder unwissentlich ändern. Nun könnte es sich um ein POJO oder eine Sammlung oder eine Objektreferenz handeln und Sie erwarten keine Änderung daran oder Sie möchten die Daten schützen. Sie würden das Objekt definitiv als Verteidigungstechnik unveränderlich machen

Beispiele, bei denen Sie Änderungen erwarten: Unveränderlichkeit ist wirklich nicht erforderlich, da dies die richtigen Programmierverfahren behindert.

1216600cookie-checkWarum sollte ich nicht unveränderliche POJOs anstelle von JavaBeans verwenden?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy