Als erfahrener Softwareentwickler habe ich gelernt, magische Fäden zu meiden.
Mein Problem ist, dass es so lange her ist, seit ich sie benutzt habe, dass ich die meisten Gründe dafür vergessen habe. Infolgedessen kann ich meinen weniger erfahrenen Kollegen nicht erklären, warum sie ein Problem sind.
Welche objektiven Gründe gibt es, sie zu vermeiden? Welche Probleme verursachen sie?
anti-patterns
Kramii
quelle
quelle
Antworten:
In einer kompilierten Sprache wird der Wert einer magischen Zeichenfolge beim Kompilieren nicht überprüft . Wenn die Zeichenfolge mit einem bestimmten Muster übereinstimmen muss, müssen Sie das Programm ausführen, um sicherzustellen, dass es zu diesem Muster passt. Wenn Sie beispielsweise eine Aufzählung verwendet haben, ist der Wert zum Zeitpunkt der Kompilierung mindestens gültig, auch wenn es sich möglicherweise um den falschen Wert handelt.
Wenn eine magische Zeichenfolge an mehreren Stellen geschrieben wird , müssen Sie sie alle ohne Sicherheit ändern (z. B. Fehler bei der Kompilierung). Dem kann entgegengewirkt werden, indem nur an einer Stelle deklariert und die Variable erneut verwendet wird.
Tippfehler können schwerwiegende Fehler werden. Wenn Sie eine Funktion haben:
und jemand tippt versehentlich:
Dies ist umso schlimmer, je seltener oder komplexer die Zeichenfolge ist, insbesondere wenn Sie Programmierer haben, die mit der Muttersprache des Projekts nicht vertraut sind.
Magic Strings sind selten selbstdokumentierend. Wenn Sie eine Zeichenfolge sehen, sagt dies nichts darüber aus, was die Zeichenfolge sonst sein könnte / sollte. Sie müssen wahrscheinlich in die Implementierung schauen, um sicherzugehen, dass Sie die richtige Zeichenfolge ausgewählt haben.
Diese Art der Implementierung ist undicht und erfordert entweder externe Dokumentation oder Zugriff auf den Code, um zu verstehen, was geschrieben werden soll, zumal er zeichengenau sein muss (wie in Punkt 3).
Neben den Funktionen zum Suchen von Zeichenfolgen in IDEs gibt es eine kleine Anzahl von Tools, die das Muster unterstützen.
Sie können zufällig dieselbe magische Schnur an zwei Stellen verwenden, wenn es sich wirklich um verschiedene Dinge handelt. Wenn Sie also ein Suchen und Ersetzen durchgeführt und beide geändert haben, könnte eine davon brechen, während die andere funktioniert.
quelle
Der Gipfel dessen, was die anderen Antworten verstanden haben, ist nicht, dass "magische Werte" schlecht sind, sondern dass sie sein sollten:
Was normalerweise akzeptable "Konstanten" von "magischen Werten" unterscheidet, ist ein Verstoß gegen eine oder mehrere dieser Regeln.
Konstanten erlauben es uns einfach, bestimmte Axiome unseres Codes auszudrücken.
Was mich zum Schluss bringt, dass eine übermäßige Verwendung von Konstanten (und damit eine übermäßige Anzahl von Annahmen oder Einschränkungen, die in Form von Werten ausgedrückt werden), auch wenn sie ansonsten die oben genannten Kriterien erfüllen (aber insbesondere wenn sie von diesen abweichen), Dies kann bedeuten, dass die zu entwickelnde Lösung nicht allgemein genug oder nicht gut strukturiert ist (und daher sprechen wir nicht mehr wirklich über die Vor- und Nachteile von Konstanten, sondern über die Vor- und Nachteile von gut strukturiertem Code).
Sprachen auf hoher Ebene haben Konstrukte für Muster in Sprachen auf niedrigerer Ebene, die Konstanten verwenden müssten. Die gleichen Muster können auch in der höheren Sprache verwendet werden, sollten es aber nicht sein.
Aber das kann ein Expertenurteil sein, das auf einem Eindruck aller Umstände beruht und wie eine Lösung aussehen sollte, und genau, wie dieses Urteil gerechtfertigt sein wird, wird stark vom Kontext abhängen. In der Tat kann es nicht nach einem allgemeinen Grundsatz gerechtfertigt sein, außer zu behaupten, "ich bin alt genug, um diese Art von Arbeit, mit der ich vertraut bin, schon besser gesehen zu haben"!
BEARBEITEN: Nachdem ich eine Bearbeitung akzeptiert, eine andere abgelehnt und jetzt meine eigene Bearbeitung durchgeführt habe, kann ich jetzt in Betracht ziehen, dass die Formatierung und der Interpunktionsstil meiner Regelliste ein für alle Mal festgelegt werden müssen, haha!
quelle
value / 2
, als wenn dieser Wert anderswovalue / VALUE_DIVISOR
definiert2
ist. Wenn Sie eine Methode zur Verarbeitung von CSVs verallgemeinern möchten, möchten Sie wahrscheinlich, dass das Trennzeichen als Parameter übergeben und überhaupt nicht als Konstante definiert wird. Aber im Kontext ist alles eine Frage des Urteils - @ WGroleaus Beispiel für dasSPEED_OF_LIGHT
ist etwas, das Sie explizit benennen möchten, aber nicht jedes Wort benötigt dies.quelle
Beispiel aus dem wirklichen Leben: Ich arbeite mit einem Drittsystem, in dem "Entitäten" mit "Feldern" gespeichert sind. Grundsätzlich ein EAV- System. Da es ziemlich einfach ist, ein weiteres Feld hinzuzufügen, können Sie auf eines zugreifen, indem Sie den Namen des Felds als Zeichenfolge verwenden:
(Beachten Sie die magische Zeichenfolge "ProductName")
Dies kann zu mehreren Problemen führen:
Daher bestand meine Lösung darin, Konstanten für diese Namen zu generieren, die nach Entitätstypen organisiert sind. So, jetzt kann ich verwenden:
Es ist immer noch eine String-Konstante und kompiliert genau die gleiche Binärdatei, hat aber mehrere Vorteile:
Als nächstes auf meiner Liste: Verstecke diese Konstanten hinter generierten stark typisierten Klassen - dann ist auch der Datentyp gesichert.
quelle
nameField = myEntity.ProductName;
.Magische Saiten sind nicht immer schlecht , daher kann es sein, dass Sie keinen pauschalen Grund finden, sie zu vermeiden. (Mit "magische Zeichenkette" meine ich Zeichenkettenliteral als Teil eines Ausdrucks und nicht als Konstante definiert.)
In bestimmten Fällen sollten magische Zeichenfolgen vermieden werden:
Aber in einigen Fällen sind "magische Saiten" gut. Angenommen, Sie haben einen einfachen Parser:
Hier gibt es wirklich keine Magie, und keines der oben beschriebenen Probleme trifft zu. Es wäre meiner Meinung nach kein Vorteil,
string Plus="+"
usw. zu definieren . Halten Sie es einfach.quelle
if (dx != 0) { grad = dy/dx; }
."+"
und"-"
mitTOKEN_PLUS
und ersetzt habenTOKEN_MINUS
. Jedes Mal, wenn ich es las, hatte ich das Gefühl, dass es schwieriger war, es zu lesen und zu debuggen. Auf jeden Fall ein Ort, an dem ich der Meinung bin, dass die Verwendung einfacher Zeichenfolgen besser ist.So fügen Sie vorhandene Antworten hinzu:
Internationalisierung (i18n)
Wenn der auf dem Bildschirm anzuzeigende Text fest codiert und in Funktionsebenen eingebettet ist, wird es sehr schwierig, Übersetzungen dieses Textes in andere Sprachen bereitzustellen.
Einige Entwicklungsumgebungen (z. B. Qt) verarbeiten Übersetzungen durch Nachschlagen von einer Basissprachentextzeichenfolge in die übersetzte Sprache. Magic Strings können dies im Allgemeinen überstehen - bis Sie sich entscheiden, denselben Text an einer anderen Stelle zu verwenden, und einen Tippfehler erhalten. Selbst dann ist es sehr schwer zu finden, welche magischen Zeichenfolgen übersetzt werden müssen, wenn Sie Unterstützung für eine andere Sprache hinzufügen möchten.
Einige Entwicklungsumgebungen (z. B. MS Visual Studio) verwenden einen anderen Ansatz und erfordern, dass alle übersetzten Zeichenfolgen in einer Ressourcendatenbank gespeichert und anhand der eindeutigen ID dieser Zeichenfolge für das aktuelle Gebietsschema zurückgelesen werden. In diesem Fall kann Ihre Anwendung mit magischen Zeichenfolgen einfach nicht ohne größere Überarbeitung in eine andere Sprache übersetzt werden. Für eine effiziente Entwicklung müssen alle Textzeichenfolgen in die Ressourcendatenbank eingegeben und beim ersten Schreiben des Codes mit einer eindeutigen ID versehen werden. Danach ist die Eingabe relativ einfach. Der Versuch, dies nachträglich nachzufüllen, erfordert normalerweise einen sehr großen Aufwand (und ja, ich war dabei!). Es ist also viel besser, die Dinge von Anfang an richtig zu machen.
quelle
Dies ist nicht für alle eine Priorität, aber wenn Sie jemals in der Lage sein möchten, Kopplungs- / Kohäsionsmetriken für Ihren Code automatisiert zu berechnen, machen magische Zeichenfolgen dies nahezu unmöglich. Eine Zeichenfolge an einer Stelle verweist auf eine Klasse, eine Methode oder eine Funktion an einer anderen Stelle, und es gibt keine einfache, automatische Möglichkeit, durch einfaches Parsen des Codes festzustellen, ob die Zeichenfolge mit der Klasse / Methode / Funktion gekoppelt ist. Nur das zugrunde liegende Framework (z. B. Angular) kann feststellen, dass eine Verknüpfung besteht - und das nur zur Laufzeit. Um die Kopplungsinformationen selbst zu erhalten, muss Ihr Parser über die Basissprache hinaus, in der Sie codieren, alles über das verwendete Framework wissen.
Aber auch dies ist für viele Entwickler nicht wichtig.
quelle