In einem Code, den ich überprüfe, sehe ich Dinge, die dem folgenden moralischen Äquivalent entsprechen:
public class Foo
{
private Bar bar;
public MethodA()
{
bar = new Bar();
bar.A();
bar = null;
}
public MethodB()
{
bar = new Bar();
bar.B();
bar = null;
}
}
Das Feld bar
hier ist logischerweise eine lokale Variable, da sein Wert niemals für Methodenaufrufe beibehalten werden soll. Da jedoch viele der Methoden Foo
ein Objekt vom Typ benötigen Bar
, hat der ursprüngliche Codeautor gerade ein Feld vom Typ erstellt Bar
.
- Das ist offensichtlich schlecht, oder?
- Gibt es einen Namen für dieses Antimuster?
object-oriented
terminology
anti-patterns
JSB ձոգչ
quelle
quelle
MethodA
oderMethodB
UrsacheMethodA
oderMethodB
in irgendeiner Weise aufgerufen werden (undbar
wieder verwendet wird, in dem Fall derbar.{A,B}()
Täter zu sein) haben Sie ähnliche Probleme auch ohne Gleichzeitigkeit.Antworten:
Ja.
Dadurch werden die Methoden nicht mehr wiedereintrittsfähig. Dies ist ein Problem, wenn sie in derselben Instanz rekursiv oder in einem Kontext mit mehreren Threads aufgerufen werden.
Dies bedeutet, dass der Status von einem Anruf zu einem anderen Anruf durchgesickert ist (wenn Sie vergessen haben, die Neuinitialisierung durchzuführen).
Dies erschwert das Verständnis des Codes, da Sie überprüfen müssen, ob der Code tatsächlich funktioniert. (Im Gegensatz zur Verwendung lokaler Variablen.)
Es macht jede
Foo
Instanz größer als es sein muss. (Und stellen Sie sich dies für N Variablen vor ...)IMO, das verdient es nicht, Antimuster genannt zu werden. Es ist nur eine schlechte Programmiergewohnheit / ein Missbrauch von Java-Konstrukten / Mistcode. Dies ist die Art von Dingen, die im Code eines Studenten zu sehen sind, wenn der Student Vorlesungen übersprungen hat und / oder keine Programmierkenntnisse hat. Wenn Sie es in Seriencode sehen, ist es ein Zeichen dafür, dass Sie viel mehr Codeüberprüfungen durchführen müssen ...
Für die Aufzeichnung lautet die richtige Schreibweise:
Beachten Sie, dass ich auch die Methoden- und Variablennamen so korrigiert habe, dass sie den akzeptierten Stilregeln für Java-Bezeichner entsprechen.
quelle
Ich würde es als unnötig großen Bereich für eine Variable bezeichnen. Diese Einstellung berücksichtigt auch Race-Bedingungen, wenn mehrere Threads auf MethodA und MethodB zugreifen.
quelle
Dies ist ein spezieller Fall eines allgemeinen Musters, bekannt als
global doorknobbing
. Wenn Sie ein Haus bauen, ist es verlockend, nur einen Türknauf zu kaufen und herumliegen zu lassen. Wenn jemand eine Tür oder einen Schrank benutzen möchte, schnappt er sich einfach diesen einen globalen Türknauf. Wenn Türklinken teuer sind, kann es ein gutes Design sein.Leider zerbricht die Realität, wenn dein Freund vorbeikommt und der Türknauf gleichzeitig an zwei verschiedenen Orten benutzt wird. Wenn die Türklinke so teuer ist, dass Sie sich nur eine leisten können, lohnt es sich, ein System zu bauen, mit dem die Leute sicher auf die Türklinke warten können.
In diesem Fall ist der Türknauf nur eine Referenz, es ist also billig. Wenn der Türknauf ein tatsächliches Objekt war (und das Objekt anstelle der Referenz wiederverwendet wurde), ist es möglicherweise teuer genug, um ein Objekt zu sein
prudent global doorknob
. Wenn es jedoch billig ist, nennt man es acheapskate global doorknob
.Ihr Beispiel ist von der
cheapskate
Vielfalt.quelle
Das Hauptanliegen hier wäre Parallelität - Wenn das Foo von mehreren Threads verwendet wird, haben Sie ein Problem.
Darüber hinaus ist es einfach albern - lokale Variablen verwalten ihre eigenen Lebenszyklen perfekt. Das Ersetzen durch Instanzvariablen, die ungültig gemacht werden müssen, wenn sie nicht mehr nützlich sind, ist eine Aufforderung zum Fehler.
quelle
Es ist ein spezieller Fall von "inkorrektem Scoping" mit einer Seite von "variabler Wiederverwendung".
quelle
Es ist kein Anti-Muster. Anti-Patterns haben eine Eigenschaft, die es wie eine gute Idee erscheinen lässt, die die Leute dazu bringt, es absichtlich zu tun. Sie sind als Muster geplant und dann geht es fürchterlich schief.
Dies ist auch der Grund für Debatten darüber, ob es sich bei etwas um ein Muster, ein Anti-Muster oder ein häufig falsch angewendetes Muster handelt, das an einigen Stellen noch Verwendung findet.
Das ist einfach falsch.
Um ein bisschen mehr hinzuzufügen.
Dieser Code ist abergläubisch oder bestenfalls eine Frachtkultpraxis.
Ein Aberglaube ist etwas, das ohne klare Begründung getan wird. Es mag mit etwas Realem zusammenhängen, aber die Verbindung ist nicht logisch.
Eine Frachtkult-Praxis ist eine, bei der Sie versuchen, etwas zu kopieren, was Sie aus einer sachkundigeren Quelle gelernt haben, aber Sie kopieren tatsächlich eher die Oberflächenartefakte als den Prozess (so genannt für einen Kult in Papua-Neuguinea, der dies machen würde) Flugzeugsteuerradios aus Bambus in der Hoffnung, dass die japanischen und amerikanischen Flugzeuge des Zweiten Weltkriegs zurückkehren).
In beiden Fällen ist kein wirklicher Fall zu machen.
Ein Anti-Pattern ist ein Versuch, eine vernünftige Verbesserung zu erzielen, sei es in dem kleinen (dieser zusätzlichen Verzweigung, die zu dem zusätzlichen Fall führt, der behandelt werden muss, der zu Spaghetti-Code führt) oder in dem großen, in dem Sie ein Pattern sehr bewusst implementieren Das ist entweder diskreditiert oder umstritten (viele würden die Singletons als solche bezeichnen, wobei einige Objekte nur zum Schreiben (z. B. Protokollieren von Objekten) oder nur zum Lesen (z. B. Konfigurationseinstellungen) ausschließen und einige sogar diese verurteilen würden) oder wo Sie das lösen falsches Problem (als .NET zum ersten Mal herauskam, empfahl MS ein Muster für den Umgang mit der Entsorgung, wenn Sie sowohl nicht verwaltete als auch verwaltete Einwegfelder hatten - es geht in der Tat sehr gut mit dieser Situation um, aber das eigentliche Problem ist, dass Sie es haben beide Feldtypen derselben Klasse).
Als solches ist ein Anti-Pattern etwas, das eine kluge Person, die die Sprache, die Problemdomäne und die verfügbaren Bibliotheken gut kennt, absichtlich tut und das immer noch eine Kehrseite hat (oder von der behauptet wird), die die Kehrseite überwältigt.
Da keiner von uns anfängt, eine bestimmte Sprache, Problemdomäne und verfügbare Bibliotheken gut zu kennen, und jeder etwas übersehen kann, wenn er von einer vernünftigen Lösung zur nächsten wechselt (z. B. etwas in einem Feld für eine gute Verwendung ablegen und dann versuchen zu Refactor es weg, aber nicht den Job, und Sie werden am Ende mit Code wie in der Frage), und da wir alle Dinge von Zeit zu Zeit im Lernen vermissen, haben wir alle einige abergläubische oder Fracht-Kult-Code irgendwann erstellt . Das Gute ist, dass sie tatsächlich klarer zu identifizieren und zu korrigieren sind als Anti-Patterns. Wahre Anti-Muster sind entweder wohl keine Anti-Muster oder haben eine attraktive Qualität oder haben zumindest eine Möglichkeit, einen in sie zu locken, selbst wenn sie als schlecht identifiziert werden (zu viele und zu wenige Schichten sind beide unumstritten schlecht, aber vermeiden eine führt zum anderen).
quelle
(1) Ich würde sagen, dass es nicht gut ist.
Es führt eine manuelle Hausverwaltung durch, die der Stack automatisch mit lokalen Variablen durchführen kann.
Es gibt keinen Leistungsvorteil, da "neu" als Methodenaufruf bezeichnet wird.
BEARBEITEN: Der Speicherbedarf der Klasse ist größer, da der Balkenzeiger während der gesamten Lebensdauer der Klasse immer Speicher belegt. Wenn der Balkenzeiger lokal wäre, würde er nur für die Lebensdauer des Methodenaufrufs Speicher belegen. Der Speicher für den Zeiger ist nur ein Tropfen im Ozean, aber es ist immer noch ein unnötiger Tropfen.
Die Leiste ist für andere Methoden in der Klasse sichtbar. Methoden, die bar nicht verwenden, sollten es nicht sehen können.
Zustandsbasierte Fehler. In diesem speziellen Fall sollten Zustandsbasisfehler nur beim Multithreading auftreten, da jedes Mal "new" aufgerufen wird.
(2) Ich weiß nicht, ob es einen Namen dafür gibt, da es sich tatsächlich um mehrere Probleme handelt, nicht um eines.
- manuelle Reinigung, wenn Automatik verfügbar ist -
notwendiger Zustand -
Zustand, der länger lebt als seine Lebensdauer -
Sichtbarkeit oder Umfang ist zu hoch
quelle
Ich würde es "Wandering Xenophobe" nennen. Es möchte in Ruhe gelassen werden, weiß aber nicht genau, wo oder was es ist. Daher ist es eine schlechte Sache, wie andere gesagt haben.
quelle
Hier geht es gegen den Strich, aber obwohl ich das angegebene Beispiel in seiner aktuellen Form nicht als guten Codierungsstil betrachte, gibt es das Muster beim Testen von Einheiten.
Dies ist eine ziemlich übliche Methode zum Testen von Einheiten
ist nur eine Überarbeitung dieses Äquivalents des OP-Codes
Ich würde niemals Code schreiben, wie es in OPs Beispiel angegeben ist, es schreit nach Umgestaltung, aber ich betrachte das Muster weder als ungültig noch als Antimuster .
quelle
bar
umnull
, schafft JUnit ohnehin eine neue Testinstanz für jede Testmethode.Dieser Codegeruch wird bei Refactoring von Beck / Fowler als temporäres Feld bezeichnet.
http://sourcemaking.com/refactoring/temporary-field
Bearbeitet, um auf Anfrage der Moderatoren weitere Erklärungen hinzuzufügen: Weitere Informationen zum Codegeruch finden Sie in der oben angegebenen URL oder in der gedruckten Ausgabe des Buches. Da das OP nach dem Namen für diesen bestimmten Antimuster- / Codegeruch suchte, dachte ich, dass es hilfreich wäre, wenn ich einen zuvor nicht erwähnten Verweis von einer etablierten Quelle zitiere, die über 10 Jahre alt ist, obwohl mir völlig klar ist, dass ich zu spät bin Spiel auf diese Frage, so ist es unwahrscheinlich, dass die Antwort abgestimmt oder akzeptiert wird.
Wenn es nicht zu persönlich ist, verweise und erkläre ich diesen speziellen Code-Geruch auch in meinem bevorstehenden Pluralsight-Kurs Refactoring Fundamentals, der voraussichtlich im August 2013 veröffentlicht wird.
Lassen Sie uns darüber sprechen, wie Sie dieses spezielle Problem beheben können, um einen Mehrwert zu erzielen. Es gibt verschiedene Möglichkeiten. Wenn das Feld wirklich nur von einer Methode verwendet wird, kann es zu einer lokalen Variablen herabgestuft werden. Wenn jedoch mehrere Methoden das Feld für die Kommunikation verwenden (anstelle von Parametern), ist dies der in Refactoring beschriebene klassische Fall, der durch Ersetzen des Felds durch Parameter korrigiert werden kann, oder wenn die mit diesem Code arbeitenden Methoden eng beieinander liegen Im Zusammenhang kann Extract Class verwendet werden, um die Methoden und das / die Feld (er) in eine eigene Klasse zu ziehen, in der sich das Feld immer in einem gültigen Zustand befindet (möglicherweise während der Erstellung festgelegt) und den Zustand dieser neuen Klasse darstellt. Wenn Sie die Parameterroute durchlaufen, aber zu viele Werte übergeben werden müssen, besteht eine andere Option darin, ein neues Parameterobjekt einzuführen.
quelle
Ich würde sagen, wenn Sie es auf den Punkt bringen, ist dies wirklich ein Mangel an Zusammenhalt, und ich könnte ihm den Namen "Falscher Zusammenhalt" geben. Ich würde diesen Begriff prägen (oder, wenn ich ihn irgendwoher bekomme und es vergesse, "ausleihen"), weil die Klasse insofern zusammenhängend zu sein scheint, als ihre Methoden auf einem Mitgliedsfeld zu funktionieren scheinen. In Wirklichkeit ist dies jedoch nicht der Fall, was bedeutet, dass der scheinbare Zusammenhalt tatsächlich falsch ist.
Ob es schlecht ist oder nicht, ich würde sagen, es ist klar, und ich denke, Stephen C macht einen ausgezeichneten Job, um zu erklären, warum. Unabhängig davon, ob es den Namen "Anti-Pattern" verdient oder nicht, denke ich, dass es und jedes andere Codierungsparadigma mit einem Label zu tun haben könnte, da dies die Kommunikation im Allgemeinen erleichtert.
quelle
Abgesehen von den bereits erwähnten Problemen würde die Verwendung dieses Ansatzes in Umgebungen ohne automatische Garbage Collection (z. B. C ++) zu Speicherverlusten führen, da die temporären Objekte nach der Verwendung nicht freigegeben werden. (Obwohl dies ein bisschen weit hergeholt zu sein scheint, gibt es Leute da draußen, die einfach 'null' in 'NULL' ändern und froh sind, dass der Code kompiliert wird.)
quelle
Dies scheint mir eine schreckliche Fehlanwendung des Flyweight-Musters zu sein. Ich habe leider ein paar Entwickler gekannt, die das gleiche "Ding" mehrere Male in verschiedenen Methoden verwenden und es einfach in ein privates Feld ziehen müssen, um irrtümlich Speicher zu sparen oder die Leistung zu verbessern oder eine andere seltsame Pseudooptimierung durchzuführen. In ihren Gedanken versuchen sie, ein ähnliches Problem zu lösen, wie Flyweight es nur in einer Situation tun soll, in der es eigentlich kein Problem ist, das gelöst werden muss.
quelle
Ich habe dies oft erlebt, normalerweise beim Aktualisieren von Code, der zuvor von jemandem geschrieben wurde, der VBA For Dummies als ersten Titel aufnahm und dann ein relativ großes System in der Sprache schrieb, in die er gestolpert war.
Zu sagen, dass es wirklich schlechte Programmierpraktiken sind, ist richtig, aber es könnte nur eine Folge davon sein, dass wir keine von Internet und Fachleuten geprüften Ressourcen haben, wie wir sie heute alle genießen, die den ursprünglichen Entwickler möglicherweise auf einen "sichereren" Weg geführt haben.
Es hat das "Antipattern" -Tag zwar nicht wirklich verdient - aber es war gut, die Vorschläge zu sehen, wie das OP neu codiert werden könnte.
quelle