Ich bin nicht auf der Suche nach einer Meinung zur Semantik, sondern einfach nach einem Fall, in dem ein vernünftiger Einsatz von Gettern ein tatsächliches Hindernis darstellt. Vielleicht stürzt es mich in eine endlose Spirale, mich auf sie zu verlassen, vielleicht ist die Alternative sauberer und geht automatisch mit Gettern um usw. Etwas Konkretes.
Ich habe alle Argumente gehört, ich habe gehört, dass sie schlecht sind, weil sie Sie dazu zwingen, Objekte als Datenquellen zu behandeln, dass sie den "reinen Zustand" eines Objekts verletzen von "Geben Sie nicht zu viel heraus, sondern seien Sie bereit dazu viel akzeptieren ".
Aber absolut kein vernünftiger Grund, warum a getData
eine schlechte Sache ist, in der Tat argumentierten einige Leute, dass es viel um Semantik geht, besser als per se, aber nenne sie einfach nicht getX
, für mich ist das zumindest lustig .
Was ist eine Sache ohne Meinungen, die kaputt geht, wenn ich Getter vernünftig einsetze und Daten, bei denen die Integrität des Objekts eindeutig nicht kaputt geht, wenn es gelöscht wird?
Natürlich ist es nicht blöd, einen Getter für einen String zuzulassen, mit dem etwas verschlüsselt wird, aber ich spreche von Daten, die Ihr System benötigt, um zu funktionieren. Möglicherweise werden Ihre Daten Provider
aus dem Objekt durch a abgerufen, aber das Objekt muss immer noch zulassen Provider
, dass a ausgeführt $provider[$object]->getData
wird. Es führt kein Weg daran vorbei.
Warum ich frage: Für mich werden Getter, wenn sie vernünftig verwendet werden und wenn Daten, die als "sicher" behandelt werden, von Gott gesendet werden, 99% meiner Getter verwendet, um das Objekt zu identifizieren, wie in, frage ich, durch Code Object, what is your name? Object, what is your identifier?
, Jeder, der mit einem Objekt arbeitet, sollte diese Dinge über ein Objekt wissen, denn fast alles in der Programmierung ist Identität und wer weiß besser, was es ist als das Objekt selbst? Ich sehe keine wirklichen Probleme, es sei denn, Sie sind Purist.
Ich habe mir alle StackOverflow-Fragen zum Thema "Warum Getter / Setter" angeschaut und obwohl ich der Meinung bin, dass Setter in 99% der Fälle wirklich schlecht sind, müssen Getter nicht gleich behandelt werden, nur weil sie sich reimen.
Ein Setter wird die Identität Ihres Objekts gefährden und es sehr schwer machen, zu debuggen, wer die Daten ändert, aber ein Getter unternimmt nichts.
quelle
Antworten:
Ohne Getter kann man keinen guten Code schreiben.
Der Grund dafür ist nicht, dass Getter die Kapselung nicht brechen, sondern dass sie es tun. Es liegt nicht daran, dass Getter die Leute nicht dazu verleiten, OOP nicht zu folgen, wodurch sie Methoden mit den Daten setzen müssten, auf die sie einwirken. Tun sie. Nein, du brauchst Getter wegen der Grenzen.
Die Idee der Kapselung und des Zusammenhaltens von Methoden mit den Daten, auf die sie wirken, funktioniert einfach nicht, wenn Sie auf eine Grenze stoßen, die Sie vom Verschieben einer Methode abhält und Sie daher zum Verschieben von Daten zwingt.
Es ist wirklich so einfach. Wenn Sie Getter verwenden, wenn es keine Grenze gibt, haben Sie am Ende keine realen Objekte. Alles beginnt sich dem Verfahren anzunähern. Welches funktioniert so gut wie nie zuvor.
True OOP kann man nicht überall verbreiten. Es funktioniert nur innerhalb dieser Grenzen.
Diese Grenzen sind nicht hauchdünn. Sie haben Code in ihnen. Dieser Code kann nicht OOP sein. Es kann auch nicht funktionieren. Nein, dieser Code hat unsere Ideale gestrippt, damit er mit der harten Realität umgehen kann.
Michael Fetters nannte diese Code- Faszie nach dem weißen Bindegewebe, das Teile einer Orange zusammenhält.
Dies ist eine wunderbare Art, darüber nachzudenken. Es wird erklärt, warum es in Ordnung ist, beide Arten von Code in derselben Codebasis zu haben. Ohne diese Perspektive klammern sich viele neue Programmierer hart an ihre Ideale, haben dann das Herz gebrochen und geben diese Ideale auf, wenn sie an ihre erste Grenze stoßen.
Die Ideale funktionieren nur an ihrem richtigen Ort. Gib sie nicht auf, nur weil sie nicht überall funktionieren. Verwenden Sie sie dort, wo sie arbeiten. Dieser Ort ist der saftige Teil, den die Faszie schützt.
Ein einfaches Beispiel für eine Grenze ist eine Sammlung. Dies hält etwas und hat keine Ahnung, was es ist. Wie könnte ein Kollektionsdesigner möglicherweise die Verhaltensfunktionalität des gehaltenen Objekts in die Sammlung verschieben, wenn er keine Ahnung hat, was es halten wird? Das kannst du nicht. Sie stoßen an eine Grenze. Deshalb haben Kollektionen Getter.
Wenn Sie das wüssten, könnten Sie dieses Verhalten verschieben und vermeiden, den Status zu verschieben. Wenn Sie es wissen, sollten Sie es tun. Du weißt es einfach nicht immer.
Manche Leute nennen das einfach pragmatisch. Und es ist. Aber es ist schön zu wissen, warum wir pragmatisch sein müssen.
Sie haben zum Ausdruck gebracht, dass Sie semantische Argumente nicht hören wollen, und scheinen zu befürworten, überall "vernünftige Getter" zu setzen. Sie möchten, dass diese Idee in Frage gestellt wird. Ich denke, ich kann zeigen, dass die Idee Probleme mit der Art und Weise hat, wie Sie sie eingerahmt haben. Ich glaube aber auch, dass ich weiß, woher du kommst, weil ich dort war.
Wenn Sie überall Getters wollen, schauen Sie sich Python an. Es gibt kein privates Schlüsselwort. Dennoch macht Python OOP ganz gut. Wie? Sie benutzen einen semantischen Trick. Sie nennen alles, was privat sein soll, mit einem führenden Unterstrich. Sie dürfen sogar davon lesen, vorausgesetzt, Sie übernehmen die Verantwortung dafür. "Wir sind alle Erwachsene hier", sagen sie oft.
Was ist also der Unterschied zwischen dem, alles in Java oder C # zu verbessern? Tut mir leid, aber es ist Semantik. Pythons unterstreichen die Konvention und signalisieren Ihnen deutlich, dass Sie hinter der Tür des Mitarbeiters herumstöbern. Schlagen Sie auf alles und Sie verlieren dieses Signal. Mit Reflektion hätten Sie das Private sowieso abstreifen und trotzdem nicht das semantische Signal verlieren können. Hier gibt es einfach kein strukturelles Argument.
Wir müssen also entscheiden, wo das Schild "nur für Angestellte" aufgehängt werden soll. Was ist als privat zu betrachten? Sie nennen das "vernünftige Getter". Wie ich bereits sagte, ist die beste Rechtfertigung für einen Getter eine Grenze, die uns von unseren Idealen abhält. Das sollte nicht dazu führen, dass alles besser wird. Wenn es zu einem Getter kommt, sollten Sie erwägen, das Verhalten weiter in das saftige Bit zu verschieben, in dem Sie es schützen können.
Diese Trennung hat zu einigen Begriffen geführt. Ein Datenübertragungsobjekt oder DTO enthält kein Verhalten. Die einzigen Methoden sind Getter und manchmal Setter, manchmal Konstruktoren. Dieser Name ist bedauerlich, weil er überhaupt kein echtes Objekt ist. Die Getter und Setter sind eigentlich nur Debugging-Codes, mit denen Sie einen Haltepunkt setzen können. Ohne diese Notwendigkeit wären sie nur ein Haufen öffentlicher Felder. In C ++ haben wir sie Structs genannt. Der einzige Unterschied zu einer C ++ - Klasse bestand darin, dass sie standardmäßig öffentlich waren.
DTOs sind nett, weil Sie sie über eine Grenzmauer werfen und Ihre anderen Methoden sicher in einem netten saftigen Verhaltensobjekt aufbewahren können. Ein wahres Objekt. Es gibt keine Getter, die die Kapselung verletzen könnten. Meine Verhaltensobjekte können DTOs essen, indem sie als Parameterobjekte verwendet werden . Manchmal muss ich eine defensive Kopie davon erstellen , um einen gemeinsamen veränderlichen Zustand zu verhindern . Ich verbreite keine veränderlichen DTOs innerhalb des saftigen Teils innerhalb der Grenze. Ich kapsle sie ein. Ich verstecke sie. Und wenn ich endlich an eine neue Grenze stoße, drehe ich ein neues DTO auf und werfe es über die Mauer, wodurch es das Problem eines anderen macht.
Aber Sie möchten Gettern zur Verfügung stellen, die Identität ausdrücken. Nun, Glückwunsch, Sie haben eine Grenze gefunden. Entitäten haben eine Identität, die über ihre Referenz hinausgeht. Das heißt, jenseits ihrer Speicheradresse. Also muss es irgendwo aufbewahrt werden. Und etwas muss in der Lage sein, sich anhand seiner Identität auf dieses Ding zu beziehen. Ein Getter, der Identität ausdrückt, ist durchaus vernünftig. Ein Haufen Code, der diesen Getter verwendet, um Entscheidungen zu treffen, die die Entität selbst hätte treffen können, ist dies nicht.
Am Ende ist es nicht die Existenz von Gettern, die falsch ist. Sie sind viel besser als öffentliche Felder. Schlecht ist, wenn sie so tun, als wären Sie objektorientiert, wenn Sie es nicht sind. Getter sind gut. Objektorientiert zu sein ist gut. Getter sind nicht objektorientiert. Verwenden Sie Getter, um einen sicheren Ort für die Objektorientierung zu finden.
quelle
clearly
? Wenn Daten von einem Wert an mich übergeben werden, besitzt mein Objekt jetzt die Daten, aber von der Semantik her hat es noch nicht die Daten von jemand anderem. Es muss dann Operationen ausführen, um diese Daten zu transformieren. Sobald die Daten berührt werden, müssen Sie semantische Änderungen vornehmen: Sie haben Daten mit dem Namen$data_from_request
und jetzt haben Sie sie bearbeitet? Nennen Sie es$changed_data
. Sie möchten diese Daten an Dritte weitergeben? Erstellen Sie einen GettergetChangedRequestData
, dann ist der Besitz eindeutig festgelegt. Oder ist es?Getter verstoßen gegen das Hollywood-Prinzip ("Ruf uns nicht an, wir rufen dich an")
Das Hollywood-Prinzip (auch bekannt als Inversion of Control) besagt, dass Sie keinen Bibliothekscode aufrufen, um Dinge zu erledigen. Vielmehr ruft das Framework Ihren Code auf. Da das Framework die Dinge steuert, ist es nicht erforderlich, den internen Status an die Clients zu senden. Das musst du nicht wissen.
In seiner heimtückischsten Form bedeutet ein Verstoß gegen das Hollywood-Prinzip, dass Sie einen Getter verwenden, um Informationen über den Status einer Klasse abzurufen, und dann anhand des erhaltenen Werts entscheiden, welche Methoden für diese Klasse aufgerufen werden sollen. es ist eine Verletzung der Kapselung vom Feinsten.
Die Verwendung eines Getters impliziert, dass Sie diesen Wert benötigen, wenn Sie dies tatsächlich nicht tun.
Möglicherweise benötigen Sie diese Leistungsverbesserung tatsächlich
In extremen Fällen von leichten Objekten, die die maximal mögliche Leistung aufweisen müssen, ist es möglich (wenn auch äußerst unwahrscheinlich), dass Sie die sehr geringe Leistungsstrafe, die ein Getter verhängt, nicht zahlen können. Dies wird in 99,9 Prozent der Fälle nicht der Fall sein.
quelle
Generator
Objekt, das alle meineItems
Objekte durchläuft und danngetName
von jedem aufruftItem
, etwas weiter zu machen. Was ist das Problem damit? Im GegenzugGenerator
spucken die formatierten Zeichenfolgen aus. Dies liegt in meinem Framework, für das ich dann zusätzlich eine API habe, mit der Benutzer alles ausführen können, was die Benutzer bereitstellen, ohne das Framework zu berühren.What is the issue with this?
Keine, die ich sehen kann. Genau das macht einemap
Funktion. Aber das ist nicht die Frage, die Sie gestellt haben. Sie fragte im Wesentlichen „Gibt es irgendwelche Bedingungen , unter denen ein Getter nicht ratsam sein könnte.“ Ich antwortete mit zwei, aber das heißt nicht, dass Sie die Setter ganz aufgeben.Bekommt Leck-Implementierungsdetails und unterbricht Abstraktion
Erwägen
public int millisecondsSince1970()
Ihre Kunden werden denken : „Oh, das ist ein int“ und es wird eine Unmenge Anrufe werden unter der Annahme , dass es eine ist int , integer math tun Daten zu vergleichen, etc ... Wenn Sie feststellen , dass Sie eine brauchen lange , es wird eine Menge sein von Legacy-Code mit Problemen. In einer Java-Welt würden Sie
@deprecated
die API erweitern, jeder wird sie ignorieren, und Sie müssen veralteten, fehlerhaften Code beibehalten. :-( (Ich gehe davon aus, dass andere Sprachen ähnlich sind!)In diesem speziellen Fall bin ich mir nicht sicher, was eine bessere Option sein könnte, und die Antwort von @candiedorange ist völlig zutreffend. Es gibt viele Male, wenn Sie Getter benötigen, aber dieses Beispiel zeigt die Nachteile. Jeder öffentliche Getter neigt dazu, Sie an eine bestimmte Implementierung zu "binden". Verwenden Sie sie, wenn Sie wirklich "Grenzen überschreiten" müssen, aber so wenig wie möglich und mit Sorgfalt und Umsicht.
quelle
timepoint
undtimespan
jeweils. (epoch
ist ein besonderer Wert vontimepoint
.) In diesen Klassen bieten sie Getter wiegetInt
odergetLong
odergetDouble
. Wenn Klassen, die die Zeit manipulieren, so geschrieben werden, dass sie (1) zeitbezogene Arithmetik an diese Objekte und Methoden delegieren und (2) über Getter Zugriff auf diese Zeitobjekte gewähren, ist das Problem gelöst, ohne Getter loswerden zu müssen .Ich denke, der erste Schlüssel ist, sich daran zu erinnern, dass Absolutes immer falsch ist.
Stellen Sie sich ein Adressbuchprogramm vor, in dem einfach die Kontaktinformationen der Benutzer gespeichert werden. Aber machen wir es richtig und unterteilen es in die Ebenen Controller / Service / Repository.
Es wird eine
Person
Klasse geben, die aktuelle Daten enthält: Name, Adresse, Telefonnummer usw.,Address
undPhone
es handelt sich auch um Klassen, sodass wir später den Polymorphismus verwenden können, um Schemata außerhalb der USA zu unterstützen. Alle drei Klassen sind Datenübertragungsobjekte , daher sind sie nichts anderes als Getter und Setter. Und das macht Sinn: Sie werden keine Logik in sich haben, die über das Überschreiben vonequals
und hinausgehtgetHashcode
. Die Aufforderung, Ihnen eine Darstellung der vollständigen Personendaten zu geben, ist nicht sinnvoll: Ist dies für HTML-Präsentationen, eine benutzerdefinierte GUI-App, eine Konsolen-App, einen HTTP-Endpunkt usw. sinnvoll?Hier kommen der Controller, der Service und das Repository ins Spiel. Alle diese Klassen werden dank der Abhängigkeitsinjektion logiklastig und getterleicht sein.
Der Controller wird einen Dienst injizieren lassen, der Methoden wie
get
und verfügbar macht, diesave
beide einige vernünftige Argumente benötigen (z. B.get
Überschreibungen für die Suche nach Namen, Postleitzahl oder einfach allessave
abrufen) eine einzelnePerson
und speichern Sie es). Welche Stärken hätte der Controller? In der Lage zu sein, den Namen der konkreten Klasse abzurufen, kann für die Protokollierung hilfreich sein. In welchem anderen Status als dem Status, der in die Klasse injiziert wurde, wird sie gespeichert?In ähnlicher Weise wird der Service-Schicht ein Repository hinzugefügt, so dass sie tatsächlich
Person
s abrufen und beibehalten kann , und sie kann eine gewisse "Geschäftslogik" aufweisen (z. B. müssen möglicherweise allePerson
Objekte mindestens eine Adresse oder ein Telefon haben) Nummer). Aber noch einmal: Welchen Zustand hat dieses Objekt anders als das, was injiziert wurde? Wieder keine.Auf der Repository-Ebene wird es etwas interessanter: Sie stellt eine Verbindung zu einem Speicherort her, z. Eine Datei, eine SQL-Datenbank oder ein In-Memory-Speicher. Hier ist es verlockend, einen Getter hinzuzufügen, um den Dateinamen oder die SQL-Verbindungszeichenfolge abzurufen, aber dieser Status wurde in die Klasse eingefügt. Soll das Repository einen Getter haben, der feststellt, ob die Verbindung zu seinem Datenspeicher erfolgreich hergestellt wurde oder nicht? Nun, vielleicht, aber wozu dienen diese Informationen außerhalb der Repository-Klasse selbst? Die Repository-Klasse selbst sollte bei Bedarf versuchen können, erneut eine Verbindung zu ihrem Datenspeicher herzustellen, was darauf hindeutet, dass die
isConnected
Eigenschaft bereits einen zweifelhaften Wert hat. Darüber hinaus wird eineisConnected
Eigenschaft wahrscheinlich genau dann falsch sein, wenn sie richtig sein müsste: ÜberprüfenisConnected
vor dem Versuch, Daten abzurufen / zu speichern, kann nicht garantiert werden, dass das Repository weiterhin verbunden ist, wenn der "echte" Aufruf erfolgt, sodass die Notwendigkeit einer Ausnahmebehandlung nicht beseitigt wird (es gibt darüber hinaus Argumente dafür, wohin dies führen sollte) den Umfang dieser Frage).Berücksichtigen Sie auch Unit-Tests (Sie schreiben Unit-Tests, oder?): Der Service erwartet nicht, dass eine bestimmte Klasse injiziert wird, sondern vielmehr, dass eine konkrete Implementierung einer Schnittstelle injiziert wird. Auf diese Weise kann die Anwendung als Ganzes ändern, wo die Daten gespeichert werden, ohne dass etwas anderes als das in den Service eingespeiste Repository ausgetauscht werden muss. Außerdem kann der Service durch Injizieren eines Schein-Repository Unit-getestet werden. Dies bedeutet, in Schnittstellen anstatt in Klassen zu denken. Würde die Repository-Schnittstelle irgendwelche Getter aussetzen? Gibt es einen internen Status, der allen Repositorys gemeinsam ist, der außerhalb des Repositorys nützlich ist und nicht in das Repository eingespeist wird? Mir fällt es schwer, an mich selbst zu denken.
TL; DR
Fazit: Abgesehen von den Klassen, deren einziger Zweck es ist, Daten herumzutragen, hat nichts im Stapel einen Platz, um einen Getter zu setzen: state ist außerhalb der Arbeiterklasse entweder injiziert oder irrelevant.
quelle
Veränderbare Mitglieder.
Wenn Sie eine Sammlung von Dingen in einem Objekt haben, die Sie über einen Getter verfügbar machen, setzen Sie sich möglicherweise Fehlern aus, die mit den falschen Dingen zusammenhängen, die der Sammlung hinzugefügt werden.
Wenn Sie ein veränderbares Objekt haben, das Sie über einen Getter verfügbar machen, können Sie sich dem internen Zustand Ihres Objekts auf eine Weise öffnen, die Sie nicht erwarten.
Ein wirklich schlechtes Beispiel wäre ein Objekt, das von 1 bis 100 zählt und seinen aktuellen Wert als veränderbare Referenz anzeigt. Dies ermöglicht einem Drittanbieterobjekt, den Wert von Current so zu ändern, dass der Wert außerhalb der erwarteten Grenzen liegen kann.
Dies ist meistens ein Problem beim Freilegen veränderlicher Objekte. Das Freilegen von Strukturen oder unveränderlichen Objekten ist überhaupt kein Problem, da Änderungen an diesen stattdessen eine Kopie ändern (normalerweise entweder durch eine implizite Kopie im Fall einer Struktur oder durch eine explizite Kopie im Fall eines unveränderlichen Objekts).
Verwenden Sie eine Metapher, mit der Sie den Unterschied leichter erkennen können.
Eine Blume hat eine Reihe von Dingen, die an ihr einzigartig sind. Es hat eine
Color
und es hat eine Reihe von Blütenblättern (NumPetals). Wenn ich diese Blume in der realen Welt beobachte, kann ich ihre Farbe klar erkennen. Ich kann dann anhand dieser Farbe Entscheidungen treffen. Zum Beispiel, wenn die Farbe schwarz ist, geben Sie nicht an die Freundin, aber wenn die Farbe rot ist, geben Sie an die Freundin. In unserem Objektmodell wird die Farbe der Blume als Getter auf dem Blumenobjekt angezeigt. Meine Beobachtung dieser Farbe ist wichtig für Aktionen, die ich ausführen werde, hat jedoch keinerlei Einfluss auf das Blumenobjekt. Ich sollte nicht in der Lage sein, die Farbe dieser Blume zu ändern. Ebenso ist es nicht sinnvoll, die Farbeigenschaft auszublenden. Eine Blume kann Menschen im Allgemeinen nicht davon abhalten, ihre Farbe zu beobachten.Wenn ich die Blume färbe, sollte ich die ReactToDye-Methode (Color dyeColor) für die Blume aufrufen, die die Blume gemäß den internen Regeln ändert. Anschließend kann ich die
Color
Eigenschaft erneut abfragen und auf Änderungen reagieren, nachdem die ReactToDye-Methode aufgerufen wurde. Es wäre falsch für mich, dieColor
der Blume direkt zu modifizieren, und wenn ich könnte, dann ist die Abstraktion zusammengebrochen.Manchmal (seltener, aber dennoch oft genug, um es zu erwähnen) sind Setter durchaus gültiges OO-Design. Wenn ich ein Kundenobjekt habe, ist es durchaus zulässig, einen Setter für seine Adresse anzugeben. Ob das nennt du
setAddress(string address)
oderChangeMyAddressBecauseIMoved(string newAddress)
oder einfachstring Address { get; set; }
eine Frage der Semantik. Der interne Status dieses Objekts muss geändert werden, und die entsprechende Methode besteht darin, den internen Status dieses Objekts festzulegen. Auch wenn ich eine historische Aufzeichnung der Adressen benötige, in denen derCustomer
Benutzer gewohnt hat, kann ich den Setter verwenden, um meinen internen Status entsprechend zu ändern. In diesem Fall ist es nicht sinnvollCustomer
, unveränderlich zu sein, und es gibt keinen besseren Weg, eine Adresse zu ändern, als einen Setter dafür bereitzustellen.Ich bin nicht sicher, wer vorschlägt, dass Getters und Setter schlechte oder gegen objektorientierte Paradigmen verstoßen, aber wenn doch, tun sie dies wahrscheinlich als Reaktion auf ein bestimmtes Sprachmerkmal der Sprache, die sie gerade verwenden. Ich habe das Gefühl, dass dies aus der Java-Kultur "Alles ist ein Objekt" heraus gewachsen ist (und sich möglicherweise auf einige andere Sprachen ausgeweitet hat). Die .NET-Welt hat diese Diskussion überhaupt nicht. Getter und Setter sind eine erstklassige Sprachfunktion, die nicht nur von Benutzern verwendet wird, die Anwendungen in der Sprache schreiben, sondern auch von der Sprach-API selbst.
Sie sollten vorsichtig sein, wenn Sie Getter verwenden. Sie möchten nicht die falschen Datenelemente verfügbar machen und auch nicht die falschen Datenelemente (dh veränderbare Objekte, Verweise auf Strukturen, mit denen ein Konsument den internen Status ändern kann). Sie möchten Ihre Objekte jedoch so modellieren, dass die Daten so eingekapselt werden, dass Ihre Objekte von externen Verbrauchern verwendet und vor Missbrauch durch dieselben Verbraucher geschützt werden können. Häufig erfordert das Getter.
Zusammenfassend: Getter und Setter sind gültige objektorientierte Entwurfswerkzeuge. Sie dürfen nicht so großzügig verwendet werden, dass jedes Implementierungsdetail offengelegt wird, und Sie möchten sie auch nicht so sparsam verwenden, dass die Konsumenten eines Objekts das Objekt nicht effizient nutzen können.
quelle
Wartbarkeit wird brechen.
Jedes Mal (ich sollte fast immer sagen), wenn Sie einen Getter anbieten, geben Sie im Grunde mehr weg, als von Ihnen verlangt wurde. Dies bedeutet auch, dass Sie mehr warten müssen, als verlangt wurde. Sie verringern daher die Wartbarkeit ohne wirklichen Grund.
Gehen wir zum
Collection
Beispiel von @ candied_orange . Im Gegensatz zu dem, was er schreibt,Collection
sollte man keinen Getter haben. Sammlungen existieren aus ganz bestimmten Gründen, insbesondere, um alle Elemente zu durchlaufen . Diese Funktionalität ist für niemanden überraschend. Sie sollte daher in der implementiert werdenCollection
, anstatt den offensichtlichen Anwendungsfall auf den Benutzer zu übertragen, indem For-Cycle und Getter oder so weiter verwendet werden.Um fair zu sein, einige Grenzen tun müssen Getter. Dies passiert, wenn Sie wirklich nicht wissen, wofür sie verwendet werden. Beispielsweise können Sie den Stacktrace
Exception
heutzutage programmgesteuert aus Javas Klasse abrufen, weil die Leute ihn aus allerlei merkwürdigen Gründen verwenden wollten, die sich die Autoren nicht vorstellen konnten oder wollten.quelle
Collection
, die wie in zwei Sekunden gleichzeitig iterieren muss(A1, B1), (A2, B2), ...
. Dies erfordert eine Implementierung von "zip". Wie implementieren Sie "zip", wenn die Iterationsfunktion auf einem der beiden implementiert istCollection
? Wie greifen Sie auf das entsprechende Element auf dem anderen zu?Collection
musszip
mit sich selbst implementieren , je nachdem wie die Bibliothek geschrieben ist. Wenn dies nicht der Fall ist, implementieren Sie es und senden eine Pull-Anfrage an den Ersteller der Bibliothek. Beachten Sie, dass ich zugestimmt habe, dass einige Grenzen manchmal Getter benötigen. Mein eigentliches Problem ist, dass Getter heutzutage überall sind.Collection
Objekt haben muss, zumindest für ihre eigene Implementierung vonzip
. (Das heißt, der Getter muss mindestensCollection
kann offensichtlich auf seinen eigenen internen Zustand zugreifen, genauer gesagt, jedeCollection
Instanz kann auf den internen Zustand eines anderen zugreifen. Es ist der gleiche Typ, keine Getter erforderlich.