it-swarm-eu.dev

Ist es jemals eine gute Idee, Werte in unsere Anwendungen fest zu codieren?

Ist es jemals eine gute Idee, Werte in unsere Anwendungen fest zu codieren? Oder ist es immer richtig, diese Wertetypen dynamisch aufzurufen, falls sie sich ändern müssen?

45
Edward

Ja, aber machen Sie es offensichtlich.

Tun:

  • benutze Konstanten
  • verwenden Sie einen beschreibenden Variablennamen

Nicht:

64
J.K.

Was ich bisher an diesen Fragen und Antworten merkwürdig finde, ist, dass niemand tatsächlich versucht hat, "Hardcode" oder, was noch wichtiger ist, die Alternativen klar zu definieren.

tl; dr: Ja, es ist Manchmal ist es eine gute Idee, Werte hart zu codieren, aber es gibt keine einfache Regel für wann; es hängt ganz vom Kontext ab.

Die Frage beschränkt es auf Werte, was ich als magische Zahlen verstehe, aber die Antwort darauf, ob sie eine gute Idee sind oder nicht, ist relativ zu = wofür sie eigentlich verwendet werden !

Einige Beispiele für "fest codierte" Werte sind:

  • Konfigurationswerte

    Ich erschrecke, wenn ich Aussagen wie command.Timeout = 600 Sehe. Warum 600? Wer hat das entschieden? War es vorher eine Zeitüberschreitung und jemand hat die Zeitüberschreitung als Hack ausgelöst, anstatt das zugrunde liegende Leistungsproblem zu beheben? Oder ist es tatsächlich eine bekannte und dokumentierte Erwartung für die Verarbeitungszeit?

    Dies sollten keine magischen Zahlen oder Konstanten sein, sie sollten in einer Konfigurationsdatei oder Datenbank irgendwo mit einem aussagekräftigen Namen externalisiert werden, da ihr optimaler Wert weitgehend oder vollständig von der Umgebung bestimmt wird, in der sich die Anwendung befindet läuft in.

  • Mathematische Formeln

    Formeln sind normalerweise ziemlich statisch, so dass die Art der darin enthaltenen konstanten Werte nicht besonders wichtig ist. Das Volumen einer Pyramide beträgt (1/3) b * h. Interessiert es uns, woher die 1 oder 3 kamen? Nicht wirklich. Ein früherer Kommentator hat zu Recht darauf hingewiesen, dass diameter = radius * 2 Wahrscheinlich besser ist als diameter = radius * RADIUS_TO_DIAMETER_CONVERSION_FACTOR - aber das ist eine falsche Zweiteilung.

    Was Sie für diese Art von Szenario tun sollten, ist das Erstellen einer Funktion. Ich muss nicht wissen, wie Sie gekommen sind mit der Formel, aber ich muss noch wissen wofür es ist. Wenn ich anstelle des oben geschriebenen Unsinns volume = GetVolumeOfPyramid(base, height) schreibe, wird plötzlich alles viel klarer und es ist vollkommen in Ordnung, magische Zahlen zu haben inside die Funktion (return base * height / 3), Weil es offensichtlich ist, dass sie nur ein Teil der Formel sind.

    Der Schlüssel hier ist natürlich, kurz und einfach Funktionen zu haben. Dies funktioniert nicht für Funktionen mit 10 Argumenten und 30 Berechnungszeilen. Verwenden Sie in diesem Fall die Funktionszusammensetzung oder Konstanten.

  • Domain-/Geschäftsregeln

    Dies ist immer die Grauzone, da dies davon abhängt, was genau der Wert ist. Meistens In dieser Zeit sind es diese besonderen magischen Zahlen, die Kandidaten für die Umwandlung in Konstanten sind, da dies das Verständnis des Programms erleichtert, ohne die Programmlogik zu komplizieren. Betrachten Sie den Test if Age < 19 Gegen if Age < LegalDrinkingAge; Sie haben wahrscheinlich können herausgefunden, was ohne die Konstante vor sich geht, aber mit dem beschreibenden Titel ist es einfacher.

    Diese können auch Kandidaten für die Funktionsabstraktion werden, zum Beispiel function isLegalDrinkingAge(age) { return age >= 19 }. Das einzige ist, dass Ihre Geschäftslogik oft viel komplizierter ist und es möglicherweise nicht sinnvoll ist, Dutzende von Funktionen mit jeweils 20 bis 30 Parametern zu schreiben. Wenn es keine eindeutige Abstraktion basierend auf Objekten und/oder Funktionen gibt, ist es in Ordnung, auf Konstanten zurückzugreifen.

    Die Einschränkung ist, wenn Sie für die Steuerabteilung arbeiten, wird es wirklich, wirklich lästig und ehrlich sinnlos, AttachForm(FORM_CODE_FOR_SINGLE_TAXPAYER_FILING_JOINTLY_FOR_DEPRECIATION_ON_ARMPIT_HAIR) zu schreiben. Sie werden das nicht tun, Sie werden AttachForm("B-46") tun, weil jeder einzelne Entwickler, der jemals dort gearbeitet hat oder jemals dort arbeiten wird, wissen wird, dass "B-46" der Formularcode für a ist einzelner Steuerzahler, der bla bla bla einreicht - die Formularcodes sind Teil der Domain selbst, sie ändern sich nie, also sind sie keine wirklich magischen Zahlen.

    Daher müssen Sie Konstanten in der Geschäftslogik sparsam verwenden. Grundsätzlich muss man verstehen, ob diese "magische Zahl" tatsächlich eine magische Zahl ist oder ob es sich um einen bekannten Aspekt der Domäne handelt. Wenn es sich um eine Domain handelt, codieren Sie sie nicht, es sei denn, es besteht eine gute Chance, dass sie sich ändert.

  • Fehlercodes und Statusflags

    Diese sind nie okay für Hardcode, wie jeder arme Bastard, der jemals mit dem Previous action failed due to error code 46 Getroffen wurde, Ihnen sagen kann. Wenn Ihre Sprache dies unterstützt, sollten Sie einen Aufzählungstyp verwenden. Andernfalls haben Sie normalerweise eine ganze Datei/ein ganzes Modul voller Konstanten, die die gültigen Werte für einen bestimmten Fehlertyp angeben.

    Lassen Sie mich niemals return 42 In einem Fehlerbehandler sehen, capiche? Keine Ausreden.

Ich habe wahrscheinlich mehrere Szenarien ausgelassen, aber ich denke, das deckt die meisten davon ab.

Also, ja, es ist manchmal akzeptabel, Dinge hart zu codieren. Sei einfach nicht faul; Es sollte eher eine bewusste Entscheidung sein als einfacher alter schlampiger Code.

27
Aaronaught

Es gibt verschiedene Gründe, einer Nummer eine Kennung zuzuweisen.

  • Wenn sich die Nummer ändern könnte, sollte sie eine Kennung haben. Es ist viel einfacher, NUMBER_OF_PLANETS zu finden, als nach jeder Instanz von 9 zu suchen und zu überlegen, ob sie in 8 geändert werden soll. (Beachten Sie, dass vom Benutzer sichtbare Zeichenfolgen muss sich möglicherweise ändern, wenn die Software jemals in einer anderen Sprache verwendet werden muss, und das ist im Voraus schwer vorherzusagen.)
  • Wenn die Zahl in irgendeiner Weise schwer einzugeben ist. Für Konstanten wie pi ist es besser, eine Definition mit maximaler Genauigkeit anzugeben, als sie an mehreren Stellen erneut einzugeben, möglicherweise ungenau.
  • Wenn die Zahl an verschiedenen Stellen vorkommt. Sie sollten sich nicht zwei Verwendungen von 45 in benachbarten Funktionen ansehen und sich fragen müssen, ob sie dasselbe bedeuten.
  • Wenn die Bedeutung nicht sofort erkennbar ist. Man kann davon ausgehen, dass jeder weiß, was 3.14159265 ... ist. Es ist nicht sicher anzunehmen, dass jeder die Gravitationskonstante oder sogar pi/2 erkennt. ("Jeder" hier hängt von der Art der Software ab. Von Systemprogrammierern kann erwartet werden, dass sie die oktale Darstellung von Unix-Berechtigungsbits oder dergleichen kennen. Überprüfen Sie in Software für Marine-/Schiffsarchitektur die Froude-Nummer eines vorgeschlagenen Rumpfs und die Geschwindigkeit auf zu sehen, ob es 1.1 oder höher ist, könnte für jeden, der daran arbeiten sollte, vollkommen selbsterklärend sein.)
  • Wenn der Kontext nicht erkennbar ist. Jeder weiß, dass eine Stunde 60 Minuten hat, aber das Multiplizieren oder Teilen mit 60 kann unklar sein, wenn es keine unmittelbaren Hinweise darauf gibt, dass die Menge ein Zeitwert oder ein Ratenwert ist .

Dies gibt uns Kriterien für hartcodierte Literale. Sie sollten unveränderlich sein, nicht schwer zu tippen, nur an einem Ort oder in einem Kontext vorkommen und eine erkennbare Bedeutung haben. Es macht keinen Sinn, beispielsweise 0 als ARRAY_BEGINNING oder 1 als ARRAY_INCREMENT zu definieren.

7
David Thornley

Als Ergänzung zu anderen Antworten. Verwenden Sie nach Möglichkeit Konstanten für Zeichenfolgen. Natürlich willst du nicht haben

const string server_var="server_var";

aber du solltest haben

const string MySelectQuery="select * from mytable;";

(Angenommen, Sie haben tatsächlich eine Abfrage, bei der Sie immer alle Ergebnisse aus einer bestimmten Tabelle abrufen möchten.)

Verwenden Sie ansonsten Konstanten für eine andere Zahl als 0 (normalerweise). Wenn Sie eine Berechtigungsbitmaske von 255 benötigen, verwenden Sie diese nicht

const int 8th_bit=255; //or some other obscure naming scheme that equates to 255.

stattdessen verwenden

const int AllowGlobalRead=255;

Natürlich wissen Sie zusammen mit Konstanten, wann Enumeratoren verwendet werden müssen. Der obige Fall würde wahrscheinlich gut in einen passen.

5
Earlz

Ist es jemals eine gute Idee, Werte in unsere Anwendungen fest zu codieren?

I Hardcode-Werte nur wenn die Werte angegeben in der Spezifikation sind (bei einer endgültigen Veröffentlichung der Spezifikation), z. Die HTTP-OK-Antwort lautet immer 200 (es sei denn, es ändert sich im RFC), daher sehen Sie (in einigen meiner Codes) Konstanten wie:

public static final int HTTP_OK = 200;

Ansonsten speichere ich Konstanten in der Eigenschaftendatei.

Der Grund, warum ich Spezifikationen angegeben habe, ist, dass das Ändern von Konstanten in Spezifikationen ein Änderungsmanagement erfordert, bei dem die Stakeholder die Änderung überprüfen und genehmigen/ablehnen. Es passiert nie über Nacht und es dauert Monate/Jahre für eine Genehmigung. Vergessen Sie nicht, dass viele Entwickler Spezifikationen (z. B. HTTP) verwenden. Wenn Sie diese ändern, werden Millionen von Systemen beschädigt.

4
Buhake Sindi

Es hängt davon ab, was Sie als Hardcodierung betrachten. Wenn Sie versuchen, alle fest codierten Dinge zu vermeiden, landen Sie im Gebiet Softcoding und erstellen ein System, das nur der Ersteller verwalten kann (und das ist der ultimative Hardcode).

Viele Dinge sind in einem vernünftigen Rahmen fest codiert und funktionieren. Das heißt, es gibt keinen technischen Grund, warum ich den Einstiegspunkt einer C # -Anwendung (statische Leere Main) nicht ändern sollte, sondern eine Hardcodierung, die für keinen Benutzer Probleme verursacht (außer gelegentlich SO-Frage =)

Die Faustregel, die ich verwende, lautet, dass alles, was sich ändern kann und wird, ohne den Zustand des gesamten Systems zu beeinflussen, konfigurierbar sein sollte.

Also, IMHO, es ist albern, Dinge, die sich nie ändern, nicht fest zu codieren (pi, Gravitationskonstante, eine Konstante in einer mathematischen Formel - denken Sie an das Volumen einer Kugel).

Es ist auch albern, Dinge oder Prozesse, die sich auf Ihr System auswirken und in jedem Fall programmiert werden müssen, nicht fest zu codieren, dh es ist verschwenderisch, dem Benutzer das Hinzufügen dynamischer Felder zu einem Formular zu ermöglichen, wenn ein zusätzliches Feld dies vom Wartungsentwickler erfordern würde Gehen Sie hinein und schreiben Sie ein Skript, mit dem das Ding funktioniert. Es ist auch dumm (und ich habe es einige Male in Unternehmensumgebungen gesehen), ein Konfigurationstool zu erstellen, sodass nichts fest codiert ist, aber nur die Entwickler in der IT-Abteilung können es verwenden, und es ist nur geringfügig einfacher zu verwenden als um es in Visual Studio zu tun.

Unterm Strich hängt es also von zwei Variablen ab, ob ein Objekt fest codiert werden soll:

  • wird sich der Wert ändern
  • wie wirkt sich eine Änderung des Werts auf das System aus?
4
SWeko
  • wenn sich der Wert ändern kann und tatsächlich ändern kann, codieren Sie ihn nach Möglichkeit per Softcode, solange der Aufwand die erwartete Rendite nicht überschreitet
  • einige Werte können nicht können weich codiert werden. Befolgen Sie in diesen (seltenen) Fällen die Richtlinien von Jonathan
3
Steven A. Lowe

Ich habe festgestellt, dass jedes Mal, wenn Sie Daten aus Ihrem Code extrahieren können, die verbleibenden Daten verbessert werden. Sie bemerken neue Refactorings und verbessern ganze Abschnitte Ihres Codes.

Es ist nur eine gute Idee, auf das Extrahieren von Konstanten hinzuarbeiten. Betrachten Sie es nicht als dumme Regel, sondern betrachten Sie es als eine Möglichkeit, besser zu codieren.

Der größte Vorteil wäre die Art und Weise, wie Sie ähnliche Konstanten als einzigen Unterschied in Codegruppen finden. Wenn ich sie in Arrays abstrahiere, kann ich einige Dateien um 90% ihrer Größe reduzieren und in der Zwischenzeit einige Fehler beim Kopieren und Einfügen beheben .

Ich habe noch keinen einzigen Vorteil darin gesehen, keine Daten zu extrahieren.

3
Bill K

Ich habe kürzlich eine MySQL-Funktion codiert, um den Abstand zwischen zwei Lat/Long-Paaren richtig zu berechnen. Sie können nicht einfach Pythagorus machen; Längengradlinien rücken näher zusammen, wenn der Breitengrad in Richtung der Pole zunimmt, so dass es sich um einen haarigen Trigger handelt. Der Punkt ist, ich war ziemlich hin und her gerissen, ob ich den Wert, der den Radius der Erde in Meilen darstellt, hart codieren soll.

Am Ende habe ich es getan, obwohl die Lat/Lng-Linien auf dem Mond viel näher beieinander liegen. Und meine Funktion würde Entfernungen zwischen Punkten auf Jupiter drastisch unterschätzen. Ich fand die Wahrscheinlichkeit, dass die Website, die ich baue, mit einem außerirdischen Standort betreten wird, ziemlich gering.

2
Dan Ray

Nun, es hängt davon ab, ob Ihre Sprache kompiliert ist. Wenn es nicht kompiliert ist, ist es keine große Sache, Sie bearbeiten nur den Quellcode, auch wenn es für einen Nicht-Programmierer etwas heikel ist.

Wenn Sie mit einer kompilierten Sprache programmieren, ist dies eindeutig keine gute Idee, da Sie bei einer Änderung der Variablen eine Neukompilierung durchführen müssen. Dies ist eine große Zeitverschwendung, wenn Sie diese Variable anpassen möchten.

Sie müssen keinen Schieberegler oder keine Schnittstelle erstellen, um seine Variable dynamisch zu ändern, aber das Mindeste, was Sie tun können, ist eine Textdatei.

Zum Beispiel verwende ich bei meinem Oger-Projekt immer die ConfigFile-Klasse, um eine Variable zu laden, die ich in eine Konfigurationsdatei geschrieben habe.

1
jokoon

Zwei Fälle, in denen Konstanten (zumindest meiner Meinung nach) in Ordnung sind:

  1. Konstanten, die sich auf nichts anderes beziehen; Sie können diese Konstanten jederzeit ändern, ohne etwas anderes ändern zu müssen. Beispiel: Die Standardbreite einer Rasterspalte.

  2. Absolut unveränderliche, präzise, ​​offensichtliche Konstanten wie "Anzahl der Tage pro Woche". days = weeks * 7 Ersetzen 7 mit einer Konstanten DAYS_PER_WEEK liefert kaum einen Wert.

1
user281377

Ich stimme Jonathan vollkommen zu, aber da es alle Regeln gibt, gibt es Ausnahmen ...

"Magische Nummer in der Spezifikation: Magische Nummer im Code"

Grundsätzlich heißt es, dass alle magischen Zahlen, die nach vernünftigen Versuchen, einen beschreibenden Kontext für sie zu erhalten, in der Spezifikation verbleiben, als solche im Code wiedergegeben werden sollten. Wenn magische Zahlen im Code verbleiben, sollten alle Anstrengungen unternommen werden, um sie zu isolieren und sie eindeutig mit ihrem Ursprungsort zu verknüpfen.

Ich habe einige Schnittstellenverträge abgeschlossen, bei denen Nachrichten mit Werten aus der Datenbank gefüllt werden müssen. In den meisten Fällen ist die Zuordnung ziemlich einfach und würde in Jonathans allgemeine Richtlinien passen, aber ich bin auf Fälle gestoßen, in denen die Zielnachrichtenstruktur einfach schrecklich war. Mehr als 80% der Werte, die in der Struktur weitergegeben werden mussten, waren Konstanten, die durch die Spezifikation des entfernten Systems erzwungen wurden. Dies zusammen mit der Tatsache, dass die Nachrichtenstruktur gigantisch war, führte dazu, dass eine Menge solcher Konstanten ausgefüllt werden mussten. In den meisten Fällen gaben sie keine Bedeutung oder keinen Grund an, sondern sagten nur "hier M setzen" oder "hier 4.10.53.10100.889450.4452 setzen". Ich habe auch nicht versucht, einen Kommentar neben alle zu setzen, da dies den resultierenden Code unlesbar gemacht hätte. Ich habe jedoch sichergestellt, dass die Codeabschnitte, in denen diese magischen Werte angezeigt werden, ordnungsgemäß isoliert sind und dass ihre Container (Klassen, Pakete) entsprechend benannt sind, um direkt auf die Spezifikation zu verweisen, die sie erzwingt.

Das heißt, wenn Sie darüber nachdenken ... geht es so ziemlich darum, es offensichtlich zu machen ...

0
Newtopian

Wenn Sie den Wert der Gravitationskonstante der Erde fest codieren, wird es niemanden interessieren. Wenn Sie die IP-Adresse Ihres Proxyservers fest codieren, treten Probleme auf.

0
jwenting

Meistens nein, aber ich denke, das ist erwähnenswert, dass Sie die meisten Probleme haben werden, wenn Sie anfangen, den fest codierten Wert zu duplizieren. Wenn Sie es nicht duplizieren (z. B. nur einmal in der Implementierung einer Klasse verwenden), ist es möglicherweise in Ordnung, keine Konstante zu verwenden.

0
user22908