Soll ich Debug.Assert heute noch verwenden?

23

Kürzlich bin ich auf einen neu geschriebenen Code gestoßen, der mit viel Debug.Assert (C #) durchsetzt war.

Sollten wir dies trotz der Verwendung von TDD, BDD und Unit Testing im Allgemeinen immer noch in großem Umfang nutzen?

Dominik Fretz
quelle
9
Ich kann nicht sehen, wie einer den anderen ausschließt.
SuperM
2
@superM Ich habe auf jeden Fall gesehen, dass faule Entwickler Tests als Zusicherungen hinzugefügt haben, da sie ihren Code so geschrieben hatten, dass es schwierig war, Abhängigkeiten auszutricksen. Ich würde das natürlich nicht empfehlen
jk.

Antworten:

23

Ich sehe keinen Grund, warum Sie Assert nicht verwenden sollten. Auf diese Weise haben Sie bereits erkannt, dass Schutzmaßnahmen wie Vorbedingungen und Invarianten erforderlich sind, und sind auf dem Weg zu Design by Contract . Behauptung ist nur ein Weg, um dies zu erreichen ...

// Precondition using Asert
void SomeMethod(Foo someParameter)
{
    Debug.Assert(someParameter != null)
}

// Precondition using If-Then-Throw
void SomeMethod(Foo someParameter)
{
    if (someParameter == null)
        throw new ArgumentNullException("someParameter");
}

// Precondition using Code Contracts
void SomeMethod(Foo someParameter)
{
    Contract.Requires(someParameter != null);
}

// Precondition using some custom library
void SomeMethod(Foo someParameter)
{
    Require.ArgumentNotNull(() => someParameter);
}

Alle sind Wege, um dasselbe zu erreichen: Robustheit im Code. Es kommt nur darauf an, eine Option auszuwählen, für die Assert eine gültige Wahl ist.

Beachten Sie, dass ich Unit-Tests bisher überhaupt nicht erwähnt habe, da sie etwas ganz anderes bewirken. Ein Komponententest beweist die Robustheit des Codes formell, indem er eine Wache ausübt:

[Test]
void SomeMethod_WhenGivenNull_ThrowsArgumentNullException()
{
    delegate call = () => someObject.SomeMethod(null);

    Assert.That(call).Throws<ArgumentNullException>();
}

Dies ist eine ganz andere Art von Behauptung ...

** Beachten Sie, dass es in einigen Frameworks sehr schwierig ist, einen Komponententest für einen Assertionsfehler durchzuführen, da ein Assertionsfehler die gesamte Laufzeit beeinträchtigen kann. Daher ist eine der anderen Optionen möglicherweise vorzuziehen ... *

MattDavey
quelle
10

Ich betrachte Asserts und Unit-Tests als zwei verschiedene Tools in meiner Toolbox. Einige Dinge sind besser für das eine und andere besser für das andere geeignet.

Als Beispiel verwende ich heutzutage meistens Asserts, um Parameter für nicht öffentliche Methoden zu validieren.

vaughandroid
quelle
5

Ich betrachte Debug.Assert heutzutage als vorzeitige Optimierung. Wenn Sie die Leistung nicht wirklich benötigen, kann das Unterdrücken der Zusicherung im Freigabemodus Fehler länger verbergen.

Als MattDavey Punkte aus Code Verträgen können statt dynamischer Überprüfung Überprüfung, ein überlegenes und bietet statisch sein und zur Verfügung , wenn nicht ich lieber Trace.Assert oder ein plain oldif(x) throw SomeException;

jk.
quelle
4
Es ist erwähnenswert, dass das Generieren von Code mit Visual Studio im Freigabemodus dazu führt, dass alle Aufrufe von Methoden der DebugKlasse von der Kompilierung übersprungen werden. Das Unterdrücken von Aufrufen zur AssertLeistungsverbesserung ist also nicht nur eine vorzeitige Optimierung, sondern ein Unsinn.
Konamiman
@Konamiman das ist der Punkt, ich möchte fast immer, dass es im Release-Modus auf die gleiche Weise fehlschlägt:. Debug.Assert nützt mir in 97% der Fälle nichts
jk.
Was sind das dann 3%, @jk? Nur Legacy-Code oder eine andere Instanz?
DougM
@DougM leistungskritischer Code, der auf das Knuth-Zitat verweist. Ich würde auch hinzufügen, dass ich denke, dass der Heartbleed-Bug zeigt, dass meine Ansicht die richtige ist, es sei denn, Sie haben keine andere Wahl, lassen Sie die Vorbedingungen in Ihrem Release-Code nicht überprüfen
jk.