Code, der einen Wert in eine andere Darstellung konvertiert und ihn dann wieder an den Ausgangspunkt zurückkonvertiert, ist schlecht, aber wie? [geschlossen]

35

Ich las einen Artikel über schlechte Programmierpraktiken .

Es wurde erwähnt -

"Yo-Yo-Code", der einen Wert in eine andere Darstellung konvertiert und ihn dann wieder an die ursprüngliche Position zurücksetzt (z. B .: Konvertieren einer Dezimalzahl in eine Zeichenfolge und dann zurück in eine Dezimalzahl oder Auffüllen einer Zeichenfolge und anschließendes Zuschneiden)

Ich verstehe nicht, warum das besondere Beispiel, das er gibt, eine schlechte Art ist, Programme zu schreiben. Es scheint mir in Ordnung, zurück zu konvertieren, wenn die Situation dies erfordert, damit der Wert verwendet werden kann.

Kann mir jemand mehr darüber erklären?

user13107
quelle
4
Empfohlene Lektüre: Diskutiere diesen $ {blog}
Mücke
8
Die meiste Zeit ist es nur überflüssig und es passiert nur, weil der Programmierer keinen besseren Weg wusste, um das zu bekommen, was er wollte. Der Blog - Eintrag gibt ein typisches Beispiel ein paar Absätze später: "Roundabout code" that accomplishes in many instructions what could be done with far fewer (eg: rounding a number by converting a decimal into a formatted string, then converting the string back into a decimal). if the situation is so that they have to be used?- Welche Situation wäre das?
Konrad Morawski
3
@gnat Ich verstehe nicht, wie das dies zu einer schlechten Frage macht. Wenn Sie möchten, kann ich es bearbeiten, um zu sagen: "Ist Code, der einen Wert konvertiert und zurück konvertiert, schlecht?" und es passt nicht mehr zu dieser Vorlage.
Djechlin
5
Kürzlich habe ich in Java Code gefunden, der über ein Array iteriert und jedes Objekt in ein JSON-Objekt serialisiert, wobei eine Zeichenfolgenverkettung verwendet wird, kein JSON-Serializer. Das Ergebnis wurde dann an eine private Methode übergeben, die das JSON-Array analysierte, um eine Reihe von IDs zu extrahieren, und die IDs dann an eine andere Stelle weitergab. Dies war die einzige Verwendung dieses JSON-Arrays im System. Das ist Jojo-Code. Es gab keinen Grund für eine Transformation hin und her. Wir hätten einfach die IDs der ursprünglichen Objekte übergeben können.
Brandon
3
decimal myValue = decimal.Parse(dataReader["myColumn"].ToString())ist ein Haustier Peeve von mir.
Matthew

Antworten:

125

Auch wenn Sie tun müssen sowohl die numerische als auch die Zeichenfolgendarstellung einer Zahl, ist es besser , nur einmal zu konvertieren und auch auf den ursprünglichen Wert hängen, anstatt wieder zu konvertieren jedes Mal , wenn der eine oder andere benötigen.

Das Prinzip ist, wie immer, dass Code, der nicht existiert, keine subtilen Mängel aufweisen kann , während Code, der oft existiert, dies tut. Das klingt vielleicht paranoid, aber die Erfahrung lehrt uns, dass es angebracht ist. Wenn Sie sich der Programmierung mit der permanenten Sorge nähern, "Ich bin nicht wirklich schlau genug, um dieses komplexe System zu verstehen", sind Sie auf dem richtigen Weg.

Kilian Foth
quelle
5
Gut gesagt. Wir Programmierer sollten alle so vorsichtig sein.
Neil
58
"Code, der nicht existiert, kann keine subtilen Mängel aufweisen, Code, der oft existiert," wünschte, ich könnte Ihnen dafür +2 geben. Unterschätzen Sie niemals den Wert, keinen Code schreiben zu müssen.
Benjamin Gruenbaum
2
Einige einfache Operationen (Konvertieren in String und zurück) sind jedoch möglicherweise weniger komplex (einfacher zu verstehen und zu codieren) als die "richtige" Art, die Bits zu manipulieren. Es ist oft eine gute Idee, alle Daten einer Kategorie in einem einzigen Formular zu speichern, auch wenn bestimmte Daten zwangsläufig in andere Formulare konvertiert werden.
Daniel R Hicks
36
@DanielRHicks also lasst uns dieses einfache Datum (10. November 2014) in einen String umwandeln, -> 10-11-2014 und zurück zu einem Datum -> (11. Oktober 2014) hey warte was?
Pieter B
20
@PieterB Es gibt eine große deutsche Buchhaltungssoftware, die auf Computern mit einem nicht deutschen Gebietsschema nicht funktioniert, da dies der Fall ist. Es konvertiert zuerst das Datum unter Verwendung des Systemgebietsschemas in eine Zeichenfolge und versucht dann, es mit einem festen Gebietsschema zu analysieren, und beklagt sich über das illegale Format. Dasselbe gilt für Zahlen und unterschiedliche Dezimaltrennzeichen, mit der Ausnahme, dass sie sich dort nicht beschweren, die Daten verfälschen und seltsames Verhalten zeigen. Ich habe Tage gebraucht, um das herauszufinden.
CodesInChaos
23

Es ist aus drei Hauptgründen schlecht:

  1. Es zeigt, dass Sie nicht darüber nachgedacht haben, welchen Typ / welches Format die Variable eigentlich haben sollte, sondern sie stattdessen in das konvertieren, was Sie gerade benötigen. Dies zeigt den Mangel an Designgedanken.
  2. Es ist wahrscheinlich verschwenderisch. Sie verschwenden mit ziemlicher Sicherheit Zyklen und Codezeilen und führen Konvertierungen durch, die nicht vorhanden sein müssen. Dadurch wird Ihr Code langsamer und aufgeblähter als nötig.
  3. Typkonvertierungen sind anfällig für subtile Fehler. Indem Sie diese Konvertierungen in Ihrem Code vermerken, erhöhen Sie die Fehlerwahrscheinlichkeit.

Ich vermute, Grund 1 ist der Grund, an den Ihre Quelle aufgrund des Kontexts gedacht hat, in dem sie erwähnt wurde.

Jack Aidley
quelle
6

Ich würde die Beschreibung als "Code" umformulieren, der einen Typ in eine andere Darstellung umwandelt , um etwas zu tun, was im Original genauso gut oder besser hätte gemacht werden können, und es dann wieder zurück umwandeln andere Art, wirken auf mich, und sich zurück Umwandlung ist völlig angemessen und Versagen zu tun , würde zu falschem Verhalten so führen.

Ein Beispiel für eine gute Konvertierung:
Man hat vier floatWerte von beliebigen Vorzeichen, deren Größen sich um einen Faktor von bis zu 1.000 unterscheiden können, und man muss die Summe zuletzt auf 0,625 Einheiten genau berechnen. Das Konvertieren aller vier Werte in double, das Berechnen der Summe und das Zurückkonvertieren des Ergebnisses in floatist wesentlich effizienter als dies bei einem Ansatz floatallein der Fall wäre .
Gleitkommawerte sind bestenfalls auf 0,5 Einheiten (ULP) genau. Dieses Beispiel würde erfordern, dass der Worst-Case-Rundungsfehler nicht mehr als 25% über dem optimalen Worst-Case-Fehler liegt. Die Verwendung eines Doppels ergibt einen Wert, der innerhalb von 0,5001 ULP genau ist. Während eine ULP-Anforderung von 0,625 erfunden zu sein scheint, sind solche Anforderungen in sukzessiven Approximationsalgorithmen häufig wichtig. Je genauer die Fehlergrenze angegeben wird, desto geringer ist die Anforderung an die Iteration im ungünstigsten Fall.

Ein Beispiel für eine schlechte Konvertierung:
Man hat eine Gleitkommazahl und möchte einen String ausgeben, der seinen Wert eindeutig darstellt. Ein Ansatz besteht darin, die Zahl in eine Zeichenfolge mit einer bestimmten Anzahl von Ziffern zu konvertieren, sie zurück zu konvertieren und zu prüfen, ob das Ergebnis übereinstimmt.

Aber das ist eigentlich ein schlechter Ansatz. Wenn eine Dezimalzeichenfolge einen Wert darstellt, der fast genau auf dem halben Weg zwischen zwei Gleitkommawerten liegt, ist es für eine Zeichenfolge-zu-Gleitkomma-Methode ziemlich teuer, sicherzustellen, dass sie immer den näheren floatWert ergibt, und viele solche Konvertierungsmethoden geben keinen Wert an Halten Sie eine solche Garantie nicht ein (unter anderem würde dies in einigen Fällen das Lesen aller Ziffern einer Zahl erfordern, selbst wenn sie Milliarden von Ziffern lang wäre).

Es ist viel billiger für eine Methode, zu garantieren, dass sie immer einen Wert zurückgibt, der innerhalb von 0,5625 Einheiten an der letzten Stelle (ULP) des dargestellten Werts liegt. Eine robuste "umkehrbare" Formatierungsroutine von Dezimal zu Zeichenfolge sollte berechnen, wie weit der Ausgabewert vom korrekten Wert entfernt ist, und die Ausgabe von Ziffern fortsetzen, bis das Ergebnis innerhalb von 0,375 (ULP) liegt, wenn nicht 0,25 (ULP). Andernfalls wird möglicherweise eine Zeichenfolge ausgegeben, die einige Konvertierungsmethoden ordnungsgemäß verarbeiten, andere Konvertierungsmethoden jedoch nicht.

Manchmal ist es besser, eine Ziffer auszugeben, die möglicherweise nicht "notwendig" ist, als einen Wert auszugeben, der möglicherweise falsch interpretiert wird. Entscheidend ist, dass die Entscheidung darüber, wie viele Ziffern ausgegeben werden sollen, auf numerischen Berechnungen im Zusammenhang mit dem Ausgabeprozess und nicht auf dem Ergebnis des Versuchs einer bestimmten Methode, die Zeichenfolge wieder in eine Zahl umzuwandeln, basiert.

Superkatze
quelle
1
Ihr Beispiel gibt nicht den ursprünglichen Wert zurück, nach dem das OP fragt. Es wird lediglich ein Wert desselben Typs zurückgegeben, der aus mehreren Eingaben berechnet wurde.
CJ Dennis
2

Aus verschiedenen Gründen

  1. Es ist sinnlos und erhöht die Komplexität - sowohl in Bezug auf die zu schreibende und zu wartende Codemenge als auch in Bezug auf die benötigte CPU-Zeit

    1. Es kann an Genauigkeit verlieren oder den Wert komplett verfälschen

    2. Es verschwendet Speicher (möglicherweise, abhängig von der Sprache), wenn Sie mehr Darstellungen einer Zahl speichern, die Sie benötigen

Es empfiehlt sich nur, die erste möglichst genaue Darstellung aller von Ihnen empfangenen Daten beizubehalten. Führen Sie mit diesen Daten Berechnungen durch und konvertieren Sie sie nur, wenn Sie sie ausgeben oder in einem besser lesbaren Format anzeigen müssen.

Jon Geschichte
quelle
dies scheint nicht alles wesentliche über Punkte gemacht hinzuzufügen und erklärte in früheren Antworten
gnat
2
Rechtfertigt das eine Ablehnung? Ich glaube, mein Beitrag ist möglicherweise prägnanter
Jon Story
vor Antworten tatsächlich aussehen prägnant mir, beide
gnat
0

Warum? Denn auch die Besten von uns können Fehler machen.

Sehen Sie sich an, was passiert ist, als Microsoft versucht hat, ein Roundtrip-Format zu implementieren, um sicherzustellen, dass die Konvertierung von Float-Zeichenfolgen sicher ist: https://stackoverflow.com/q/24299692/541686

Mehrdad
quelle
0

Als ich in der Schule war (und nach der Schule in der Elektrotechnik), wurde uns nach dem Multiplizieren das Teilen beigebracht. Division oft viele Ziffern und wird gerundet. Multiplikation nach Division multipliziert den Divisionsfehler.

Typkonvertierungen sind gleich, Sie laufen Gefahr, Daten zu verlieren. CInt (1,3) = 1.

In meiner Sprache, Basic, führen wir nur Typkonvertierungen durch (ein VB6-Programm verbringt 90% seiner Zeit mit der ANSI / Unicode-Konvertierung, für alle API-Aufrufe, die von der Laufzeit ausgeführt werden).

Die Typkonvertierung ist in allem, was wir tun, impliziert.

 Print 5

Die Zeichenfolge "5" wird aus dem numerischen Literal gedruckt.

form1.caption = "My Form"

Das Unicode-Zeichenfolgenliteral wird in eine ANSI-Zeichenfolge konvertiert und vom Formularpaket an SetWindowsTextA gesendet.

Auch das funktioniert in Basic

a = "5"
b = 3

c = a + b (= 8)

Ich bin heutzutage ein Variantenprogrammierer - ich denke nicht einmal an Typ. Ich verlasse mich nur auf die Autokonvertierungen.

Sowieso sind meine 3 Haustierhülsen

Zuweisen von Zeichenfolgenliteralen zu Variablen, um sie zu verwenden (verschwendet Speicher und Zeit)

Sinnlose Funktionen, wenn Code inline sein könnte (und der Compiler wird wahrscheinlich Ihre Funktion rückgängig machen und es trotzdem inline setzen)

Setzen Sie alle Objekte auf nichts als die letzten Zeilen vor einer End Function oder einem Programmende.

und ein viertes für Kurzprogramme

3 Variablen in einem 5-Zeilen-Programm sinnlos dimmen.

triggeradeadcat
quelle