Ich habe gehört, dass es empfohlen wird, Argumente öffentlicher Methoden zu validieren:
- Sollte man nach null suchen, wenn man nicht null erwartet?
- Sollte eine Methode ihre Parameter validieren?
- MSDN - CA1062: Überprüfen Sie die Argumente öffentlicher Methoden (ich habe .NET-Hintergrund, aber die Frage ist nicht C # -spezifisch ).
Motivation ist verständlich. Wenn ein Modul falsch verwendet wird, möchten wir sofort eine Ausnahme auslösen, anstatt ein unvorhersehbares Verhalten.
Was mich stört, ist, dass falsche Argumente nicht der einzige Fehler sind, der bei der Verwendung eines Moduls gemacht werden kann. Hier sind einige Fehlerszenarien, in denen wir eine Überprüfungslogik hinzufügen müssen, wenn wir den Empfehlungen folgen und keine Fehlereskalation wünschen:
- Eingehender Anruf - unerwartete Argumente
- Eingehender Anruf - Modul ist in einem falschen Zustand
- Externer Anruf - unerwartete Ergebnisse zurückgegeben
- Externer Aufruf - unerwartete Nebenwirkungen (doppelter Eintrag in ein aufrufendes Modul, Aufheben anderer Abhängigkeitszustände)
Ich habe versucht, all diese Bedingungen zu berücksichtigen und ein einfaches Modul mit einer Methode zu schreiben (sorry, nicht-C # Jungs):
public sealed class Room
{
private readonly IDoorFactory _doorFactory;
private bool _entered;
private IDoor _door;
public Room(IDoorFactory doorFactory)
{
if (doorFactory == null)
throw new ArgumentNullException("doorFactory");
_doorFactory = doorFactory;
}
public void Open()
{
if (_door != null)
throw new InvalidOperationException("Room is already opened");
if (_entered)
throw new InvalidOperationException("Double entry is not allowed");
_entered = true;
_door = _doorFactory.Create();
if (_door == null)
throw new IncompatibleDependencyException("doorFactory");
_door.Open();
_entered = false;
}
}
Jetzt ist es sicher =)
Es ist ziemlich gruselig. Aber stellen Sie sich vor, wie gruselig es in einem realen Modul mit Dutzenden von Methoden, komplexem Zustand und vielen externen Aufrufen sein kann (Hallo, Liebhaber der Abhängigkeitsinjektion!). Beachten Sie, dass Sie, wenn Sie ein Modul aufrufen, dessen Verhalten überschrieben werden kann (nicht versiegelte Klasse in C #), einen externen Anruf tätigen und die Konsequenzen für den Aufrufer nicht vorhersehbar sind.
Zusammenfassend, was ist der richtige Weg und warum? Wenn Sie aus den folgenden Optionen auswählen können, beantworten Sie bitte weitere Fragen.
Überprüfen Sie die gesamte Modulnutzung. Benötigen wir Unit-Tests? Gibt es Beispiele für solchen Code? Sollte die Abhängigkeitsinjektion in der Verwendung eingeschränkt sein (da dies mehr Überprüfungslogik verursacht)? Ist es nicht praktisch, diese Prüfungen auf die Debug-Zeit zu verschieben (nicht in der Version enthalten)?
Überprüfen Sie nur Argumente. Nach meiner Erfahrung ist die Argumentprüfung - insbesondere die Nullprüfung - die am wenigsten wirksame Prüfung, da Argumentfehler selten zu komplexen Fehlern und Fehlereskalationen führen. Meistens erhalten Sie eine NullReferenceException
in der nächsten Zeile. Warum sind Argumentprüfungen so besonders?
Überprüfen Sie nicht die Modulnutzung. Es ist eine ziemlich unpopuläre Meinung, können Sie erklären, warum?