Dovrei ancora usare Debug.Assert oggi?


23

Di recente mi sono imbattuto in alcuni nuovi codici scritti intervallati da molti Debug.Assert (C #).

Dovremmo comunque utilizzarlo ampiamente nonostante l'uso di TDD, BDD e Unit Test in generale?


9
Non riesco a vedere come uno esclude l'altro.
superM

2
@superM Ho sicuramente visto sviluppatori pigri aggiungere test come asserzioni in precedenza poiché avevano scritto il loro codice in modo che fosse difficile deridere le dipendenze. inutile dire che non lo consiglierei
jk.

Risposte:


23

Non vedo alcun motivo per cui non dovresti usare Assert. In questo modo hai già riconosciuto la necessità di guardie, come precondizioni e invarianti, e stai facendo un passo verso la progettazione per contratto . Assert è solo un modo per raggiungere questo ...

// 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);
}

Tutti sono modi per ottenere la stessa cosa: solidità nel codice. Dipende solo dalla scelta di un'opzione, di cui Assert è una scelta valida.

Si noti che non ho menzionato affatto test di unità finora, in quanto realizzano qualcosa di molto diverso. Un unit test dimostra formalmente la solidità del codice esercitando una guardia:

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

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

Questo è un tipo completamente diverso di affermazione ...

** Si noti che in alcuni framework è in realtà abbastanza difficile testare l'unità per un errore di asserzione, in quanto un errore di asserzione può ridurre l'intero runtime, quindi una delle altre opzioni potrebbe essere preferita ... *


10

Considero affermazioni e unit test come due strumenti diversi nella mia cassetta degli attrezzi. Alcune cose sono più adatte all'una e altre sono più adatte all'altra.

Ad esempio, in questi giorni utilizzo principalmente assert per validare parametri per metodi non pubblici.


5

Oggi considero Debug.Assert come ottimizzazione prematura. A meno che tu non abbia davvero bisogno delle prestazioni, la soppressione di Assert in modalità di rilascio può nascondere i bug più a lungo.

Come sottolinea MattDavey, i contratti di codice possono essere superiori, fornendo controlli statici invece di controlli dinamici, e se non disponibili preferirei Trace.Assert o un semplice vecchioif(x) throw SomeException;


4
Vale la pena ricordare che la generazione di codice con Visual Studio in modalità di rilascio farà sì che tutte le chiamate ai metodi della Debugclasse vengano saltate dalla compilazione ... quindi sopprimere le chiamate a Assertsemplicemente per prestazioni non è solo un'ottimizzazione prematura, è una semplice assurdità.
Konamiman,

@Konamiman questo è il punto, quasi sempre voglio che fallisca allo stesso modo in modalità di rilascio:. Debug.Assert non mi è utile il 97% delle volte
jk.

Cos'è quel 3% allora, @jk? Solo codice legacy o qualche altra istanza?
DougM,

Codice critico per le prestazioni di @DougM, è un riferimento alla citazione di knuth. Aggiungo anche che penso che il bug heartble dimostri che la mia vista è quella corretta, a meno che tu non abbia altra scelta, non eludere i controlli di condizione nel tuo codice di rilascio
jk.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.