Ich habe eine Struktur geschrieben, die Breiten- / Längengradkoordinaten darstellt. Ihre Werte reichen von -180 bis 180 für Längen und 90 bis -90 für Breiten.
Wenn mir ein Benutzer dieser Struktur einen Wert außerhalb dieses Bereichs gibt, habe ich zwei Möglichkeiten:
- Ausnahme auslösen (Argument außerhalb des gültigen Bereichs)
- Konvertieren Sie den Wert in die Einschränkung
Da eine Koordinate von -185 eine Bedeutung hat (sie kann sehr leicht in +175 konvertiert werden, da dies Polarkoordinaten sind), könnte ich sie akzeptieren und konvertieren.
Ist es besser, eine Ausnahme auszulösen, um dem Benutzer mitzuteilen, dass mir sein Code einen Wert gegeben hat, den er nicht haben sollte?
Edit: Auch ich kenne den Unterschied zwischen lat / lng und Koordinaten, aber ich wollte das vereinfachen, um die Diskussion zu vereinfachen - es war nicht die hellste Idee
quelle
Antworten:
Wenn der Kern Ihrer Frage das ist ...
... dann würde meine allgemeine Antwort "ablehnen" lauten, da dies dazu beiträgt, die Aufmerksamkeit auf potenzielle Fehler im Client-Code zu lenken, die dazu führen, dass der ungültige Wert im Programm angezeigt wird und Ihren Konstruktor erreicht. Die Aufmerksamkeit auf Fehler zu lenken, ist in den meisten Systemen eine erwünschte Eigenschaft, zumindest während der Entwicklung (es sei denn, es handelt sich um eine erwünschte Eigenschaft Ihres Systems, die bei Fehlern durcheinandergebracht werden soll).
Die Frage ist, ob Sie diesem Fall tatsächlich gegenüberstehen .
Wenn Ihre Datenstruktur im Allgemeinen Polarkoordinaten modellieren soll, akzeptieren Sie den Wert, da Winkel außerhalb des Bereichs -180 und +180 nicht wirklich ungültig sind. Sie sind vollkommen gültig und haben zufällig immer ein Äquivalent im Bereich von -180 bis +180 (und wenn Sie sie in einen Zielbereich umwandeln möchten, fühlen Sie sich frei - der Client-Code muss sich normalerweise nicht darum kümmern). .
Wenn Ihre Datenstruktur explizit Web Mercator-Koordinaten modelliert (gemäß der Frage in ihrer ursprünglichen Form), befolgen Sie am besten die in der Spezifikation genannten Bestimmungen (die ich nicht kenne, daher werde ich nichts dazu sagen). . Wenn die Spezifikation des Objekts, das Sie modellieren, besagt, dass einige Werte ungültig sind, lehnen Sie sie ab. Wenn es heißt, dass sie als etwas Sinnvolles interpretiert werden können (und somit tatsächlich gültig sind), akzeptieren Sie sie.
Der Mechanismus, mit dem Sie signalisieren, ob die Werte akzeptiert wurden oder nicht, hängt von den Merkmalen Ihrer Sprache, ihrer allgemeinen Philosophie und Ihren Leistungsanforderungen ab. Sie könnten also eine Ausnahme auslösen (im Konstruktor) oder eine nullfähige Version Ihrer Struktur zurückgeben (über eine statische Methode, die einen privaten Konstruktor aufruft) oder einen Booleschen Wert zurückgeben und Ihre Struktur als
out
Parameter an den Aufrufer übergeben (erneut über ein statische Methode, die einen privaten Konstruktor aufruft) und so weiter.quelle
Es kommt sehr darauf an. Aber Sie sollten sich entscheiden , etwas zu tun und es zu dokumentieren .
Das einzig absolut Falsche für Ihren Code ist, zu vergessen, dass die Benutzereingabe möglicherweise außerhalb des erwarteten Bereichs liegt, und Code zu schreiben, der versehentlich ein bestimmtes Verhalten aufweist. Denn dann gehen einige Leute falsch davon aus, wie sich Ihr Code verhält, und es kommt zu Fehlern, während andere davon abhängen, wie sich Ihr Code versehentlich verhält (auch wenn dieses Verhalten völlig verrückt ist), und Sie werden mehr Fehler verursachen Wenn Sie das Problem später beheben.
In diesem Fall kann ich Argumente so oder so sehen. Wenn jemand von 175 auf +10 Grad fährt, sollte er bei -175 enden. Wenn Sie immer normalisieren Benutzereingaben und so behandeln 185 als gleichwertig mit -175 dann Client - Code kann nicht die falsche Sache tun , wenn es 10 Grad addiert; es hat immer die richtige wirkung. Wenn Sie 185 als Fehler behandeln, erzwingen Sie jeden Fall, in dem der Client-Code relative Grade hinzufügt, um sie in die Normalisierungslogik einzufügen (oder denken Sie zumindest daran, Ihre Normalisierungsprozedur aufzurufen), was tatsächlich dazu führtBugs (obwohl es hoffentlich leicht ist, solche zu finden, die schnell zerdrückt werden). Wenn jedoch eine Längengradzahl vom Benutzer eingegeben, wörtlich im Programm geschrieben oder durch eine Prozedur berechnet wird, die immer auf [-180, 180) eingestellt ist, weist ein Wert außerhalb dieses Bereichs mit hoher Wahrscheinlichkeit auf einen Fehler hin "das konvertieren könnte probleme verbergen.
Mein Ideal wäre in diesem Fall wahrscheinlich, einen Typ zu definieren, der die richtige Domäne darstellt. Verwenden Sie einen abstrakten Typ (lassen Sie den Client-Code nicht einfach auf die darin enthaltenen unformatierten Zahlen zugreifen) und stellen Sie sowohl eine normalisierende als auch eine validierende Factory bereit (damit der Client den Kompromiss eingehen kann). Unabhängig davon, welcher Wert für diesen Typ festgelegt wurde, sollte 185 in Ihrer öffentlichen API nicht von -175 zu unterscheiden sein (unabhängig davon, ob sie bei der Erstellung konvertiert wurden oder ob Sie Gleichheit, Zugriffsmethoden und andere Operationen bereitstellen, die den Unterschied irgendwie ignorieren). .
quelle
Wenn es Ihnen nicht wirklich wichtig ist, eine Lösung zu wählen, können Sie den Benutzer einfach entscheiden lassen.
Wenn Ihre Struktur ein schreibgeschütztes Wertobjekt ist und von einer Methode / einem Konstruktor erstellt wurde, können Sie basierend auf den Optionen, die der Benutzer hat, zwei Überladungen bereitstellen:
Lassen Sie den Benutzer auch niemals eine ungültige Struktur zu, um sie an Ihre anderen Methoden weiterzugeben, und korrigieren Sie sie bei der Erstellung.
Bearbeiten: basierend auf den Kommentaren gehe ich davon aus, dass Sie C # verwenden.
quelle
catch
Ihre Ausnahmen ausführen . Wie andere gesagt haben, soll es dem Kunden gestattet sein, sich selbst einzuschränken, wenn er dies wünscht. Sie umgehen nichts wirklich.Es hängt davon ab, ob die Eingabe direkt von einem Benutzer über eine Benutzeroberfläche oder vom System stammt.
Eingabe über eine Benutzeroberfläche
Es ist eine Frage der Benutzererfahrung, wie mit ungültigen Eingaben umgegangen wird. Ich weiß nichts über Ihren speziellen Fall, aber im Allgemeinen gibt es ein paar Möglichkeiten:
Die Auswahl hängt von den Erwartungen Ihrer Benutzer ab und davon, wie kritisch die Daten sind. Zum Beispiel korrigiert Google die Rechtschreibung in Abfragen automatisch, dies ist jedoch ein geringes Risiko, da eine nicht hilfreiche Änderung kein Problem darstellt und leicht zu beheben ist (und selbst dann wird auf der Ergebnisseite klargestellt, dass die Abfrage geändert wurde). Wenn Sie hingegen Koordinaten für eine Nuklearrakete eingeben, möchten Sie möglicherweise eine strengere Eingabevalidierung und keine stillschweigenden Korrekturen ungültiger Daten. Es gibt also keine allgemeingültige Antwort.
Am wichtigsten ist, dass Sie überlegen, ob die Korrektur von Eingaben überhaupt einen Nutzen für den Benutzer hat. Warum sollte ein Benutzer ungültige Daten eingeben? Es ist leicht zu erkennen, wie jemand einen Rechtschreibfehler machen könnte, aber warum sollte jemand einen Längengrad von -185 eingeben? Wenn der Benutzer wirklich +175 gemeint hätte, hätte er wahrscheinlich +175 eingegeben. Ich denke, es ist höchstwahrscheinlich, dass ein ungültiger Längengrad einfach ein Tippfehler ist und der Benutzer -85 oder etwas anderes meinte. In diesem Fall ist eine stille Konvertierung schlecht und nicht hilfreich . Der benutzerfreundlichste Ansatz für Ihre App besteht wahrscheinlich darin, den Benutzer auf den ungültigen Wert aufmerksam zu machen und ihn selbst korrigieren zu lassen.
Eingabe über eine API
Wenn die Eingabe von einem anderen System oder Subsystem stammt, besteht keine Frage. Sie sollten eine Ausnahme auslösen. Sie sollten niemals ungültige Eingaben von einem anderen System stillschweigend konvertieren, da dies zu einer Maskierung von Fehlern an anderer Stelle im System führen kann. Wenn die Eingabe "korrigiert" wird, sollte dies auf der Benutzeroberflächenebene und nicht tiefer im System geschehen.
quelle
Sie sollten eine Ausnahme auslösen.
In dem Beispiel, das Sie angegeben haben, 185 gesendet und in -175 konvertiert, kann es in einigen Fällen nützlich sein, diese Funktionalität bereitzustellen. Aber was ist, wenn der Anrufer 1 Million sendet? Wollen sie das wirklich umsetzen? Es scheint eher ein Fehler zu sein. Wenn Sie also eine Ausnahme für 1.000.000, aber nicht für 185 auslösen müssen, müssen Sie eine Entscheidung über einen beliebigen Schwellenwert für das Auslösen einer Ausnahme treffen. Dieser Schwellenwert wird Sie manchmal stören, wenn eine anrufende App Werte um den Schwellenwert sendet.
Es ist besser, die Ausnahme für Werte außerhalb des Bereichs auszulösen.
quelle
Die bequemste Option für einen Entwickler wäre eine Fehlerunterstützung bei der Kompilierung auf der Plattform für Werte außerhalb des Bereichs. In diesem Fall sollte der Bereich ebenso wie der Typ der Parameter Teil der Methodensignatur sein. So wie Ihr API-Benutzer keinen String übergeben kann, wenn für Ihre Methodensignatur eine Ganzzahl definiert ist , hätte der Benutzer keinen Wert übergeben können, ohne zu prüfen, ob der Wert innerhalb des in der Methodensignatur angegebenen Bereichs liegt. Wenn nicht markiert, sollte er einen Fehler zur Kompilierungszeit bekommen und somit könnte ein Laufzeitfehler vermieden werden.
Derzeit unterstützen jedoch nur sehr wenige Compiler / Plattformen diese Art der Überprüfung der Kompilierzeit. Es ist also ein Entwickler-Kopfschmerz. Im Idealfall sollte Ihre Methode jedoch nur eine sinnvolle Ausnahme für nicht unterstützte Werte auslösen und diese klar dokumentieren.
Übrigens, ich liebe das Fehlermodell, das Joe Duffy hier vorgeschlagen hat .
quelle
Standardmäßig sollte eine Ausnahme ausgelöst werden. Sie können auch eine Option zulassen
strict=false
und den Zwang basierend auf der Flagge ausführen, wobei dies natürlichstrict=true
die Standardeinstellung ist. Das ist ziemlich häufig:DateFormat
unterstützt lenient .quelle
strict=false
?Für mich ist es die beste Praxis, Benutzereingaben niemals zu ändern. Der Ansatz, den ich normalerweise verfolge, besteht darin, die Validierung von der Ausführung zu trennen.
quelle