Parameter zur Steuerung, ob eine Ausnahme ausgelöst oder Null zurückgegeben werden soll - bewährte Methode?

24

Oft stoße ich auf Methoden / Funktionen, die einen zusätzlichen booleschen Parameter haben, der steuert, ob bei einem Fehler eine Ausnahme ausgelöst oder Null zurückgegeben wird.

Es gibt bereits Diskussionen darüber, welche davon in welchem ​​Fall die bessere Wahl ist, also wollen wir uns hier nicht darauf konzentrieren. Siehe z. B. magischen Wert zurückgeben, Ausnahme auslösen oder falsch zurückgeben, wenn ein Fehler auftritt.

Nehmen wir stattdessen an, dass es einen guten Grund gibt, warum wir beide Wege unterstützen wollen.

Persönlich denke ich, dass eine solche Methode eher zweigeteilt werden sollte: Eine, die bei einem Fehler eine Ausnahme auslöst, die andere, die bei einem Fehler null zurückgibt.

Also, was ist besser?

A: Eine Methode mit $exception_on_failureParameter.

/**
 * @param int $id
 * @param bool $exception_on_failure
 *
 * @return Item|null
 *   The item, or null if not found and $exception_on_failure is false.
 * @throws NoSuchItemException
 *   Thrown if item not found, and $exception_on_failure is true.
 */
function loadItem(int $id, bool $exception_on_failure): ?Item;

B: Zwei verschiedene Methoden.

/**
 * @param int $id
 *
 * @return Item|null
 *   The item, or null if not found.
 */
function loadItemOrNull(int $id): ?Item;

/**
 * @param int $id
 *
 * @return Item
 *   The item, if found (exception otherwise).
 *
 * @throws NoSuchItemException
 *   Thrown if item not found.
 */
function loadItem(int $id): Item;

EDIT: C: Noch etwas?

Viele Leute haben andere Optionen vorgeschlagen oder behaupten, dass sowohl A als auch B fehlerhaft sind. Solche Vorschläge oder Meinungen sind willkommen, relevant und nützlich. Eine vollständige Antwort kann solche zusätzlichen Informationen enthalten, befasst sich aber auch mit der Hauptfrage, ob ein Parameter zum Ändern der Signatur / des Verhaltens eine gute Idee ist.

Anmerkungen

Für den Fall, dass sich jemand wundert: Die Beispiele sind in PHP. Aber ich denke, die Frage gilt für alle Sprachen, solange sie PHP oder Java etwas ähneln.

donquixote
quelle
5
Während ich in PHP arbeiten muss und ziemlich kompetent bin, ist es einfach eine schlechte Sprache, und die Standardbibliothek ist allgegenwärtig. Lesen Sie eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design als Referenz. So ist es nicht wirklich überraschend, dass einige PHP-Entwickler schlechte Gewohnheiten annehmen. Aber ich habe diesen besonderen Designgeruch noch nicht gesehen.
Polygnome
In den gegebenen Antworten fehlt mir ein wesentlicher Punkt: Wann würden Sie den einen oder anderen verwenden? Sie würden die Ausnahmemethode verwenden, wenn ein nicht gefundenes Element unerwartet ist und als Fehler angesehen wird (Zeit bis zur Panik). Sie würden die Try ... -Methode verwenden, wenn ein fehlendes Element nicht unwahrscheinlich und mit Sicherheit kein Fehler ist, sondern nur eine Möglichkeit, die Sie in Ihre normale Ablaufsteuerung einbeziehen.
Martin Maat
1
@Polygnome Sie haben Recht, Standard-Bibliotheksfunktionen sind weit verbreitet, und es gibt eine Menge schlechten Codes, und es gibt das Problem, dass nur ein Prozess pro Anforderung ausgeführt wird. Aber es wird mit jeder Version besser. Das Typ- und Objektmodell erledigt alle oder die meisten Dinge, die man von ihm erwarten kann. Ich möchte Generics, Co- und Contravariance, Callback-Typen, die eine Signatur spezifizieren, etc. sehen. Vieles davon wird diskutiert oder ist auf dem Weg, implementiert zu werden. Ich denke, die allgemeine Richtung ist gut, auch wenn die Standard-Macken der Bibliothek nicht so leicht verschwinden werden.
donquixote
4
Ein Vorschlag: Überlegen Sie sich stattdessen loadItemOrNull(id), ob dies loadItemOr(id, defaultItem)für Sie sinnvoll ist. Wenn item ein String oder eine Zahl ist, ist dies häufig der Fall.
user949300

Antworten:

35

Sie haben Recht: Zwei Methoden sind aus mehreren Gründen viel besser:

  1. In Java enthält die Signatur der Methode, die möglicherweise eine Ausnahme auslöst, diese Ausnahme. die andere Methode wird nicht. Es wird besonders deutlich, was von dem einen und anderen zu erwarten ist.

  2. In Sprachen wie C #, in denen die Signatur der Methode nichts über die Ausnahmen aussagt, sollten die öffentlichen Methoden weiterhin dokumentiert sein, und diese Dokumentation enthält die Ausnahmen. Eine einzige Methode zu dokumentieren, wäre nicht einfach.

    Ihr Beispiel ist perfekt: Die Kommentare im zweiten Teil des Codes sehen viel klarer aus, und ich würde sogar kurz "Das Element, wenn es gefunden wird (Ausnahme sonst)." Bis zu "Das Element" - das Vorhandensein einer möglichen Ausnahme und der Ihre Beschreibung ist selbsterklärend.

  3. In einem Fall einer einzelnen Methode gibt es wenige Fälle, in denen Sie den Wert des booleschen Parameters zur Laufzeit umschalten möchten, und in diesem Fall müsste der Aufrufer beide Fälle behandeln (eine nullAntwort und die Ausnahme) ), was den Code viel schwieriger macht, als er sein muss. Da die Auswahl nicht zur Laufzeit getroffen wird, sondern beim Schreiben des Codes, sind zwei Methoden sinnvoll.

  4. Einige Frameworks, z. B. .NET Framework, haben Konventionen für diese Situation festgelegt und lösen diese mit zwei Methoden, wie Sie vorgeschlagen haben. Der einzige Unterschied besteht darin, dass sie ein von Ewan in seiner Antwort erklärtes Muster verwenden , also int.Parse(string): inteine Ausnahme auslösen, während int.TryParse(string, out int): booldies nicht der Fall ist. Diese Namenskonvention ist in der .NET-Community sehr stark verbreitet und sollte befolgt werden, wenn der Code der von Ihnen beschriebenen Situation entspricht.

Arseni Mourzenko
quelle
1
Danke, das ist die Antwort, nach der ich gesucht habe! Der Zweck war, eine Diskussion darüber für Drupal CMS, drupal.org/project/drupal/issues/2932772 , zu beginnen , und ich möchte nicht, dass es sich um meine persönlichen Vorlieben handelt, aber ich möchte dies mit Feedback von anderen unterstützen.
donquixote
4
Eigentlich ist es für .NET eine lange Tradition, NICHT zwei Methoden zu verwenden, sondern die richtige Wahl für die richtige Aufgabe zu treffen. Ausnahmen gelten für außergewöhnliche Umstände, um den erwarteten Kontrollfluss nicht zu handhaben. Fehler beim Parsen einer Zeichenfolge in eine Ganzzahl? Kein sehr unerwarteter oder außergewöhnlicher Umstand. int.Parse()wird als eine wirklich schlechte Designentscheidung angesehen, weshalb das .NET-Team die Implementierung vorangetrieben hat TryParse.
Voo
1
Das Bereitstellen von zwei Methoden, anstatt darüber nachzudenken, um welche Art von Anwendungsfall es sich handelt, ist der einfache Ausweg: Denken Sie nicht darüber nach, was Sie tun, sondern übertragen Sie die Verantwortung auf alle Benutzer Ihrer API. Sicher, es funktioniert, aber das ist nicht das Markenzeichen eines guten API-Designs (oder irgendeines Designs in dieser Angelegenheit. Lesen Sie z. B. Joels
Meinung
@ Voo Gültiger Punkt. Wenn Sie zwei Methoden angeben, hat der Anrufer die Wahl. Möglicherweise wird für einige Parameterwerte erwartet, dass ein Element vorhanden ist, während für andere Parameterwerte ein nicht vorhandenes Element als normaler Fall betrachtet wird. Möglicherweise wird die Komponente in einer Anwendung verwendet, in der immer erwartet wird, dass die Elemente vorhanden sind, und in einer anderen Anwendung, in der nicht vorhandene Elemente als normal betrachtet werden. Vielleicht ruft der Anrufer ->itemExists($id)vor dem Anruf an ->loadItem($id). Oder vielleicht ist es nur eine Entscheidung, die andere in der Vergangenheit getroffen haben und die wir für selbstverständlich halten müssen.
donquixote
1
Grund 1b: Für einige Sprachen (Haskell, Swift) muss in der Signatur die Nullfähigkeit vorhanden sein. Insbesondere hat Haskell einen völlig anderen Typ für nullfähige Werte ( data Maybe a = Just a | Nothing).
John Dvorak
9

Eine interessante Variante ist die Swift-Sprache. In Swift deklarieren Sie eine Funktion als "werfen", das heißt, es ist erlaubt, Fehler zu werfen (ähnlich, aber nicht ganz so wie bei Java-Ausnahmen). Der Anrufer kann diese Funktion auf vier Arten aufrufen:

ein. In einer try / catch-Anweisung wird die Ausnahme abgefangen und behandelt.

b. Wenn der Anrufer selbst als auslösend deklariert ist, rufen Sie ihn einfach auf, und jeder ausgelöste Fehler wird zu einem vom Anrufer ausgelösten Fehler.

c. Markieren Sie den Funktionsaufruf, mit dem try!die Meldung "Ich bin sicher, dieser Anruf wird nicht ausgelöst" angezeigt wird. Wenn die aufgerufene Funktion tut werfen, wird die Anwendung zum Absturz zu bringen garantiert.

d. Markieren des Funktionsaufrufs, mit dem try?die Meldung "Ich weiß, dass die Funktion ausgelöst werden kann, aber es ist mir egal, welcher Fehler genau ausgelöst wird" angezeigt wird. Dies ändert den Rückgabewert der Funktion von Typ " T" in Typ " optional<T>" und eine geworfene Ausnahme wird in " return nil" umgewandelt.

(a) und (d) sind die Fälle, nach denen Sie fragen. Was ist, wenn die Funktion nil zurückgeben und Ausnahmen auslösen kann? In diesem Fall wäre der Typ des Rückgabewerts " optional<R>" für einen Typ R, und (d) würde dies in " optional<optional<R>>" ändern, was etwas kryptisch und schwer zu verstehen ist, aber völlig in Ordnung ist. Und eine Swift-Funktion kann zurückkehren optional<Void>, so dass (d) zum Werfen von Funktionen verwendet werden kann, die Void zurückgeben.

gnasher729
quelle
2

Ich mag den bool TryMethodName(out returnValue)Ansatz.

Es gibt Ihnen einen schlüssigen Hinweis darauf, ob die Methode erfolgreich war oder nicht, und die Benennung stimmt überein, wenn die Ausnahmewurfmethode in einen try catch-Block eingeschlossen wird.

Wenn Sie nur null zurückgeben, wissen Sie nicht, ob dies fehlgeschlagen ist oder der Rückgabewert zu Recht null war.

z.B:

//throws exceptions when error occurs
Item LoadItem(int id);

//returns false when error occurs
bool TryLoadItem(int id, out Item item)

Beispielverwendung (out bedeutet, dass die Referenz nicht initialisiert wird)

Item i;
if(TryLoadItem(3, i))
{
    Print(i.Name);
}
else
{
    Print("unable to load item :(");
}
Ewan
quelle
Entschuldigung, du hast mich hier verloren. Wie würde Ihr " bool TryMethodName(out returnValue)Ansatz" im ursprünglichen Beispiel aussehen?
donquixote
bearbeitet, um ein Beispiel hinzuzufügen
Ewan
1
Verwenden Sie also einen By-Reference-Parameter anstelle eines Rückgabewerts, damit Sie den Rückgabewert für den Bool-Erfolg frei haben? Gibt es eine Programmiersprache, die dieses Schlüsselwort "out" unterstützt?
donquixote
2
ja, sorry habe nicht bemerkt, dass 'out' spezifisch für c # ist
Ewan
1
nicht immer nein. Aber was , wenn Punkt 3 ist null? Sie würden nicht wissen, ob ein Fehler aufgetreten wäre oder nicht
Ewan
2

Normalerweise gibt ein boolescher Parameter an, dass eine Funktion in zwei Teile geteilt werden kann. In der Regel sollten Sie sie immer aufteilen, anstatt einen booleschen Wert zu übergeben.

Max
quelle
1
Ich würde dies in der Regel nicht ausnehmen, ohne eine Qualifikation oder Nuance hinzuzufügen. Wenn Sie einen Booleschen Wert als Argument entfernen, werden Sie möglicherweise gezwungen, ein dummes if / else an eine andere Stelle zu schreiben, sodass Sie Daten in Ihrem geschriebenen Code und nicht in Variablen codieren.
Gerard
@Gerard kannst du mir bitte ein Beispiel geben?
Max
@Max Wenn Sie eine boolesche Variable haben b: Anstatt aufzurufen foo(…, b);, müssen Sie if (b) then foo_x(…) else foo_y(…);die anderen Argumente schreiben und wiederholen, oder ((b) ? foo_x : foo_y)(…)wenn die Sprache einen ternären Operator und erstklassige Funktionen / Methoden hat. Und dies wird vielleicht sogar an mehreren Stellen im Programm wiederholt.
Blackjack
@BlackJack na ja ich könnte dir zustimmen. Ich dachte an das Beispiel, if (myGrandmaMadeCookies) eatThem() else makeFood()das ich vielleicht in eine andere Funktion wie diese einwickeln würde checkIfShouldCook(myGrandmaMadeCookies). Ich frage mich, ob die von Ihnen erwähnte Nuance damit zusammenhängt, ob wir einen Booleschen Wert für das Verhalten der Funktion übergeben, wie in der ursprünglichen Frage, oder ob wir Informationen zu unserem Modell übergeben, wie in der Oma Beispiel, das ich gerade gegeben habe.
Max
1
Die in meinem Kommentar erwähnte Nuance bezieht sich auf "Sie sollten immer". Vielleicht umformulieren als "wenn a, b und c zutreffen dann [...]". Die "Regel", die Sie erwähnen, ist ein großartiges Paradigma, aber eine sehr abweichende Variante des Anwendungsfalls.
Gerard
1

Clean Code rät dazu, Argumente mit booleschen Flags zu vermeiden, da ihre Bedeutung an der Aufrufstelle undurchsichtig ist:

loadItem(id, true) // does this throw or not? We need to check the docs ...

Während separate Methoden aussagekräftige Namen verwenden können:

loadItemOrNull(id); // meaning is obvious; no need to refer to docs
Meriton - im Streik
quelle
1

Wenn ich entweder A oder B verwenden müsste, würde ich aus den in der Antwort von Arseni Mourzenkos angegebenen Gründen B verwenden, zwei getrennte Methoden .

Es gibt aber noch eine andere Methode 1 : In Java heißt es Optional, aber Sie können dasselbe Konzept auf andere Sprachen anwenden, in denen Sie Ihre eigenen Typen definieren können, wenn die Sprache noch keine ähnliche Klasse bereitstellt.

So definieren Sie Ihre Methode:

Optional<Item> loadItem(int id);

In Ihrer Methode kehren Sie entweder zurück, Optional.of(item)wenn Sie den Artikel gefunden haben, oder Sie kehren Optional.empty()zurück, falls Sie dies nicht tun. Du wirfst niemals 2 und kommst niemals zurück null.

Für den Klienten Ihrer Methode ist es etwas Ähnliches null, aber mit dem großen Unterschied, dass er gezwungen ist, über den Fall fehlender Elemente nachzudenken. Der Benutzer kann die Tatsache, dass möglicherweise kein Ergebnis vorliegt, nicht einfach ignorieren. Um den Gegenstand aus dem zu entfernen, ist Optionaleine explizite Aktion erforderlich:

  • loadItem(1).get()wirft einen NoSuchElementExceptionoder gibt den gefundenen Gegenstand zurück.
  • Es ist auch loadItem(1).orElseThrow(() -> new MyException("No item 1"))eine benutzerdefinierte Ausnahme zu verwenden, wenn die zurückgegebene Optionalleer ist.
  • loadItem(1).orElse(defaultItem)Gibt entweder das gefundene Element oder das übergebene zurück defaultItem(was auch sein kann null), ohne eine Ausnahme auszulösen.
  • loadItem(1).map(Item::getName)würde wieder einen Optionalmit dem Itemnamen zurückgeben, falls vorhanden.
  • Weitere Methoden finden Sie im JavadocOptional .

Der Vorteil ist, dass es nun am Client-Code liegt, was passieren soll, wenn es keinen Artikel gibt und Sie dennoch nur eine einzige Methode bereitstellen müssen .


1 Ich denke, es ist so etwas wie die Antwort vontry? in gnasher729s, aber es ist mir nicht ganz klar, da ich Swift nicht kenne und es ein Sprachmerkmal zu sein scheint, so dass es spezifisch für Swift ist.

2 Sie können Ausnahmen aus anderen Gründen auslösen, z. B. wenn Sie nicht wissen, ob ein Element vorhanden ist oder nicht, weil Sie Probleme mit der Kommunikation mit der Datenbank hatten.

siegi
quelle
0

Ein weiterer Punkt, der mit der Verwendung von zwei Methoden übereinstimmt, ist, dass dies sehr einfach zu implementieren ist. Ich schreibe mein Beispiel in C #, da ich die PHP-Syntax nicht kenne.

public Widget GetWidgetOrNull(int id) {
    // All the lines to get your item, returning null if not found
}

public Widget GetWidget(int id) {
    var widget = GetWidgetOrNull(id);

    if (widget == null) {
        throw new WidgetNotFoundException();
    }

    return widget;
}
Krillgar
quelle
0

Ich bevorzuge zwei Methoden, auf diese Weise werden Sie mir nicht nur sagen, dass Sie einen Wert zurückgeben, sondern welchen Wert genau.

public int GetValue(); // If you can't get the value, you'll throw me an exception
public int GetValueOrDefault(); // If you can't get the value, you'll return me 0, since it's the default for ints

Das TryDoSomething () ist auch kein schlechtes Muster.

public bool TryParse(string value, out int parsedValue); // If you return me false, I won't bother checking parsedValue.

Ich bin eher daran gewöhnt, Ersteres in Datenbankinteraktionen zu sehen, während Letzteres eher in Syntaxanalyse verwendet wird.

Wie andere bereits gesagt haben, sind Flag-Parameter normalerweise ein Code-Geruch (Code-Gerüche bedeuten nicht, dass Sie etwas falsch machen, nur, dass es wahrscheinlich ist, dass Sie es falsch machen). Obwohl Sie es genau benennen, gibt es manchmal Nuancen, die es schwierig machen, diese Flagge zu verwenden, und Sie sehen sich am Ende den Methodenkörper an.

Ein Bravo Dev
quelle
-1

Während andere Leute etwas anderes vorschlagen, würde ich vorschlagen, dass eine Methode mit einem Parameter, der angibt, wie Fehler behandelt werden sollen, besser ist als die Verwendung separater Methoden für die beiden Verwendungsszenarien. Während es wünschenswert sein kann, auch unterschiedliche Einstiegspunkte für die Verwendungen "Fehlerauslösungen" im Vergleich zu "Fehler gibt Fehleranzeige zurück" zu haben, wird durch die Verwendung eines Einstiegspunkts, der beide Verwendungsmuster bedienen kann, eine Codeduplizierung in Wrapper-Methoden vermieden. Als einfaches Beispiel, wenn man Funktionen hat:

Thing getThing(string x);
Thing tryGetThing (string x);

und man möchte Funktionen, die sich ebenfalls verhalten, aber mit x in eckige Klammern eingeschlossen, müssten zwei Sätze von Wrapper-Funktionen geschrieben werden:

Thing getThingWithBrackets(string x)
{
  getThing("["+x+"]");
}
Thing tryGetThingWithBrackets (string x);
{
  return tryGetThing("["+x+"]");
}

Wenn es ein Argument für den Umgang mit Fehlern gibt, wird nur ein Wrapper benötigt:

Thing getThingWithBrackets(string x, bool returnNullIfFailure)
{
  return getThing("["+x+"]", returnNullIfFailure);
}

Wenn der Wrapper einfach genug ist, ist die Codeduplizierung möglicherweise nicht so schlecht, aber wenn sie jemals geändert werden muss, müssen zum Duplizieren des Codes Änderungen vorgenommen werden. Selbst wenn man sich dafür entscheidet, Einstiegspunkte hinzuzufügen, die das zusätzliche Argument nicht verwenden:

Thing getThingWithBrackets(string x)
{
   return getThingWithBrackets(x, false);
}
Thing tryGetThingWithBrackets(string x)
{
   return tryGetThingWithBrackets(x, true);
}

Man kann die gesamte "Geschäftslogik" in einer Methode aufbewahren - der, die ein Argument akzeptiert, das angibt, was im Fehlerfall zu tun ist.

Superkatze
quelle
Sie haben Recht: Bei Dekoratoren und Wrappern und sogar bei der regulären Implementierung kann es bei Verwendung von zwei Methoden zu Codeduplikationen kommen.
donquixote
Stellen Sie sicher, dass die Versionen mit und ohne Ausnahme in separate Pakete, und machen Sie die Wrapper generisch?
Will Crawford
-1

Ich denke, alle Antworten, die erklären, dass Sie kein Flag haben sollten, das steuert, ob eine Ausnahme ausgelöst wird oder nicht, sind gut. Ihr Rat wäre mein Rat an alle, die das Bedürfnis haben, diese Frage zu stellen.

Ich wollte jedoch darauf hinweisen, dass es eine sinnvolle Ausnahme von dieser Regel gibt. Sobald Sie fortgeschritten genug sind, um mit der Entwicklung von APIs zu beginnen, die von Hunderten anderer Personen verwendet werden, kann es vorkommen, dass Sie ein solches Flag bereitstellen möchten. Wenn Sie eine API schreiben, schreiben Sie nicht nur an die Puristen. Sie schreiben an echte Kunden, die echte Wünsche haben. Teil Ihrer Aufgabe ist es, sie mit Ihrer API zufrieden zu stellen. Das wird eher zu einem sozialen Problem als zu einem Programmierproblem, und manchmal schreiben soziale Probleme Lösungen vor, die als eigene Programmierlösungen nicht ideal wären.

Möglicherweise haben Sie zwei unterschiedliche Benutzer Ihrer API, von denen einer Ausnahmen wünscht und einer dies nicht tut. Ein Beispiel aus der Praxis, in dem dies auftreten könnte, ist eine Bibliothek, die sowohl in der Entwicklung als auch auf einem eingebetteten System verwendet wird. In Entwicklungsumgebungen möchten Benutzer wahrscheinlich überall Ausnahmen haben. Ausnahmen sind sehr beliebt für den Umgang mit unerwarteten Situationen. In vielen eingebetteten Situationen sind sie jedoch verboten, da sie zu schwierig sind, um Einschränkungen in Echtzeit zu analysieren. Wenn Sie sich nicht nur um die durchschnittliche Zeit für die Ausführung Ihrer Funktion kümmern , sondern auch um die Zeit, die für einen einzelnen Spaß benötigt wird, ist die Idee, den Stapel an einem beliebigen Ort abzuwickeln, sehr unerwünscht.

Ein echtes Beispiel für mich: eine Mathematikbibliothek. Wenn Ihre Mathematikbibliothek eine VectorKlasse hat, die es unterstützt, einen Einheitsvektor in dieselbe Richtung zu erhalten, müssen Sie in der Lage sein, durch die Größe zu dividieren. Wenn die Größe 0 ist, haben Sie eine Division durch Null-Situation. In der Entwicklung möchten Sie diese fangen . Sie wollen wirklich keine überraschende Division durch Nullen. Das Auslösen einer Ausnahme ist hierfür eine sehr beliebte Lösung. Es passiert fast nie (es ist wirklich außergewöhnliches Verhalten), aber wenn es passiert, möchten Sie es wissen.

Auf der eingebetteten Plattform möchten Sie diese Ausnahmen nicht. Es wäre sinnvoller, eine Überprüfung durchzuführen if (this->mag() == 0) return Vector(0, 0, 0);. Tatsächlich sehe ich das in echtem Code.

Denken Sie jetzt aus der Perspektive eines Unternehmens. Sie können versuchen, zwei verschiedene Methoden zur Verwendung einer API beizubringen:

// Development version - exceptions        // Embeded version - return 0s
Vector right = forward.cross(up);          Vector right = forward.cross(up);
Vector localUp = right.cross(forward);     Vector localUp = right.cross(forward);
Vector forwardHat = forward.unit();        Vector forwardHat = forward.tryUnit();
Vector rightHat = right.unit();            Vector rightHat = right.tryUnit();
Vector localUpHat = localUp.unit()         Vector localUpHat = localUp.tryUnit();

Dies entspricht den Meinungen der meisten Antworten, ist jedoch aus Unternehmenssicht unerwünscht. Embedded - Entwickler haben ein lernen Stil der Codierung und Entwicklung Entwickler müssen eine andere lernen. Dies kann ziemlich lästig sein und zwingt die Menschen zu einer Denkweise. Möglicherweise noch schlimmer: Wie können Sie beweisen, dass die eingebettete Version keinen Code zum Auslösen von Ausnahmen enthält? Die Throwing-Version kann sich leicht einfügen und irgendwo in Ihrem Code verstecken, bis ein teures Failure Review Board sie findet.

Wenn Sie andererseits ein Flag haben, das die Ausnahmebehandlung ein- oder ausschaltet, können beide Gruppen den exakt gleichen Codierungsstil erlernen. In vielen Fällen können Sie sogar den Code einer Gruppe in den Projekten der anderen Gruppe verwenden. unit()Wenn Sie bei Verwendung dieses Codes tatsächlich daran interessiert sind, was in einem Fall der Division durch 0 geschieht, sollten Sie den Test selbst geschrieben haben. Wenn Sie es also auf ein eingebettetes System verschieben, auf dem Sie nur schlechte Ergebnisse erzielen, ist dieses Verhalten "normal". Aus geschäftlicher Sicht trainiere ich meine Codierer jetzt einmal und sie verwenden in allen Bereichen meines Geschäfts dieselben APIs und Stile.

In den allermeisten Fällen möchten Sie den Ratschlägen anderer folgen: Verwenden Sie tryGetUnit()für Funktionen, die keine Ausnahmen auslösen, ähnliche oder ähnliche Redewendungen und geben Sie stattdessen einen Sentinel-Wert wie null zurück. Wenn Sie der Meinung sind, dass Benutzer sowohl Ausnahmebehandlungs- als auch Nicht-Ausnahmebehandlungscode in einem einzigen Programm nebeneinander verwenden möchten, bleiben Sie bei der tryGetUnit()Notation. Es gibt jedoch einen Eckfall, in dem die Realität des Geschäfts die Verwendung einer Flagge verbessern kann. Wenn Sie sich in diesem Eckfall befinden, haben Sie keine Angst, die "Regeln" auf der Strecke zu lassen. Dafür gibt es Regeln!

Cort Ammon - Setzen Sie Monica wieder ein
quelle