2017-02-09 4 views
0

Ich versuche zu entscheiden, ob ich in meinem Code Ausnahmen, Behauptungen oder Grenzkontrollen verwenden soll.Validieren von Eingabeparametern

Das Programm enthält viele Berechnungen, die von Benutzereingaben abhängig sind. Das Programm läuft auf einem eingebetteten System.

Der folgende Code ist ein typisches Beispiel. Der Parameter weight_percent_salt sollte offensichtlich nicht negativ sein und es sollte nicht mehr als 100.

float Conductivity(const float weight_percent_salt) 
{ 

    float sigma_20C = 0.0; 

    if(weight_percent_salt > 16.2) 
    { 
     sigma_20C = 19.4; 
    } 
    else 
    { 
     sigma_20C = 2.0487 * weight_percent_salt - 0.2352 * pow(weight_percent_salt,2) + 0.0187 * pow(weight_percent_salt,3); 
    } 

    return sigma_20C; 

}

In diesem speziellen Fall sein ich die Benutzereingabe zwischen 0 einschränken sein - 100% und lassen Sie den Code wie es ist, aber andere Funktionen sind nicht direkt abhängig von Benutzereingaben, sondern das Ergebnis anderer Berechnungen.

Was ist der beste Weg, um fehlerhafte Eingangsparameter in diesen Arten von Funktionen zu behandeln?

Antwort

0

Ausnahmen von den Benutzern Ihrer Klasse nicht Kraft tun, anstatt erlauben sie so tun, wenn sie wollen.

  • Geben Sie eine validWeightValue(x)-Funktion, die ein gültiger Wert für weight_percent_salttrue wenn x ist zurück.

  • Machen Sie Conductivity davon aus, dass weight_percent_salt als Teil seines Vertrags gültig ist.

bool isValidWeightPercentSalt(const float x) noexcept 
{ 
    return x >= 0.f && x <= 100.f; 
} 

float Conductivity(const float weight_percent_salt) 
{ 
    assert(isValidWeightPercentSalt(weight_percent_salt)); 
    // ... 
} 

Der Benutzer jetzt isValidWeightPercentSalt auf seiner Seite Eingabe zu bestätigen und eine Ausnahme auslösen kann. Der Benutzer weiß, dass Conductivity sein Argument annimmt, um das isValidWeightPercentSalt Prädikat zu erfüllen.

float calculateConductivityViaUserInput() 
{ 
    float percent; 
    std::cin >> percent; 

    if(!isValidWeightPercentSalt(percent)) 
    { 
     throw InvalidPercentUserInput{percent}; 
    } 

    return Conductivity(percent); 
} 

Bitte beachte, dass ich bin kein Fan von Ausnahmen - wenn Ihr Design für es erlaubt, gibt eine monadischen Fehlerbehandlung Klassen wie std::optional, std::variant oder boost::expected stattdessen eine Ausnahme zu werfen. Alternativ können Sie die enum classRückkehrcodes verwenden, wenn Sie keinen zusätzlichen Status haben, der mit einer Fehlerbedingung verknüpft ist.

+0

Dies sieht aus wie eine nette Art, es zu tun. In meinem Fall wird die Benutzereingabe über eine serielle Schnittstelle mit Modbus RTU erfolgen, daher würde ich einfach einen Fehlercode zurückgeben, anstatt eine Ausnahme auszulösen, wenn die Eingabedaten außerhalb der angegebenen Werte liegen. Danke für deine Antwort! –

+0

@ Q-Bertsuit: Ja, auf jeden Fall Ausnahmen vermeiden, wenn Sie damit durchkommen können. 'std :: optional ', Fehlercodes und ähnliche Lösungen sind meiner Meinung nach robuster, da sie das Typsystem nutzen und den Benutzer zwingen, mit ihnen umzugehen. –

+0

Schön, ich werde std :: optional betrachten, obwohl der Compiler für dieses spezielle Projekt nicht einmal C++ 11 unterstützt. –

0

Asserts: Diese sind normalerweise nur für Debug-Builds aktiviert und führen zum Absturz. Da sie im Allgemeinen für Release-Builds deaktiviert sind, möchten Sie möglicherweise einen anderen Mechanismus zum Auslösen eines Fehlers verfolgen. Ihre Hauptaufgabe besteht darin, dem Entwickler zu melden, dass der Status des Programms dem Entwickler zufolge nicht möglich ist. Klar für die Benutzereingabe ist alles möglich, und dies ist keine geeignete Wahl.

(Fast) Sonst noch: Ist für Debug-und Release-Builds getan; also wo Benutzereingaben betroffen sind, ist weit vorzuziehen. Genau, was das "alles andere" ist, hängt davon ab, wie genau Sie mit einem Misserfolg umgehen wollen, was weitgehend der Meinung ist.

Das gesagt, Ausnahmen sollten "außergewöhnlich" sein, nicht nur, dass sie nicht oft vorkommen; was wahrscheinlich nicht für das Parsen von Benutzereingaben anwendbar ist.

+0

Das Problem ist, dass es unmöglich ist, jede Kombination von schlechten Benutzereingabedaten vorherzusagen, und ich muss irgendwie berichten, was schief gelaufen ist. Wenn ich keine Ausnahmen verwenden kann (denen ich zustimme, sollte für Dinge wie Speichermangel usw. reserviert sein), sind mir Rückgabecodes übrig, und sie neigen dazu, meinen Code zu überladen. –

+0

Angesichts der Tatsache, dass Vittorio über Ausnahmen hervorgehoben hatte - wollte ich nur behaupten; da sie für die Untersuchung von Benutzereingaben völlig ungeeignet sind. In Bezug auf Würfe sagte niemand, "nicht verwenden" - aber "nicht erzwingen" - dh Sie können eine Version der Klasse, die Rückkehr-Codes hat - und dann eine Wrapper-Klasse, die die Rückkehr Codes und Würfe überprüft. (oder einfach nur eine Flagge in die Klasse setzen und danach werfen) – UKMonkey

Verwandte Themen