Ich habe in letzter Zeit ein wenig mit einem Kollegen diskutiert. Wir verwenden speziell C #, dies kann jedoch für jede Sprache mit nullfähigen Typen gelten. Angenommen, Sie haben einen Wert, der ein Maximum darstellt. Dieser Maximalwert ist jedoch optional. Ich behaupte, dass eine Nullable-Zahl vorzuziehen wäre. Mein Kollege befürwortet die Verwendung von Null unter Berufung auf Präzedenzfall. Zugegeben, Dinge wie Netzwerk-Sockets haben oft Null verwendet, um eine unbegrenzte Zeitüberschreitung darzustellen. Wenn ich heute Code schreiben würde, der sich mit Sockets befasst, würde ich persönlich einen Nullwert verwenden, da ich der Meinung bin, dass dies die Tatsache besser widerspiegeln würde, dass KEINE Zeitüberschreitung vorliegt.
Welche Darstellung ist besser? Beide erfordern eine Bedingungsprüfung für den Wert "none", aber ich glaube, dass ein nullbarer Typ die Absicht ein wenig besser vermittelt.
quelle
Antworten:
Erwägen:
Sprache,
Rahmen,
Kontext.
1. Sprache
Die Verwendung von ∞ kann eine Lösung für ein Maximum sein.
JavaScript hat zum Beispiel eine Unendlichkeit. C # nicht¹.
Ada hat zum Beispiel Bereiche. C # nicht.
In C # gibt es
int.MaxValue
, aber Sie können es in Ihrem Fall nicht verwenden.int.MaxValue
ist die maximale Ganzzahl von 2.147.483.647. Wenn Sie in Ihrem Code einen Maximalwert von etwas haben, z. B. einen maximal akzeptierten Druck, bevor etwas explodiert, hat die Verwendung von 2.147.483.647 keinen Sinn.2. Framework
.NET Framework ist in diesem Punkt eher inkonsistent und die Verwendung magischer Werte kann kritisiert werden.
Gibt beispielsweise
"Hello".IndexOf("Z")
einen magischen Wert zurück-1
. Es macht es vielleicht einfacher (oder?), Das Ergebnis zu manipulieren:anstatt eine benutzerdefinierte Struktur zu verwenden:
ist aber überhaupt nicht intuitiv. Warum
-1
nicht-123
? Ein Anfänger kann auch fälschlicherweise denken, dass0
dies auch "Nicht gefunden" bedeutet oder einfach nur "falsch"(position >= 0)
.3. Kontext
Wenn Ihr Code mit Zeitüberschreitungen in Netzwerk-Sockets zusammenhängt, ist es keine schlechte Idee , etwas zu verwenden, das seit Jahrzehnten von allen verwendet wird, um konsistent zu sein . Insbesondere
0
für ein Timeout ist sehr klar: Es ist ein Wert, der nicht Null sein kann. In diesem Fall kann die Verwendung einer benutzerdefinierten Klasse das Verständnis erschweren:Duration
auf 0 setzen , wennIsTimeoutEnabled
es wahr ist?IsTimeoutEnabled
falsch, was passiert, wenn ichDuration
auf 100 setze ?Dies kann zu mehreren Fehlern führen. Stellen Sie sich den folgenden Code vor:
Der Vorgang dauert zehn Sekunden. Können Sie sehen, was mit diesem Code nicht stimmt, ohne die Dokumentation der
Timeout
Klasse zu lesen ?Fazit
null
drückt gut die Idee aus, dass der Wert nicht hier ist. Es ist nicht vorgesehen. Nicht verfügbar. Es ist weder eine Zahl noch eine Null oder eine leere Zeichenfolge. Verwenden Sie es nicht für maximale oder minimale Werte.int.MaxValue
hängt stark mit der Sprache selbst zusammen. Nichtint.MaxValue
für eine maximale Geschwindigkeitsbegrenzung derVehicle
Klasse oder eine maximal zulässige Geschwindigkeit für ein Flugzeug usw. verwenden.Vermeiden Sie magische Werte wie
-1
in Ihrem Code. Sie sind irreführend und führen zu Fehlern im Code.Erstellen Sie Ihre eigene Klasse, die mit den angegebenen Minimal- / Maximalwerten einfacher zu handhaben ist. Zum Beispiel haben
VehicleSpeed
kannVehicleSpeed.MaxValue
.Befolgen Sie keine vorherigen Richtlinien und verwenden Sie magische Werte, wenn es sich um eine jahrzehntelange allgemeine Konvention in einem sehr speziellen Bereich handelt, die von den meisten Leuten verwendet wird, die Code in diesem Bereich schreiben.
Vergessen Sie nicht, Ansätze zu mischen. Beispielsweise:
¹ Sie können Ihren eigenen Typ erstellen, der Unendlich enthält. Ich spreche hier nur von einheimischem
int
Typ.quelle
int
, wenn ein Nackter nicht genug über den Typ aussagt, um das Problem einzuschränken, sollten Sie eine neue Struktur mit mehr Informationen in Betracht ziehen (const-Instanzen der Struktur, die beispielsweise magische Werte darstellen, oder eine Aufzählung, die darauf hinweist). Oder erwägen Sie die Programmierung von Verträgen oder andere Lösungen, aber ich denke, eine benutzerdefinierte Struktur ist am einfachsten.Null ist nicht besser als eine magische Zahl.
Das Wichtigste ist, die Werte mit magischen Effekten zu NAMEN, wenn Sie solche Werte haben müssen, und sicherzustellen, dass die Definitionen dieser Namen für jeden sichtbar sind, der auf den magischen Wert und die WTFs stößt.
quelle
MAGIC_NUMBER
Code sollte nach Möglichkeit unbedingt vermieden werden.null
ist ein viel klarerer Ausdruck der Absicht.quelle
In C # haben viele CLR-Klassen einen statischen
Empty
Member:System.String.Empty
System.EventArgs.Empty
System.Guid.Empty
System.Drawing.Rectangle.Empty
System.Windows.Size.Empty
So müssen Sie sich nicht merken, ob Sie einen magischen Wert oder null verwenden müssen, um ein leeres Objekt zu erstellen.
Aber was ist, wenn Sie es mit einem einfachen Werttyp wie einem zu tun haben
int
? Überlegen Sie in diesem Fall, ob Sie Opfer der primitiven Besessenheit werden . Es ist durchaus möglich, dass Ihre scheinbar einfache numerische Eigenschaft von einer eigenen Klasse oder Struktur profitiert, mit der Sie das Element angebenEmpty
und auch ein anderes Verhalten hinzufügen können, das für diese Art von Wert spezifisch ist.quelle
In diesem Fall ist der Nullwert ein guter Hinweis darauf, dass es kein Maximum gibt. Wenn der Sonderfall bedeutet, dass der betreffende Wert nicht zutrifft und Sie die konfigurierte Funktion einfach nicht möchten, ist null ein gutes Indiz dafür.
Ein Problem bei der Verwendung von Null zur Darstellung von Sonderfällen besteht darin, dass es nur einen Nullwert gibt und möglicherweise mehrere Sonderfälle vorliegen. In diesem Fall würde ich eine Aufzählung als zusätzlichen Parameter übergeben, der einen Sonderfall anzeigen oder den int-Wert normal verwenden kann. (Dies ist im Wesentlichen das, was das Nullable <> für Sie bewirkt, obwohl es einen Booleschen Wert anstelle einer Aufzählung verwendet und die Parameter in einer einzigen Struktur kombiniert.)
quelle
In diesem Fall ist ein nullbarer Typ meiner Meinung nach vollkommen sinnvoll.
Null bedeutet Wertlosigkeit. Dies ist ein deutlich anderes Konzept als eine Zahl mit dem Wert 0.
Wenn Sie "Wenn ich Ihnen keinen Wert gebe, verwenden Sie das Maximum" sagen möchten, ist die Übergabe von Null genau die richtige Art, dies auszudrücken.
quelle
Null: Häufiger Fehlerwert, nicht angegeben, ungültig oder nicht vorhanden.
Null: Ein tatsächlicher, aber nicht notwendigerweise logischer oder intuitiver Wert (in diesem Zusammenhang). Auch ein allgemeiner Wert bei der Initialisierung.
Im Zusammenhang mit Ihrem Problem ist die
timeoutInMilliseconds
Eigenschaft optional, und es wird nicht erwähnt, dass der Overhead dieses Ansatzes sie als Option disqualifizieren würde.Schlussfolgerung: Es gibt Ausnahmen, und die Lösungen variieren je nach Sprache und Bereich. In diesem Fall würde ich Null wählen. Ich glaube, manche Leute verstehen das falsch, wenn sie die Daten nicht gut von der Schnittstelle trennen. Sie erwarten lediglich, dass jeder Client die Dokumentation (oder Implementierung) liest, um zu bestimmen, wie diese speziellen Werte verwendet / gehandhabt werden sollen - die speziellen Fälle dringen in das Programm des Clients ein und es kann ziemlich unklar sein. Durch Hinzufügen einer guten Abstraktionsschicht kann die Verwendung viel klarer werden.
quelle
Null ist schlechter zu benutzen als
MagicNumber
. Null repräsentiert die Idee besser ausgedrückt, aber es ist nicht konsistent zwischen den Plattformen, wie es sich verhält, esMagicNumber
funktioniert immer gleich, was von Vorteil ist.je nach verwendeter umgebung / sprache könnte null sein
MagicNumber
verhält sich immer gleichquelle
Wenn Sie vergessen, nach der magischen Zahl zu suchen (was richtig sein wird), wird eine magische Zahl mit unsinnigen Daten für eine Weile fortgeführt. Es ist viel besser, eine Null zu haben, die so schnell wie möglich eine Ausnahme verursacht.
quelle
Null ist nicht die einzige Alternative zu einer magischen Zahl.
Null ist böse. Im obigen Beispiel könnten Sie damit durchkommen, da der Code offensichtlich mit einer Null umgehen kann. Im Allgemeinen passiert es jedoch, dass Sie früher oder später eine Nullzeigerausnahme erhalten, wenn Sie damit beginnen, Nullen weiterzugeben. Es kann sein, dass dies beim ersten Schreiben des Codes nicht der Fall ist, der Code bleibt jedoch weitaus länger als bei der ersten Version erhalten. Es wird oft von Leuten gepflegt, die nicht so viel über das System wissen wie die ursprünglichen Entwickler.
Scala (zum Beispiel) hat eine nette Alternative in der Optionsklasse. Die Option-Klasse hat einen von zwei Werten: Some (Einige) - umschließt den gewünschten Wert und None (Keine) - ohne Wert.
Das macht es für jeden Entwickler offensichtlich, dass es möglicherweise keinen Wert gibt und Sie einen besseren Code dafür hatten. Nun, es sollte es sowieso offensichtlich machen.
Und nicht alle magischen Zahlen sind ein Problem. Abhängig vom Kontext können 0, 1, 1024 usw. alle offensichtlich sein. 347? Ja, das solltest du vermeiden. :-)
quelle