Frage

Diese Frage hat hier bereits eine Antwort:

Allen Holub schrieb Folgendes,

Sie können kein Programm ohne Kopplung haben. Trotzdem können Sie die Kopplung erheblich minimieren, indem Sie Sklaven nach OO-Vorschriften (objektorientierte) Vorschriften sklavisch folgen (das Wichtigste ist, dass die Implementierung eines Objekts vollständig vor den Objekten verborgen sein sollte, die sie verwenden). Zum Beispiel sollten die Instanzvariablen eines Objekts (Mitgliedsfelder, die keine Konstanten), immer privat sein. Zeitraum. Keine Ausnahmen. Je. Ich meine es so. (Sie können gelegentlich geschützte Methoden effektiv anwenden, aber geschützte Instanzvariablen sind ein Gräuel.)

Was vernünftig klingt, aber er fährt fort, zu sagen,

Du solltest Verwenden Sie niemals GET/Set -Funktionen Aus dem gleichen Grund sind sie nur übermäßig komplizierte Möglichkeiten, ein Feld öffentlich zu machen ).

Das klingt ehrlich gesagt nur verrückt für mich.

Ich verstehe das Prinzip der Informationen, die sich verstecken, aber ohne Zubehör und Mutatoren konnten Sie Java -Bohnen überhaupt nicht verwenden. Ich weiß nicht, wie Sie ein MVC -Design ohne Zubehör im Modell verfolgen würden, da das Modell kann nicht Seien Sie verantwortlich für die Aussicht.

Ich bin jedoch ein jüngerer Programmierer und erfahre jeden Tag mehr über objektorientiertes Design. Vielleicht kann jemand mit mehr Erfahrung in diesem Thema wiegen.

Allen Holubs Artikel als Referenz


Verwandte Fragen:

War es hilfreich?

Lösung

Ich habe kein Problem damit, dass Holub Ihnen sagt, dass Sie im Allgemeinen vermeiden sollten, die zu ändern Zustand eines Objekts, aber stattdessen auf integrierte Methoden (Ausführung von Verhaltensweisen) greifen, um dieses Ziel zu erreichen. Wie Corletk betont, ist es Weisheit, lange und intensiv über die höchste Abstraktionsniveau nachzudenken und nicht nur gedankenlos mit Gettern/Setter zu programmieren, die Sie nur mit einer Kapselung beenden können.

Ich habe jedoch große Probleme mit jedem, der Ihnen sagt, dass Sie Setter "niemals" verwenden sollten oder "niemals" auf primitive Typen zugreifen sollten. In der Tat der Aufwand, um diese Reinheit zu erhalten alle Fälle können und werden am Ende mehr Komplexität in Ihrem Code verursachen als die Verwendung von entsprechend implementierten Eigenschaften. Sie müssen nur genug Sinn haben, um zu wissen, wann Sie die Regeln für den kurzfristigen Gewinn auf Kosten langfristiger Schmerzen umgehen.

Holub vertraut Ihnen nicht, dass Sie den Unterschied kennen. Ich denke, dass das Wissen, den Unterschied zu kennen, Sie zu einem Profi macht.

Andere Tipps

Lesen Sie diesen Artikel sorgfältig durch. Holub drückt den Punkt, dass Getter und Setter ein böses "Standard -Antipattern" sind, eine schlechte Angewohnheit, in die wir beim Entwerfen eines Systems eintreten. weil wir können.

Der Denkprozess sollte in den Bereichen Sekt sein; Was macht dieses Objekt? tun? Was sind seine Verantwortung? Was sind ihr Verhalten? Was weiß es? Wenn Sie lange und intensiv an diesen Fragen denken, führt Sie natürlich zum Entwerfen von Klassen, die die höchstmögliche Schnittstelle aufdecken.

Ein Auto ist ein gutes Beispiel. Es enthüllt eine gut definierte, standardisierte hochgradige Schnittstelle. Ich kümmere mich nicht darum setSpeed(60)... ist das mph oder km/h? Ich beschleunige, Kreuzfahrt, verlangsame. Ich muss nicht über die Details nachdenken setSteeringWheelAngle(getSteeringWheelAngle()+Math.rad(-1.5)), Ich habe gerade turn(-1.5), und die Details werden gepflegt unter der Haube.

Es läuft auf "Sie können und sollten herausfinden, wofür jede Klasse verwendet wird, was es tut, was es darstellt, und die höchstmögliche Schnittstelle auf der Erfüllung dieser Anforderungen enthüllen Der Programmierer ist nur faul, um die Analyse durchzuführen, um genau zu bestimmen, was jede Klasse ist und ist nicht, und so gehen wir den Weg von "Es kann alles tun". Getter und Setter sind böse!

Manchmal sind die tatsächlichen Anforderungen an eine Klasse im Voraus unerkennbar. Das ist cool, nur Cop-out und verwenden Sie vorerst Getter/Setter-Antipattern. Wenn Sie jedoch durch Erfahrung wissen, wofür die Klasse verwendet wird, möchten Sie wahrscheinlich die schmutzige Schnittstelle mit niedriger Ebene aufräumen. Refactoring basierend auf "Sachen, die Sie sich wünschen, Sie wussten, wenn Sie den Sauger in erster Linie schreiben" ist für den Kurs ein Par. Sie müssen nicht alles wissen, um einen Start zu haben.

Das ist die Mentalität, die er fördert. Getters und Setter sind eine einfache Falle, in die man fallen kann.

Ja, Bohnen erfordern im Grunde genommen Getter und Setter, aber für mich ist eine Bohne ein Sonderfall. Bohnen repräsentieren Substantive, Dinge, materielle identifizierbare (wenn nicht physische) Objekte. Nicht viele Objekte haben tatsächlich automatische Verhaltensweisen. In den meisten Fällen werden die Dinge von externen Kräften, einschließlich Menschen, manipuliert, um sie produktive Dinge zu machen.

daisy.setColor(Color.PINK) Macht perfekt Sinn. Was kannst du sonst noch tun? Vielleicht ein vulkanischer Mind-Meld, um die Blume zu machen wollen rosa sein? Hmmm?

Getter und Setter haben ihr? Böses? Platz. Es ist nur, wie alle wirklich guten Dinge, wir neigen dazu, sie zu überbeanspruchen, weil sie sicher und vertraut sind, ganz zu schweigen von einfach, und deshalb könnte es besser sein, wenn Noobs nicht von ihnen gesehen oder hören, zumindest bis sie ' D beherrschte das Ding-Meld-Ding.

Ich denke, was Allen Holub zu sagen versuchte, umformuliert Dies Artikel ist der folgende.

Getter und Setter können nützlich für Variablen sein, die Sie speziell einkapseln möchten, müssen sie jedoch nicht für alle Variablen verwenden. In der Tat ist die Verwendung von für alle Variablen ein böser Code -Geruch.

Die Probleme mit den Problemen, die Programmierer haben, und Allen Holub war recht, um darauf hinzuweisen, dass sie manchmal Getter/Setter für alle Variablen verwenden. Und der Zweck der Verkapselung geht verloren.

(Beachten Sie, dass ich das aus einem .NET "Eigenschaftswinkel" komme)

Einfach - ich stimme ihm nicht zu; Er macht eine große Aufregung darüber, dass die Rückkehrtypen eine schlechte Sache sind, weil es Ihren Anrufcode brechen kann - aber exakt Das gleiche Argument würde für Methodenargumente gelten. Und wenn Sie auch keine Methoden verwenden können?

Ok, Methodenargumente könnten als Verbreiterung von Conversions geändert werden, aber ... genau warum ... auch beachten Sie das in C# der var Schlüsselwort könnte einen Großteil dieser wahrgenommenen Schmerzen mildern.

Accessors sind nicht ein Implementierungsdetail; Sie sind die öffentliche API / den öffentlichen Vertrag. Ja, wenn Sie die Verhütung brechen, haben Sie Probleme. Wann wurde das eine Überraschung? Ebenso ist es nicht ungewöhnlich, dass Zubehör nicht trivial ist - dh sie tun mehr als nur Wickelfelder; Sie führen Berechnungen, Logikprüfungen, Benachrichtigungen usw. durch und ermöglichen interface basierte Zustandsstraktionen. Oh, und Polymorphismus - usw.

Betreff der ausführliche Natur von Accessors (P3? 4?) - in C#: public int Foo {get; private set;} - Job erledigt.

Letztendlich ist der gesamte Code ein Mittel, um unsere Absicht dem Compiler auszudrücken. Immobilien lassen mich dies in einer typen sicheren, vertragsbasierten, überprüfbaren, erweiterbaren, polymorphen Art und Weise tun-danke. Warum muss ich das "reparieren"?

Getters und Setter werden nur eine Maske verwendet, um eine private Variable öffentlich zu machen.

Es macht keinen Sinn, das zu wiederholen, was Holub bereits gesagt hat, aber der Kern davon ist, dass Klassen Verhalten darstellen und nicht nur angeben sollten.

Ich habe zusätzliche Googeln auf Allen Holub gemacht, scheint seinen Anteil an Gegnern in der Java -Community zu haben.

Der letzte ist besonders gezeigt. Der Text des Kommentators ist kursiv.

Obwohl GetIdentity mit "GET" beginnt, ist es kein Accessor, da es nicht nur ein Feld zurückgibt. Es gibt ein komplexes Objekt zurück, das ein angemessenes Verhalten hat

Oh, aber warte ... dann ist es in Ordnung, Zubehör zu verwenden, solange Sie Objekte anstelle von primitiven Typen zurückgeben? Das ist eine andere Geschichte, aber für mich ist es genauso dumm. Manchmal brauchen Sie ein Objekt, manchmal benötigen Sie einen primitiven Typ.

Außerdem bemerke ich, dass Allen seine Position seit seiner vorherigen Spalte zum selben Thema radikal gemildert hat, in dem das Mantra "nie Zubehör" keine einzige Ausnahme erlitten hat. Vielleicht erkannte er nach ein paar Jahren, dass die Zubehör doch einen Zweck erfüllen ...

Denken Sie daran, dass ich keinen UI -Code in die Geschäftslogik eingebaut habe. Ich habe die UI -Ebene in Bezug auf AWT (abstraktes Fenster -Toolkit) oder Swing geschrieben, bei denen beide Abstraktionsschichten sind.

Gut. Was ist, wenn Sie Ihre Bewerbung auf SWT schreiben? Wie "Abstract" ist in diesem Fall wirklich AWT? Stellen Sie sich einfach vor: Dieser Rat führt Sie einfach dazu, UI -Code in Ihre Geschäftslogik zu schreiben. Was für ein großes Prinzip. Schließlich ist es nur mindestens zehn Jahre her, seit wir diese Praxis als eine der schlechtesten Designentscheidungen identifiziert haben, die Sie in einem Projekt treffen können.

Mein Problem ist, dass ein Anfängerprogrammierer manchmal auf Artikel im Internet stolpert und ihnen mehr Glauben verleiht als ich es sollte. Vielleicht ist dies einer dieser Fälle.

Wenn mir solche Ideen präsentiert werden, schaue ich mir gerne Bibliotheken und Frameworks an, die ich benutze und die ich gerne benutze.

Obwohl einige nicht zustimmen, mag ich die Java -Standard -API. Ich mag auch das Frühlingsgerüst. Wenn Sie sich die Klassen in diesen Bibliotheken ansehen, werden Sie feststellen, dass es sehr seltene Setter und Getter gibt, die nur eine interne Variable aufdecken. Es gibt Methoden genannt Getx, aber das bedeutet nicht, dass es im konventionellen Sinne ein Getter ist.

Ich denke, er hat einen Punkt, und es ist Folgendes: Jedes Mal, wenn Sie "Getter/Setzer generieren" in Eclipse (oder Ihrer IDE Ihrer Wahl) wählen, sollten Sie einen Schritt zurücktreten und sich fragen, was Sie tun. Ist es wirklich angemessen, diese interne Darstellung aufzudecken, oder habe ich mein Design zu einem Schritt durcheinander gebracht?

Ich glaube nicht, dass er sagt, dass er niemals GET/SET verwendet, sondern dass es nicht besser ist, das Feld zu verwenden, als das Feld öffentlich zu machen (z.

Wenn GET/SET verwendet wird, begrenzt es die Informationen, die OO versteckt haben, was Sie möglicherweise in eine schlechte Schnittstelle sperrten.

Im obigen Beispiel ist der Name eine Zeichenfolge; Was ist, wenn wir das Design später ändern möchten, um mehrere Namen hinzuzufügen? Die Schnittstelle enthüllt nur eine einzelne Zeichenfolge, sodass wir nicht mehr hinzufügen können, ohne die vorhandene Implementierung zu brechen.

Wenn Sie jedoch anstatt GET/Set zu verwenden, hatten Sie zunächst eine Methode wie Add (String -Name), intern können Sie den Namen einzigartig verarbeiten oder zu einer Liste hinzufügen oder was nicht, und rufen Sie die Methode hinzufügen so oft auf, wie Sie es hinzufügen möchten. Weitere Namen.

Das OO -Ziel ist es, mit einer Abstraktionsniveau zu gestalten. Entdecken Sie nicht mehr Details als Sie absolut müssen.

Wenn Sie gerade einen primitiven Typ mit einem Get/Set eingewickelt haben, haben Sie diesen Grundsatz gebrochen.

Dies ist natürlich, wenn Sie an die OO -Ziele glauben; Ich finde, dass die meisten nicht wirklich, nicht wirklich, sie verwenden Objekte nur als überzeugende Methode, um Funktionscode zu gruppieren.

Öffentliche Variablen sind sinnvoll, wenn die Klasse nichts weiter als ein Datenpaket ohne wirkliche Kohärenz ist oder wenn sie wirklich, wirklich elementar ist (wie eine Punktklasse). Wenn es in einer Klasse eine Variable gibt, von der Sie glauben, dass sie wahrscheinlich nicht öffentlich sein sollte, bedeutet dies, dass die Klasse eine gewisse Kohärenz hat und Variablen eine bestimmte Beziehung haben, die beibehalten werden sollte, sodass alle Variablen privat sein sollten.

Getters und Setter machen Sinn, wenn sie eine kohärente Idee widerspiegeln. In einer Polygonklasse beispielsweise haben die X- und Y -Koordinaten gegebener Eckpunkte eine Bedeutung außerhalb der Klassengrenze. Es ist wahrscheinlich sinnvoll, Getter zu haben, und es ist wahrscheinlich sinnvoll, Setter zu haben. In einer Bankkontoklasse wird der Guthaben wahrscheinlich als private Variable gespeichert und sollte mit ziemlicher Sicherheit einen Getter haben. Wenn es einen Setter hat, muss eine Protokollierung eingebaut sein, um die Auditierbarkeit zu erhalten.

Es gibt einige Vorteile von Getter und Setter gegenüber öffentlichen Variablen. Sie bieten eine gewisse Trennung von Schnittstelle und Implementierung. Nur weil ein Punkt einen hat .getX() Funktion bedeutet nicht, dass es ein x geben muss, da seitdem .getX() und .setX() Kann mit radialen Koordinaten gut funktioniert. Eine andere ist, dass es möglich ist, Klasseninvarianten aufrechtzuerhalten, indem es alles tut, was notwendig ist, um die Klasse im Setter konsistent zu halten. Eine andere ist, dass es möglich ist, Funktionen zu haben, die auf einem Satz ausgelöst werden, z.

Für abstraktere Klassen verlieren die Mitgliedsvariablen jedoch die individuelle Bedeutung und machen im Kontext nur Sinn. Sie müssen beispielsweise nicht alle internen Variablen einer C ++ - Stream -Klasse kennen. Sie müssen wissen, wie Sie Elemente ein- und herausholen und verschiedene andere Aktionen ausführen. Wenn Sie sich auf die genaue interne Struktur zählen, wären Sie im Detail festgefahren, was willkürlich zwischen Compilern oder Versionen variieren könnte.

Ich würde also sagen, dass sie fast ausschließlich private Variablen verwenden sollen, Getters und Setter, wo sie eine echte Bedeutung im Objektverhalten haben, und nicht anders.

Nur weil Getters und Setter häufig überbeansprucht werden, heißt das nicht, dass sie nutzlos sind.

Das Problem mit Getters/Setzern ist, dass sie versuchen, die Kapselung zu fälschen, aber sie brechen sie tatsächlich, indem sie ihre Interna entlarven. Zweitens versuchen sie, zwei getrennte Dinge zu tun - Zugang zu und die Kontrolle ihres Zustands - und am Ende auch nicht sehr gut abschneiden.

Es bricht die Kapselung durch, da Sie beim Aufrufen einer GET/SET -Methode zuerst den Namen (oder eine gute Idee) des Feldes kennen müssen, das Sie ändern möchten, und zweitens müssen Sie wissen, dass es sich um Typ -EG handelt. Sie konnten nicht anrufen

setPositionX("some string");

Wenn Sie den Namen und die Art des Feldes kennen und der Setter öffentlich ist, kann jeder die Methode so anrufen, als wäre es ohnehin ein öffentliches Feld, es ist nur eine kompliziertere Art, dies zu tun. Warum also nicht einfach vereinfachen und machen Es ist überhaupt ein öffentliches Feld.

Durch den Zugriff auf seinen Zustand, aber der Versuch, es gleichzeitig zu kontrollieren Auswirkungen, die der Benutzer möglicherweise nicht erwartet. Wenn die Fehlerprüfung erforderlich ist, kann es so etwas bezeichnet werden wie

public void tryPositionX(int x) throws InvalidParameterException{
    if (x >= 0)
        this.x = x;
    else
        throw new InvalidParameterException("Holy Negatives Batman!");
}

Oder wenn zusätzlicher Code erforderlich ist, kann er als genauerer Name bezeichnet werden, basierend auf der gesamten Methode, z.

tryPositionXAndLog(int x) throws InvalidParameterException{
    tryPositionX(x);
    numChanges++;
}

IMHO braucht Getter/Setter, damit etwas funktioniert, ist oft ein Symptom für schlechtes Design. Nutzen Sie das Prinzip "Tell, nicht fragen" oder überdenken Sie, warum ein Objekt überhaupt staatliche Daten senden muss. Entdecken Sie Methoden, die das Verhalten eines Objekts anstelle seines Zustands ändern. Zu den Vorteilen gehören einfachere Wartung und erhöhte Erweiterbarkeit.

Sie erwähnen auch MVC und sagen, dass ein Modell für diesen Fall nicht verantwortlich sein kann Allen Holub gibt ein Beispiel dafür, eine Abstraktionsschicht zu erstellen, indem eine "Give-Me-A-Jcomponent-That-Repräsentation Your-Identity-Klasse" vorliegt. Was er sagt, würde "die Art und Weise isolieren, wie Identitäten aus dem Rest des Systems dargestellt werden". Ich bin nicht genug Erfahrung, um zu kommentieren, ob dies funktionieren würde oder nicht, aber an der Oberfläche klingt es eine anständige Idee.

Öffentliche Getters/Setter sind schlecht, wenn sie Zugriff auf Implementierungsdetails ermöglichen. Es ist jedoch angemessen, den Zugriff auf Objekteigenschaften zu gewähren und dafür Getter/Setzer zu verwenden. Wenn das Auto beispielsweise über die Farbeigenschaft verfügt, ist es akzeptabel, Kunden sie mit einem Getter "beobachten" zu lassen. Wenn ein Kunde die Möglichkeit benötigt, ein Auto zu revolorieren, kann die Klasse einen Setter bereitstellen ("Recolor" ist jedoch ein klarerer Name). Es ist wichtig, dass Kunden nicht wissen, wie Eigenschaften in Objekten gespeichert werden, wie sie aufrechterhalten werden und so weiter.

Ummmm ... hat er noch nie von dem Konzept der Verkapselung gehört. Getter- und Setter -Methoden werden eingeführt, um den Zugriff auf die Mitglieder der Klasse zu kontrollieren. Indem wir alle Felder öffentlich sichtbar machen ... konnte jeder alle Werte schreiben, die sie ihnen wollten, wodurch das gesamte Objekt vollständig ungültig gemacht wird.

Nur für den Fall, dass jemand das Konzept der Kapselung ein wenig unscharf ist, lesen Sie es hier:

Kapselung (Informatik)

... und wenn sie wirklich böse sind, würde .NET das Eigenschaftskonzept in die Sprache aufbauen? (Getter- und Setter -Methoden, die nur ein wenig schöner aussehen)

BEARBEITEN

In dem Artikel wird die Kapselung erwähnt:

"Getter und Setter können nützlich für Variablen sein, die Sie speziell einkapseln möchten, müssen sie jedoch nicht für alle Variablen verwenden. In der Tat ist die Verwendung von für alle Variablen ein böser Code -Geruch."

Die Verwendung dieser Methode führt langfristig zu einem extrem schwierigen Code. Wenn Sie es in der Hälfte eines Projekts herausfinden, das Jahre umfasst, dass ein Feld eingekapselt werden muss, müssen Sie jede Referenz dieses Feldes überall in Ihrer Software aktualisieren, um den Nutzen zu erhalten. Klingt viel schlauer, um die richtige Kapselung vorne zu verwenden und sich später die Kopfschmerzen zu sichern.

Ich denke, dass Getter und Setter nur für Variablen verwendet werden sollten, auf die man außerhalb einer Klasse zugreifen oder diese ändern muss. Abgesehen davon glaube ich nicht, dass Variablen öffentlich sein sollten, wenn sie nicht statisch sind. Dies liegt daran, dass Variablen, die nicht statisch sind, dazu führen können, dass sie unerwünscht verändert werden. Nehmen wir an, Sie haben einen Entwickler, der nachlässig öffentliche Variablen verwendet. Anschließend greift er auf eine Variable aus einer anderen Klasse und ohne Bedeutung zu, ändert sie. Jetzt hat er einen Fehler in seiner Software aufgrund dieses Missgeschicks. Deshalb glaube ich an den ordnungsgemäßen Gebrauch von Gettern und Setter, aber Sie benötigen sie nicht für jede private oder geschützte Variable.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top