Über die Debatte über nicht nullbare Typen

7

Ich höre immer wieder, dass Leute darüber reden, wie nicht-nullbare Referenztypen so viele Fehler lösen und die Programmierung so viel einfacher machen. Selbst der Schöpfer von Null nennt es seinen Milliarden Dollar Fehler , und Spec # hat nicht nullable Typen eingeführt, um dieses Problem zu bekämpfen.

BEARBEITEN: Ignoriere meinen Kommentar zu Spec #. Ich habe missverstanden, wie es funktioniert.

BEARBEITEN 2: Ich muss mit den falschen Leuten reden, ich habe wirklich gehofft, dass jemand streiten könnte: -)

Ich würde also vermuten, dass ich in der Minderheit bin, dass ich falsch liege, aber ich kann nicht verstehen, warum diese Debatte einen Sinn hat. Ich sehe null als Tool zur Fehlersuche. Berücksichtigen Sie Folgendes:

%Vor%

BAM! Zugriffsverletzung. Jemand hat vergessen, c zu initialisieren.

Betrachten Sie nun Folgendes:

%Vor%

Hoppla. Die Schleife wird automatisch übersprungen. Es könnte eine Weile dauern, um das Problem zu finden.

Wenn Ihre Klasse leer ist, wird der Code trotzdem fehlschlagen. Warum lässt dich das System nicht (etwas unhöflich) sagen, anstatt es selbst herausfinden zu müssen?

    
zildjohn01 13.03.2009, 03:05
quelle

8 Antworten

12

Es ist ein wenig merkwürdig, dass die Antwort, die in diesem Thread mit "Antwort" markiert ist, das Problem mit null an erster Stelle hervorhebt, nämlich:

  

Ich habe auch das meiste meiner NULL gefunden   Zeigerfehler drehen sich um   Funktionen vom Vergessen bis zur Überprüfung   Rückgabe der Funktionen von string.h,   wobei NULL als Indikator verwendet wird.

Wäre es nicht schön, wenn der Compiler diese Art von Fehlern zur Kompilierzeit anstatt zur Laufzeit erfassen könnte?

Wenn Sie eine ML-ähnliche Sprache (SML, OCaml, SML und F # in gewissem Umfang) oder Haskell verwendet haben, sind Referenztypen nicht nullfähig. Stattdessen stellen Sie einen "Null" -Wert dar, indem Sie einen Optionstyp umschließen. Auf diese Weise ändern Sie tatsächlich den Rückgabetyp einer Funktion, wenn sie null als zulässigen Wert zurückgeben kann. Sagen wir also, ich wollte einen Benutzer aus der Datenbank herausziehen:

%Vor%

Find user hat den Typ val findUser : string -> user option , daher sagt Ihnen der Rückgabetyp der Funktion, dass er einen Nullwert zurückgeben kann. Um den Code zu verwenden, müssen Sie sowohl die Fälle Some und None behandeln:

%Vor%

Wenn Sie nicht beide Fälle behandeln, wird der Code nicht einmal kompiliert. Das Typsystem garantiert also, dass Sie niemals eine Null-Referenz-Ausnahme erhalten, und garantiert, dass Sie immer mit Nullen umgehen. Und wenn eine Funktion user zurückgibt, ist sie garantiert eine tatsächliche Instanz eines Objekts. Awesomeness.

Jetzt sehen wir das Problem im OP-Beispielcode:

%Vor%

Initialisierte und nicht initialisierte Objekte haben den gleichen Datentyp. Sie können den Unterschied nicht unterscheiden. Gelegentlich kann das Null-Objektmuster nützlich sein, aber der obige Code zeigt, dass der Compiler keine Möglichkeit hat festzustellen, ob Sie Verwenden Sie Ihre Typen korrekt.

    
Juliet 20.09.2009 20:13
quelle
6

Ich verstehe dein Beispiel nicht. Wenn Ihre "= new Class ()" nur ein Platzhalter anstelle von null ist, dann ist es (für meine Augen) offensichtlich ein Fehler. Wenn das nicht der Fall ist, ist der eigentliche Fehler, dass der "..." seinen Inhalt nicht richtig gesetzt hat, was in beiden Fällen genau derselbe ist.

Eine Ausnahme, die Ihnen zeigt, dass Sie vergessen haben, c zu initialisieren, sagt Ihnen, an welchem ​​Punkt es nicht initialisiert wurde, aber nicht wo es initialisiert werden sollte. In ähnlicher Weise teilt Ihnen eine verpasste Schleife (implizit) mit, wo ein Wert ungleich null sein muss, aber nicht, was getan werden sollte oder wo. Ich sehe keinen als etwas einfacher für den Programmierer.

Ich denke nicht, dass der Punkt von "keine Nullen" darin besteht, einfach einen Text zu finden und zu ersetzen und sie alle in leere Instanzen zu verwandeln. Das ist offensichtlich nutzlos. Es geht darum, den Code so zu strukturieren, dass sich die Variablen niemals in einem Zustand befinden, in dem sie auf nutzlose / falsche Werte verweisen, von denen NULL am häufigsten verwendet wird.

    
Ken 17.03.2009 00:17
quelle
2

Ich gebe zu, dass ich nicht wirklich viel über Spec # gelesen habe, aber ich hatte verstanden, dass das NonNullable im Wesentlichen ein Attribut ist, das Sie auf einen Parameter setzen, nicht unbedingt auf eine Variablendeklaration; Verwandle dein Beispiel in etwas wie:

%Vor%

Mit Spec # markieren Sie doSomething, um zu sagen "der Parameter c kann nicht null sein". Das scheint mir ein gutes Feature zu sein, da es bedeutet, dass ich die erste Zeile der DoSomething () -Methode nicht brauche (was eine leicht zu verges- sene Zeile ist und für den Kontext von DoSomething () völlig sinnlos ist) / p>     

Chris Shaffer 13.03.2009 03:37
quelle
2

Die Idee von Nicht-Null-Typen besteht darin, dass der Compiler und nicht Ihr Client Fehler findet. Angenommen, Sie fügen zwei Typenbezeichner @nullable (möglicherweise null) und @nornull (niemals null) zu Ihrer Sprache hinzu (ich verwende die Java-Annotationssyntax).

Wenn Sie eine Funktion definieren, kommentieren Sie ihre Argumente. Zum Beispiel kompiliert der folgende Code

%Vor%

Auch wenn foo am Eintrag null sein kann, garantiert der Kontrollfluss, dass foo beim Aufruf von foo.size () nichtnull ist.

Aber wenn Sie die Überprüfung auf Null entfernen, erhalten Sie einen Fehler bei der Kompilierung.

Das Folgende wird auch kompilieren, weil foo am Eintrag nicht null ist:

%Vor%

Sie können g jedoch nicht mit einem Nullwert-Zeiger aufrufen:

%Vor%

Der Compiler führt eine Flussanalyse für jede Funktion durch, sodass er erkennen kann, wann @nullable zu @nonnull wird (z. B. innerhalb einer if-Anweisung, die auf Null prüft). Es akzeptiert auch eine @nonnull-Veriable-Definition, sofern sie sofort initialisiert wird.

%Vor%

Es gibt viel mehr zu diesem Thema in meinem Blog .

    
Bartosz Milewski 13.04.2009 19:56
quelle
0

Wie ich sehe, gibt es zwei Bereiche, in denen null verwendet wird.

Der erste ist das Fehlen eines Wertes. Zum Beispiel kann ein Boolescher Wert wahr oder falsch sein, oder der Benutzer hat noch keine Einstellung gewählt, daher null. Dies ist nützlich und eine gute Sache, aber wurde vielleicht ursprünglich falsch implementiert und es gibt jetzt einen Versuch, diese Verwendung zu formalisieren. (Sollte es einen zweiten booleschen Wert geben, um den gesetzten / nicht gesetzten Zustand zu halten, oder null als Teil einer Logik mit drei Zuständen?)

Die Sekunde ist in der Nullzeigerrichtung. Dies ist häufiger als eine Programmfehlersituation, d. eine Ausnahme. Es ist kein beabsichtigter Zustand, es liegt ein Programmfehler vor. Dies sollte unter dem Schutz formaler Ausnahmen stehen, wie sie in modernen Sprachen implementiert sind. Das heißt, eine NullException wird über einen try / catch-Block abgefangen.

Also, an welchen interessiert Sie das?

    
Conor OG 17.03.2009 00:22
quelle
0

Ich arbeite gerade an diesem Thema in C #. .NET hat Nullable für Werttypen, aber das inverse Feature existiert nicht für Referenztypen.

Ich habe NotNullable für Referenztypen erstellt und das Problem von ifs (es wird nicht mehr nach Null gesucht) in die Datentypdomäne verschoben. Dies bewirkt, dass die Anwendung Ausnahmen in der Laufzeit und nicht in der Kompilierzeit auslöst.

    
bloparod 20.09.2009 19:35
quelle
0

Nicht nullbare Typen sind für mich sinnvoller, wenn es sich um Domänenobjekte handelt. Wenn Sie Datenbanktabellen Objekten zuordnen und nicht nullfähige Spalten haben. Angenommen, Sie haben eine Tabelle mit dem Namen "Benutzer", die Spalte "userid varchar (20)" ist nicht nulable;

Das wäre so praktisch, eine User-Klasse mit einem UserId-String-Feld zu haben, das keine Nullwerte hat. Sie können einige Fehler zur Kompilierzeit reduzieren.

    
kaptan 21.01.2011 19:19
quelle
-2

Ich mag die Verwendung von NULL. Es ist eine Weile her, seit ich in C ++ gearbeitet habe, aber es machte es sehr einfach, meine Probleme bezüglich Rückgabewerten und Referenzen zu finden und zu beheben.

    
Heather Kordinak 13.03.2009 03:14
quelle