Methoden, die nicht von Instanzfeldern abhängig sind, statisch machen?

19

Kürzlich habe ich angefangen, in Groovy für ein Integrationstest-Framework für ein Java-Projekt zu programmieren. Ich verwende Intellij IDEA mit dem Groovy-Plug-In und bin überrascht, dass dies eine Warnung für alle Methoden ist, die nicht statisch sind und von keinen Instanzfeldern abhängen. In Java ist dies jedoch kein Problem (zumindest aus Sicht der IDE).

Sollten alle Methoden, die nicht von Instanzfeldern abhängig sind, in statische Funktionen umgewandelt werden? Wenn dies zutrifft, ist dies spezifisch für Groovy oder für OOP im Allgemeinen verfügbar? Und warum?

m3th0dman
quelle
Rufen diese Methoden andere Instanzmethoden auf? Oder haben sie buchstäblich gar nichts mit einem Objekt dieser Klasse zu tun? Kannst du ein Beispiel geben?
Ray Toal

Antworten:

26

Beachten Sie, dass IDEA diese Inspektion auch für Java anbietet. Sie heißt Methode kann 'statisch' sein .

Diese Inspektion meldet alle Methoden, die sicher statisch gemacht werden können. Eine Methode kann statisch sein, wenn sie keine der nicht statischen Methoden und nicht statischen Felder ihrer Klasse referenziert und in einer Unterklasse nicht überschrieben wird ...

Allerdings ist diese Überprüfung für Java-Code standardmäßig deaktiviert (der Programmierer kann sie nach eigenem Ermessen aktivieren ). Der Grund dafür ist höchstwahrscheinlich, dass die Gültigkeit / Nützlichkeit einer solchen Inspektion aufgrund einiger recht maßgeblicher Quellen in Frage gestellt werden könnte.

So starten Sie mit, offiziellen Java - Tutorial ist ziemlich restriktiv , wenn Methoden statisch sein sollte:

Eine häufige Verwendung für statische Methoden ist der Zugriff auf statische Felder.

Angesichts der obigen Ausführungen könnte man argumentieren, dass das Aktivieren der standardmäßig erwähnten Überprüfung nicht der empfohlenen Verwendung des statischen Modifikators in Java entspricht.

Außerdem gibt es einige andere Quellen, die einen vernünftigen Ansatz für die Verwendung von Ideen vorschlagen, die hinter dieser Inspektion stehen oder sie sogar entmutigen.

Siehe zum Beispiel Java World Artikel - Mr. Happy Object lehrt statische Methoden :

Jede vom Instanzstatus unabhängige Methode kann als statisch deklariert werden.

Beachten Sie, dass ich "Kandidat für die Deklaration als statisch" sage. Selbst im vorherigen Beispiel zwingt Sie nichts dazu, instances()statisch zu deklarieren . Wenn Sie es als statisch deklarieren, ist der Aufruf einfacher, da Sie keine Instanz zum Aufrufen der Methode benötigen. Manchmal gibt es Methoden, die nicht vom Instanzstatus abhängig zu sein scheinen. Möglicherweise möchten Sie diese Methoden nicht statisch machen. Tatsächlich möchten Sie sie wahrscheinlich nur als statisch deklarieren, wenn Sie ohne Instanz darauf zugreifen müssen.

Auch wenn Sie eine solche Methode als statisch deklarieren können, möchten Sie dies möglicherweise nicht, da Vererbungsprobleme in Ihrem Entwurf auftreten. Schauen Sie sich "Effektives objektorientiertes Design" an, um einige der Probleme zu sehen, mit denen Sie konfrontiert sind ...

Ein Artikel im Google-Testblog geht sogar so weit, zu behaupten, dass statische Methoden der Testbarkeit zum Opfer fallen :

Lass uns eine mentale Übung machen. Angenommen, Ihre Anwendung verfügt nur über statische Methoden. (Ja, Code wie dieser kann geschrieben werden, man nennt ihn prozedurale Programmierung.) Stellen Sie sich nun den Aufrufgraphen dieser Anwendung vor. Wenn Sie versuchen, eine Blattmethode auszuführen, haben Sie kein Problem damit, ihren Status einzurichten und alle Eckfälle zu bestätigen. Der Grund dafür ist, dass eine Leaf-Methode keine weiteren Aufrufe ausführt. Je weiter Sie sich von den Blättern entfernen und sich der Wurzelmethode main()nähern, desto schwieriger wird es, den Status in Ihrem Test festzulegen und Dinge zu behaupten. Viele Dinge werden unmöglich zu behaupten sein. Ihre Tests werden immer größer. Sobald Sie die erreichenmain()Methode Sie haben keinen Unit-Test mehr (da Ihre Unit die gesamte Anwendung ist), haben Sie jetzt einen Szenario-Test. Stellen Sie sich vor, die Anwendung, die Sie testen möchten, ist ein Textverarbeitungsprogramm. Es gibt nicht viel, was Sie von der Hauptmethode behaupten können ...

Manchmal ist eine statische Methode eine Fabrik für andere Objekte. Dies verschärft das Testproblem weiter. In Tests verlassen wir uns darauf, dass wir Objekte unterschiedlich verdrahten können und wichtige Abhängigkeiten durch Mocks ersetzen. Sobald ein newOperator aufgerufen wird, können wir die Methode nicht mit einer Unterklasse überschreiben. Ein Aufrufer einer solchen statischen Fabrik ist permanent an die konkreten Klassen gebunden, die die Methode der statischen Fabrik erzeugt hat. Mit anderen Worten, der Schaden der statischen Methode geht weit über die statische Methode selbst hinaus. Das Zusammenführen von Objektgraphenverdrahtung und Konstruktionscode in eine statische Methode ist besonders schlecht, da Objektgraphenverdrahtung das Isolieren von Dingen zum Testen ist ...


Wie Sie oben sehen, ist es nur natürlich, dass die erwähnte Überprüfung für Java standardmäßig deaktiviert ist.

IDE-Entwickler würden es sehr schwer haben, zu erklären, warum es ihrer Meinung nach so wichtig ist, es standardmäßig zu aktivieren, und zwar gegen allgemein anerkannte Empfehlungen und Best Practices.

Bei Groovy sieht das ganz anders aus. Keines der oben aufgeführten Argumente trifft zu, insbesondere nicht das Argument zur Testbarkeit, wie z. B. in Mocking Static Methods im Groovy- Artikel von Javalobby erläutert:

Wenn die zu testende Groovy-Klasse eine statische Methode für eine andere Groovy-Klasse aufruft, können Sie die ExpandoMetaClass verwenden, mit der Sie dynamisch Methoden, Konstruktoren, Eigenschaften und statische Methoden hinzufügen können ...

Dieser Unterschied ist wahrscheinlich der Grund, warum die Standardeinstellung für die erwähnte Überprüfung in Groovy entgegengesetzt ist. Während in der Java-Standardeinstellung "Ein" zu Verwirrung der Benutzer führen würde, könnte in Groovy eine entgegengesetzte Einstellung die IDE-Benutzer verwirren.

"Hey, die Methode verwendet keine Instanzfelder. Warum haben Sie mich nicht gewarnt?" Diese Frage wäre für Java (wie oben erläutert) leicht zu beantworten, aber für Groovy gibt es einfach keine überzeugende Erklärung.

Mücke
quelle
Übrigens schlägt ReSharper (erstellt von JetBrains für C # / Visual Studio) dasselbe vor
Konrad Morawski,
6
Es gibt einen wichtigen Unterschied zwischen statischen Methoden mit und ohne Nebenwirkungen. Der Google-Extrakt spricht das erstere wirklich an.
Assylias
@assylias Tut es, aber es wird auch erläutert, wie Factory-Methoden das Testen erschweren können (da Abhängigkeiten in der Anwendung eng miteinander verbunden werden). Die Verwendung eines Frameworks zur Abhängigkeitsinjektion ist eine der besten Problemumgehungen und löst auch viele andere Probleme.
Per Lundberg
5

Es ist kaum vorstellbar, dass sich dies spürbar auf die Leistung auswirkt. Der einzige Vorteil, den ich sehen kann, staticist, dass er visuell anzeigt, dass der Instanzstatus nicht betroffen ist. Mit anderen Worten, es sagt der Person, die den Quellcode liest, etwas ... "Interessantes" über diese Methode, nur weil sie da ist. Die eigentliche Frage ist, ob es klarstellt oder verwirrt. "Warum ist diese Methode statisch? Handelt es sich um eine Factory-Methode? Kann sie aufgerufen werden, ohne dass eine Objektinstanz erforderlich ist?"

Außerdem mögen manche Leute keine statischen Methoden, weil sie behaupten, dass man sie nicht verspotten kann, und deshalb sind sie nicht testbar oder ähnliches. Natürlich, wenn Sie es aus einem der üblichen Gründe statisch machen, wie zum Beispiel eine Factory-Methode, dann bin ich alles dafür. Ich bin mir nur nicht ganz sicher, ob es ein Mandat ist, Methoden statisch zu machen, nur weil sie den Instanzstatus nicht berühren.

Robert Harvey
quelle
5
Beachten Sie, dass (in Java) eine statische Methode nicht überschrieben werden kann. Obwohl dies nicht oft ein Problem ist, bedeutet dies, dass eine spätere Unterklasse diese Implementierung nicht ändern kann. Dies soll nicht heißen, dass eine statische Methode nicht die richtige Antwort ist, sondern Teil der Entwurfsüberlegungen.
2
@ user40980 Es ist eine Überlegung wert, stimmt, aber es ist auch eine Überlegung wert, dass die Vererbung ein schwerfälliges Werkzeug sein kann, das häufig missbraucht wird, und mehrere prominente Persönlichkeiten argumentieren, dass alle Klassen im finalHinblick auf die Vererbung oder speziell dafür entworfen werden sollten .
Sara
3

Ich denke , es ist möglich , Refactoring zu ermöglichen, werden gesichtet .

Sobald die Methode statisch gemacht wurde, ist klar, dass sie aus der Klasse verschoben werden kann, beispielsweise zu einer Einheitsklasse.

Es ist auch einfach, es in eine Instanzmethode eines seiner Parameter umzuwandeln. Oft ist dies der Ort, an dem sich der Code befinden sollte.

Ian
quelle
-1

Beachten Sie, dass Sie möglicherweise zustandslose Klassen haben, die eine Schnittstelle implementieren (z. B. java.lang.Runnable- Sie können ihre Methoden nicht statisch machen. Einige Muster (z. B. Strategie) können auch zustandslose Objekte erzeugen, die möglicherweise sogar mehrere Methoden haben.

Statik sind erste Cousins ​​der Singletons. Es wird sehr schwierig sein, zu einem späteren Zeitpunkt von statisch zu nicht statisch zu wechseln. Wenn Sie also einen Status hinzufügen müssen, werden Sie versucht sein, statische Variablen einzuführen.

Eugene
quelle
Wie beantwortet dies die gestellte Frage?
gnat
1
Warum ist es schwierig, von einem Staat in einen anderen zu gelangen? Ich würde sagen, es ist umgekehrt. Es ist einfacher, etwas Reines zu kontaminieren, als etwas Kontaminiertes zu reinigen.
Sara