Ich neige dazu, alle Methoden in einer Klasse als statisch zu deklarieren, wenn diese Klasse keine internen Zustände verfolgen muss. Wenn ich beispielsweise A in B umwandeln muss und mich nicht auf einen internen Zustand C verlasse, der variieren kann, erstelle ich eine statische Transformation. Wenn es einen internen Zustand C gibt, den ich anpassen möchte, füge ich einen Konstruktor hinzu, um C festzulegen, und verwende keine statische Transformation.
Ich habe verschiedene Empfehlungen (einschließlich StackOverflow) gelesen, um statische Methoden NICHT zu überbeanspruchen, aber ich verstehe immer noch nicht, was mit der obigen Faustregel falsch ist.
Ist das ein vernünftiger Ansatz oder nicht?
Ein Objekt ohne internen Zustand ist verdächtig.
Normalerweise kapseln Objekte Status und Verhalten. Ein Objekt, das nur das Verhalten einschließt, ist ungerade. Manchmal ist es ein Beispiel für Leichtgewicht oder Fliegengewicht .
In anderen Fällen erfolgt die prozedurale Gestaltung in einer Objektsprache.
quelle
Dies ist wirklich nur eine Fortsetzung von John Millikins großartiger Antwort.
Obwohl es sicher sein kann, zustandslose Methoden (die so ziemlich Funktionen sind) statisch zu machen, kann dies manchmal zu einer Kopplung führen, die schwer zu ändern ist. Angenommen, Sie haben eine statische Methode als solche:
Was du nennst als:
Das ist alles schön und gut und sehr praktisch, bis Sie auf einen Fall stoßen, in dem Sie das Verhalten der statischen Methode ändern müssen und feststellen, dass Sie eng daran gebunden sind
StaticClassVersionOne
. Möglicherweise könnten Sie den Code ändern, und es wäre in Ordnung, aber wenn andere Anrufer vom alten Verhalten abhängig wären, müssten sie im Hauptteil der Methode berücksichtigt werden. In einigen Fällen kann dieser Methodenkörper ziemlich hässlich oder nicht mehr wartbar sein, wenn er versucht, all diese Verhaltensweisen auszugleichen. Wenn Sie die Methoden aufteilen, müssen Sie möglicherweise den Code an mehreren Stellen ändern, um dies zu berücksichtigen, oder neue Klassen aufrufen.Wenn Sie jedoch eine Schnittstelle erstellt haben, um die Methode bereitzustellen, und diese an Aufrufer weitergegeben haben, kann jetzt, wenn sich das Verhalten ändern muss, eine neue Klasse erstellt werden, um die Schnittstelle zu implementieren, die sauberer, einfacher zu testen und wartbarer ist. und das wird stattdessen den Anrufern gegeben. In diesem Szenario müssen die aufrufenden Klassen nicht geändert oder sogar neu kompiliert werden, und die Änderungen werden lokalisiert.
Es kann eine wahrscheinliche Situation sein oder auch nicht, aber ich denke, es lohnt sich, darüber nachzudenken.
quelle
Die andere Option besteht darin, sie als nicht statische Methoden zum Ursprungsobjekt hinzuzufügen:
dh ändern:
in
In vielen Situationen ist dies jedoch nicht möglich (z. B. bei der regulären Generierung von Klassencode aus XSD / WSDL / usw.), oder die Klasse wird sehr lang, und Transformationsmethoden können für komplexe Objekte oft ein echtes Problem sein, und Sie möchten sie nur in ihrer eigenen Klasse. Also ja, ich habe statische Methoden in Utility-Klassen.
quelle
Statische Klassen sind in Ordnung, solange sie an den richtigen Stellen verwendet werden.
Nämlich: Methoden, die 'Blatt'-Methoden sind (sie ändern den Status nicht, sie transformieren lediglich die Eingabe irgendwie). Gute Beispiele hierfür sind Dinge wie Path.Combine. Diese Art von Dingen sind nützlich und sorgen für eine engere Syntax.
Die Probleme, die ich mit der Statik habe, sind zahlreich:
Erstens, wenn Sie statische Klassen haben, werden Abhängigkeiten ausgeblendet. Folgendes berücksichtigen:
In TextureManager können Sie anhand eines Konstruktors nicht erkennen, welche Initialisierungsschritte ausgeführt werden müssen. Sie müssen sich mit der Klasse befassen, um ihre Abhängigkeiten zu finden und die Dinge in der richtigen Reihenfolge zu initialisieren. In diesem Fall muss der ResourceLoader vor der Ausführung initialisiert werden. Skalieren Sie nun diesen Abhängigkeitsalptraum und Sie können wahrscheinlich erraten, was passieren wird. Stellen Sie sich vor, Sie versuchen, Code zu verwalten, wenn keine explizite Reihenfolge für die Initialisierung vorliegt. Vergleichen Sie dies mit der Abhängigkeitsinjektion mit Instanzen - in diesem Fall wird der Code nicht einmal kompiliert, wenn die Abhängigkeiten nicht erfüllt sind!
Wenn Sie außerdem Statiken verwenden, die den Status ändern, ist dies wie ein Kartenhaus. Man weiß nie, wer Zugang zu was hat, und das Design ähnelt eher einem Spaghetti-Monster.
Schließlich und ebenso wichtig ist, dass die Verwendung von Statik ein Programm an eine bestimmte Implementierung bindet. Statischer Code ist das Gegenteil von Design für Testbarkeit. Das Testen von Code, der mit Statik durchsetzt ist, ist ein Albtraum. Ein statischer Aufruf kann niemals gegen ein Test-Double ausgetauscht werden (es sei denn, Sie verwenden Test-Frameworks, die speziell zum Verspotten statischer Typen entwickelt wurden). Ein statisches System bewirkt daher, dass alles, was ihn verwendet, ein sofortiger Integrationstest ist.
Kurz gesagt, Statik ist für einige Dinge in Ordnung und für kleine Werkzeuge oder Wegwerfcode würde ich ihre Verwendung nicht entmutigen. Darüber hinaus sind sie jedoch ein blutiger Albtraum für Wartbarkeit, gutes Design und einfache Tests.
Hier ist ein guter Artikel zu den Problemen: http://gamearchitect.net/2008/09/13/an-anatomy-of-despair-managers-and-contexts/
quelle
Der Grund, warum Sie vor statischen Methoden gewarnt werden, besteht darin, dass deren Verwendung einen der Vorteile von Objekten einbüßt. Objekte sind für die Datenkapselung vorgesehen. Dies verhindert das Auftreten unerwarteter Nebenwirkungen, wodurch Fehler vermieden werden. Statische Methoden haben keine gekapselten Daten * und bieten daher keinen Vorteil.
Wenn Sie jedoch keine internen Daten verwenden, sind diese in Ordnung und etwas schneller auszuführen. Stellen Sie jedoch sicher, dass Sie darin keine globalen Daten berühren.
quelle
Das scheint ein vernünftiger Ansatz zu sein. Der Grund, warum Sie nicht zu viele statische Klassen / Methoden verwenden möchten, ist, dass Sie sich von der objektorientierten Programmierung wegbewegen und sich mehr dem Bereich der strukturierten Programmierung zuwenden.
In Ihrem Fall, in dem Sie einfach A nach B transformieren, sagen wir, wir transformieren nur Text, von dem aus wir gehen
Dann wäre eine statische Methode sinnvoll.
Wenn Sie diese statischen Methoden jedoch häufig für ein Objekt aufrufen und sie für viele Aufrufe eindeutig sind (z. B. hängt die Art und Weise, wie Sie sie verwenden, von der Eingabe ab) oder Teil des inhärenten Verhaltens des Objekts ist, ist dies der Fall Sei weise, es zu einem Teil des Objekts zu machen und einen Zustand davon aufrechtzuerhalten. Eine Möglichkeit, dies zu tun, besteht darin, es als Schnittstelle zu implementieren.
Bearbeiten: Ein gutes Beispiel für die gute Verwendung statischer Methoden sind HTML-Hilfsmethoden in Asp.Net MVC oder Ruby. Sie erstellen HTML-Elemente, die nicht an das Verhalten eines Objekts gebunden sind und daher statisch sind.
Edit 2: Die funktionale Programmierung wurde in strukturierte Programmierung geändert (aus irgendeinem Grund war ich verwirrt), und Torsten wurde darauf hingewiesen, dass er darauf hingewiesen hat.
quelle
Ich habe kürzlich eine Anwendung überarbeitet, um einige Klassen zu entfernen / ändern, die ursprünglich als statische Klassen implementiert wurden. Im Laufe der Zeit haben diese Klassen so viel gewonnen und die Leute haben die neuen Funktionen immer wieder als statisch markiert, da nie eine Instanz herumschwebte.
Meine Antwort lautet also, dass statische Klassen nicht von Natur aus schlecht sind, es jedoch möglicherweise einfacher ist, jetzt mit dem Erstellen von Instanzen zu beginnen und sie später umzugestalten.
quelle
Ich würde es als Designgeruch betrachten. Wenn Sie hauptsächlich statische Methoden verwenden, haben Sie wahrscheinlich kein sehr gutes OO-Design. Es ist nicht unbedingt schlecht, aber wie bei allen Gerüchen würde es mich dazu bringen, anzuhalten und neu zu bewerten. Es deutet darauf hin, dass Sie möglicherweise ein besseres OO-Design erstellen können oder dass Sie in die andere Richtung gehen und OO für dieses Problem vollständig vermeiden sollten.
quelle
Ich pendelte zwischen einer Klasse mit einer Reihe statischer Methoden und einem Singleton hin und her. Beide lösen das Problem, aber der Singleton kann viel einfacher durch mehr als einen ersetzt werden. (Programmierer scheinen immer so sicher zu sein, dass es nur eine von etwas geben wird, und ich habe mich oft genug geirrt, um statische Methoden vollständig aufzugeben, außer in einigen sehr begrenzten Fällen).
Auf jeden Fall gibt Ihnen der Singleton die Möglichkeit, später etwas an die Factory zu übergeben, um eine andere Instanz zu erhalten, und dies ändert das Verhalten Ihres gesamten Programms ohne Refactoring. Das Ändern einer globalen Klasse statischer Methoden in etwas mit anderen "Hintergrund" -Daten oder einem etwas anderen Verhalten (untergeordnete Klasse) ist ein großes Problem.
Und statische Methoden haben keinen ähnlichen Vorteil.
Also ja, sie sind schlecht.
quelle
Solange kein interner Zustand ins Spiel kommt, ist dies in Ordnung. Beachten Sie, dass normalerweise erwartet wird, dass statische Methoden threadsicher sind. Wenn Sie also Hilfsdatenstrukturen verwenden, verwenden Sie diese threadsicher.
quelle
Wenn Sie wissen, dass Sie den internen Status von C niemals verwenden müssen, ist dies in Ordnung. Sollte sich dies in Zukunft jemals ändern, müssten Sie die Methode nicht statisch machen. Wenn es zunächst nicht statisch ist, können Sie den internen Status einfach ignorieren, wenn Sie ihn nicht benötigen.
quelle
Wenn es sich um eine Dienstprogrammmethode handelt, ist es schön, sie statisch zu machen. Guava und Apache Commons bauen auf diesem Prinzip auf.
Meine Meinung dazu ist rein pragmatisch. Wenn es sich um Ihren App-Code handelt, sind statische Methoden im Allgemeinen nicht das Beste. Statische Methoden unterliegen schwerwiegenden Einschränkungen beim Testen von Einheiten - sie können nicht einfach verspottet werden: Sie können keine verspottete statische Funktionalität in einen anderen Test einfügen. Normalerweise können Sie einer statischen Methode auch keine Funktionalität hinzufügen.
Daher habe ich in meiner App-Logik normalerweise kleine statische Dienstprogramm-ähnliche Methodenaufrufe. Dh
Einer der Vorteile ist, dass ich solche Methoden nicht teste :-)
quelle
Natürlich gibt es keine Silberkugel. Statische Klassen sind für kleine Dienstprogramme / Helfer in Ordnung. Aber die Verwendung statischer Methoden für die Programmierung von Geschäftslogik ist sicherlich böse. Betrachten Sie den folgenden Code
Sie sehen einen statischen Methodenaufruf für
ItemsProcessor.SplitItem(newItem);
Es riecht UrsacheBusinessService
Isolieren nicht testenItemsProcessor
(die meisten Testtools verspotten keine statischen Klassen) und es macht Unit-Tests unmöglich. Keine Unit Tests == geringe Qualitätquelle
Statische Methoden sind im Allgemeinen eine schlechte Wahl, selbst für zustandslosen Code. Erstellen Sie stattdessen eine Singleton-Klasse mit diesen Methoden, die einmal instanziiert und in die Klassen eingefügt wird, die die Methoden verwenden möchten. Solche Klassen sind leichter zu verspotten und zu testen. Sie sind viel objektorientierter. Sie können sie bei Bedarf mit einem Proxy umschließen. Statik macht OO viel schwieriger und ich sehe keinen Grund, sie in fast allen Fällen zu verwenden. Nicht 100%, aber fast alle.
quelle