Ich stelle diese Frage, weil ich glaube, dass sie es aus einem sehr guten Grund getan haben und dass die meisten Leute sie nicht richtig anwenden, auch aus meiner bisherigen Erfahrung in der Industrie. Aber wenn meine Theorie zutrifft, bin ich mir nicht sicher, warum sie den Modifikator für den privaten Zugriff enthielten ...?
Ich glaube, dass bei ordnungsgemäßer Verwendung des Standardzugriffs die Testbarkeit verbessert wird, während die Kapselung beibehalten wird. Außerdem wird der Modifikator für den privaten Zugriff überflüssig.
Der Standardzugriffsmodifikator kann verwendet werden, um denselben Effekt zu erzielen, indem ein eindeutiges Paket für Methoden verwendet wird, die vor dem Rest der Welt verborgen werden müssen, und dies, ohne die Testbarkeit zu beeinträchtigen, wie dies bei Paketen in einem Testordner der Fall ist Zugriff auf alle in einem Quellordner deklarierten Standardmethoden.
Ich glaube, aus diesem Grund verwendet Java den Paketzugriff als "Standard". Aber ich bin mir nicht sicher, warum sie auch privaten Zugriff enthielten, ich bin sicher, dass es einen gültigen Anwendungsfall gibt ...
Antworten:
Ich denke, sie hatten eine gute Vorstellung davon, was ein durchschnittlicher Programmierer tun würde. Und mit durchschnittlichem Programmierer meine ich einen, der nicht wirklich gut programmiert, aber trotzdem den Job bekommt, weil es nicht genug gute gibt und sie teuer sind.
Wenn sie den Standardzugriff "öffentlich" machen würden, würden sich die meisten Programmierer niemals die Mühe machen, etwas anderes zu verwenden. Das Ergebnis wäre überall eine Menge Spaghetti-Code . (Denn wenn Sie technisch irgendwo etwas aufrufen dürfen, warum sollten Sie sich dann die Mühe machen, eine Logik in einer Methode zu kapseln?)
Wenn Sie "privat" als Standardzugriff festlegen, ist dies nur geringfügig besser. Die meisten anfänglichen Programmierer erfinden einfach eine Faustregel (und teilen sie auf ihren Blogs), dass "man überall" öffentlich schreiben muss, und beschweren sich dann darüber, warum Java so schlecht ist, dass sie gezwungen werden, überall "öffentlich" zu schreiben. Und sie würden auch viel Spaghetti-Code produzieren.
Der Paketzugriff ermöglicht es Programmierern, ihre schlampigen Programmiertechniken beim Schreiben von Code innerhalb eines Pakets zu verwenden, muss jedoch beim Erstellen weiterer Pakete neu überdacht werden. Es ist ein Kompromiss zwischen guten Geschäftspraktiken und der hässlichen Realität. Wie zum Beispiel: Schreibe einen Spaghetti-Code, wenn du darauf bestehst, aber lass das hässliche Durcheinander bitte im Paket; Erstellen Sie zumindest einige schönere Schnittstellen zwischen den Paketen.
Wahrscheinlich gibt es auch andere Gründe, aber ich würde diesen nicht unterschätzen.
quelle
Der Standardzugriff macht den Modifikator für den privaten Zugriff nicht überflüssig.
Die Position der Sprachdesigner dazu spiegelt sich im offiziellen Tutorial - Kontrolle des Zugangs zu Mitgliedern einer Klasse - wider und ist ziemlich klar (für Ihre Bequemlichkeit relevante Aussage in dem fett gedruckten Zitat ):
Ihr Appell an die Testbarkeit als Rechtfertigung für den vollständigen Wegfall des Modifikators "Private" ist falsch, wie z. B. die Antworten in " Neu bei TDD" belegen . Sollte ich jetzt private Methoden meiden?
Die Position der Sprachentwickler in Bezug auf den Zweck und die Verwendung des Zugriffs auf Paketebene wird in einem anderen offiziellen Tutorial, Erstellen und Verwenden von Paketen, erläutert. Es hat nichts mit der Idee zu tun, private Modifikatoren zu löschen (für Ihre Bequemlichkeit relevante Aussage im fett gedruckten Zitat ). :
<rant> Ich glaube, ich habe genug Gejammer gehört. Schätze, es ist an der Zeit, laut und deutlich zu sagen ... </ rant>
Private Methoden sind für Unit-Tests von Vorteil.
Der folgende Hinweis setzt voraus, dass Sie mit der Codeabdeckung vertraut sind . Wenn nicht, nehmen Sie sich Zeit zum Lernen, da dies für diejenigen, die an Unit-Tests interessiert sind und überhaupt testen möchten, sehr nützlich ist.
Also gut, ich habe diese privaten Methoden- und Unit-Tests und die Coverage-Analyse, die mir sagt, dass es eine Lücke gibt, meine private Methode wird nicht durch Tests abgedeckt. Jetzt...
Was verdiene ich, wenn ich es privat halte?
Da die Methode privat ist, müssen Sie nur den Code untersuchen, um zu erfahren, wie er über die nicht-private API verwendet wird. Typischerweise zeigt eine solche Studie, dass der Grund für die Lücke darin liegt, dass in Tests ein bestimmtes Nutzungsszenario fehlt.
Der Vollständigkeit halber könnten andere (weniger häufige) Gründe für solche Abdeckungslücken Fehler in der Spezifikation / Konstruktion sein. Ich werde hier nicht weiter darauf eingehen, um die Dinge einfach zu halten. Es reicht zu sagen, dass Sie die Chance verpassen werden, zu erfahren, dass diese Fehler überhaupt existieren, wenn Sie die Zugriffsbeschränkung "nur um die Methode testbar zu machen" schwächen.
Gut, um die Lücke zu schließen, füge ich einen Komponententest für das fehlende Szenario hinzu, wiederhole die Abdeckungsanalyse und stelle sicher, dass die Lücke weg ist. Was habe ich jetzt? Ich habe als Neuheit einen Unit-Test für die spezifische Nutzung der nicht-privaten API.
Ein neuer Test stellt sicher, dass sich das erwartete Verhalten für diese Verwendung nicht ohne Vorankündigung ändert, da der Test fehlschlägt, wenn er sich ändert.
Ein externer Leser kann sich diesen Test ansehen und lernen, wie er verwendet werden soll und wie er sich verhält (hier schließt der externe Leser mein zukünftiges Ich ein, da ich den Code ein oder zwei Monate, nachdem ich damit fertig bin, vergesse).
Neuer Test ist tolerant gegenüber Refactoring (refactor ich private Methoden? Wetten Sie!) Was auch immer ich tue
privateMethod
, ich werde immer testen wollennonPrivateMethod(true)
. Unabhängig davon, was ich tueprivateMethod
, muss der Test nicht geändert werden, da die Methode nicht direkt aufgerufen wird.Nicht schlecht? Wetten Sie?
Was verliere ich durch die Schwächung der Zugriffsbeschränkung?
Stellen Sie sich nun vor, dass ich statt der oben genannten lediglich die Zugriffsbeschränkung abschwäche. Ich überspringe das Studium des Codes, der die Methode verwendet, und fahre direkt mit dem Test fort, der my aufruft
exPrivateMethod
. Groß? Nicht!Erhalte ich einen Test für die spezifische Nutzung der oben genannten nicht-privaten API? Nein, es gab
nonPrivateMethod(true)
vorher keinen Test , und jetzt gibt es keinen solchen Test.Erhalten externe Leser die Möglichkeit, die Verwendung der Klasse besser zu verstehen? Nein. "- Hey, was ist der Zweck der hier getesteten Methode? - Vergiss es, sie ist ausschließlich für den internen Gebrauch bestimmt. - Ups."
Ist es tolerant für Refactoring? Auf keinen Fall: Was auch immer ich ändere
exPrivateMethod
, wird den Test wahrscheinlich brechen. Benennen Sie um, führen Sie sie in eine andere Methode ein, ändern Sie die Argumente, und der Test hört einfach auf zu kompilieren. Kopfschmerzen? Wetten Sie?Zusammenfassend kann ich sagen , dass das Festhalten an der privaten Methode eine nützliche und zuverlässige Verbesserung bei Unit-Tests darstellt. Im Gegensatz dazu gibt mir die Schwächung der Zugriffsbeschränkungen "für die Testbarkeit" nur einen undurchsichtigen, schwer verständlichen Teil des Testcodes, der außerdem permanent durch geringfügiges Refactoring beschädigt werden kann. ehrlich gesagt, was ich bekomme, sieht verdächtig nach technischer Verschuldung aus .
</ rant>
quelle
Der wahrscheinlichste Grund ist: Es hat mit der Geschichte zu tun. Javas Vorfahr Oak hatte nur drei Zugriffsebenen: privat, geschützt, öffentlich.
Mit der Ausnahme, dass private in Oak das Äquivalent zu package private in Java war. Sie können Abschnitt 4.10 von Oaks Sprachspezifikation lesen (Hervorhebung meiner):
Daher war der private Zugriff, wie in Java bekannt, ursprünglich nicht vorhanden. Wenn Sie jedoch mehr als ein paar Klassen in einem Paket haben, würde es zu einem Alptraum der Namenskollision führen, wenn Sie nicht privat sind, wie wir es jetzt kennen (z. B. hat java.until.concurrent fast 60 Klassen) stellte es vor.
Die (ursprünglich als privat bezeichnete) Standard-Paketzugriffssemantik wurde jedoch zwischen Oak und Java nicht geändert.
quelle
Es gibt Situationen, in denen man zwei getrennte Klassen haben möchte, die enger miteinander verbunden sind, als alles öffentlich zugänglich zu machen. Dies hat ähnliche Vorstellungen von "Freunden" in C ++, bei denen eine andere Klasse, die als "Freund" einer anderen Klasse deklariert ist, auf ihre privaten Mitglieder zugreifen kann.
Wenn Sie sich die Innereien von Klassen wie BigInteger ansehen, finden Sie eine Reihe von Standardschutzpaketen für Felder und Methoden (alles, was in der Liste als blaues Dreieck angezeigt wird). Auf diese Weise können andere Klassen im Paket java.math für bestimmte Operationen optimaler auf ihre Innereien zugreifen (diese Methoden werden in BigDecimal aufgerufen - BigDecimal wird von einer BigInteger-Zahl unterstützt und speichert die erneute Implementierung von BigInteger . Dies ist die Paketebene. Isn ' Dies ist ein Schutzproblem, da java.math ein versiegeltes Paket ist und keine weiteren Klassen hinzugefügt werden können.
Auf der anderen Seite gibt es viele Dinge, die tatsächlich privat sind, wie sie sein sollten. Die meisten Pakete sind nicht versiegelt. Ohne private könnte Ihr Mitarbeiter eine andere Klasse in dieses Paket einfügen und auf das (nicht mehr) private Feld zugreifen und die Kapselung aufheben.
Es ist zu beachten, dass Unit-Tests nicht in Betracht gezogen wurden, als die Schutzbereiche gebaut wurden. JUnit (das XUnit-Testframework für Java) wurde erst 1997 entwickelt (eine Geschichte dazu finden Sie unter http://www.martinfowler.com/bliki/Xunit.html ). Die Alpha- und Betaversionen des JDK waren 1995 und JDK 1.0 war 1996, obwohl die Schutzstufen erst mit JDK 1.0.2 wirklich festgelegt wurden (vorher konnte man eine
private protected
Schutzstufe haben).Einige würden argumentieren, dass der Standard nicht Paketebene, sondern privat sein sollte. Andere argumentieren, dass es keinen Standardschutz geben sollte, aber alles sollte explizit angegeben werden - einige Anhänger davon werden Code schreiben wie:
Beachten Sie den Kommentar dort.
Der wahre Grund, warum der Schutz auf Paketebene der Standard ist, geht wahrscheinlich an den Design-Hinweisen von Java verloren (ich habe nachgegraben und kann keine Warum- Artikel finden, viele Leute erklären den Unterschied, aber keiner sagt "das ist der Grund" ").
Also rate ich mal. Und das ist alles, was es ist - eine Vermutung.
Zunächst versuchten die Leute immer noch, das Sprachdesign herauszufinden. Sprachen haben seitdem aus Javas Fehlern und Erfolgen gelernt. Dies könnte als Fehler aufgeführt werden, dass nicht für alle Felder etwas definiert werden muss.
public
undprivate
da diese die größten Auswirkungen auf den Zugang haben.Somit ist privat nicht voreingestellt und alles andere ist in Ordnung. Der Standardbereich wurde als Standard beibehalten. Dies war möglicherweise der erste Bereich, der erstellt wurde, und wurde im Interesse einer strikten Abwärtskompatibilität mit älterem Code so belassen.
Wie gesagt, das sind alles nur Vermutungen .
quelle
Die Kapselung ist eine Art zu sagen, "darüber muss man nicht nachdenken".
Diese in nichttechnische Begriffe umsetzen.
quelle
Ich glaube nicht, dass sie sich auf das Testen konzentriert haben, nur weil das Testen damals nicht sehr verbreitet war.
Was ich denke, dass sie erreichen wollten, war Kapselung auf der Paketebene. Wie Sie wissen, kann eine Klasse über interne Methoden und Felder verfügen und nur einen Teil davon durch öffentliche Mitglieder zugänglich machen. Ebenso kann ein Paket interne Klassen, Methoden und Felder enthalten und nur einen Teil davon verfügbar machen. Wenn Sie so denken, hat ein Paket eine interne Implementierung in einer Reihe von Klassen, Methoden und Feldern sowie eine öffentliche Schnittstelle in einer anderen (möglicherweise teilweise überlappenden) Reihe von Klassen, Methoden und Feldern.
Die erfahrensten Programmierer, die ich kenne, denken so. Sie nehmen die Kapselung und wenden sie auf eine Abstraktionsebene an, die über der Klasse liegt: ein Paket oder eine Komponente, wenn Sie möchten. Es scheint mir vernünftig, dass die Designer von Java bereits so ausgereift waren, wenn man bedenkt, wie gut Java noch mithält.
quelle