Ho pensato di aggiungere altri quattro casi, in cui Debug.Assert può essere la scelta giusta.
1) Qualcosa che non ho visto menzionato qui è la copertura concettuale aggiuntiva che gli Assert possono fornire durante i test automatizzati . Come semplice esempio:
Quando un chiamante di livello superiore viene modificato da un autore che ritiene di aver ampliato l'ambito del codice per gestire scenari aggiuntivi, idealmente (!) Scriverà unit test per coprire questa nuova condizione. È quindi possibile che il codice completamente integrato funzioni correttamente.
Tuttavia, in realtà è stato introdotto un sottile difetto, ma non rilevato nei risultati del test. In questo caso, la chiamata è diventata non deterministica e sembra solo fornire il risultato atteso. O forse ha prodotto un errore di arrotondamento che è stato inosservato. O ha causato un errore che è stato compensato ugualmente altrove. O concesso non solo l'accesso richiesto ma privilegi aggiuntivi che non dovrebbero essere concessi. Eccetera.
A questo punto, le istruzioni Debug.Assert () contenute nella chiamata insieme al nuovo caso (o limite) guidato dai test unitari possono fornire una preziosa notifica durante il test che le ipotesi dell'autore originale sono state invalidate e il codice non dovrebbe essere rilasciato senza ulteriore revisione. Le asserzioni con unit test sono i partner perfetti.
2) Inoltre, alcuni test sono semplici da scrivere, ma costosi e non necessari alla luce dei presupposti iniziali . Per esempio:
Se è possibile accedere a un oggetto solo da un determinato punto di ingresso protetto, è necessario eseguire una query aggiuntiva su un database dei diritti di rete da ogni metodo oggetto per garantire che il chiamante disponga delle autorizzazioni? Sicuramente no. Forse la soluzione ideale include la memorizzazione nella cache o qualche altra espansione di funzionalità, ma il design non lo richiede. Un Debug.Assert () mostrerà immediatamente quando l'oggetto è stato collegato a un punto di ingresso non sicuro.
3) Successivamente, in alcuni casi il prodotto potrebbe non avere alcuna interazione diagnostica utile per tutte o parte delle sue operazioni quando distribuito in modalità di rilascio . Per esempio:
Supponiamo che sia un dispositivo incorporato in tempo reale. Generare eccezioni e riavviare quando incontra un pacchetto non valido è controproducente. Al contrario, il dispositivo può trarre vantaggio dall'operazione di massimo sforzo, fino al punto di rendere il rumore nella sua uscita. Inoltre, potrebbe non avere un'interfaccia umana, un dispositivo di registrazione o addirittura essere fisicamente accessibile dall'essere umano quando distribuito in modalità di rilascio e la consapevolezza degli errori è meglio fornita valutando lo stesso output. In questo caso, le asserzioni liberali e i test approfonditi prima del rilascio sono più preziosi delle eccezioni.
4) Infine, alcuni test sono inutili solo perché la chiamata è percepita come estremamente affidabile . Nella maggior parte dei casi, più codice riutilizzabile è, maggiore è stato lo sforzo di renderlo affidabile. Pertanto è comune a Exception per parametri imprevisti dei chiamanti, ma asserire risultati imprevisti da callees. Per esempio:
Se un'operazione principale String.Find
indica che restituirà a -1
quando i criteri di ricerca non vengono trovati, potresti essere in grado di eseguire in sicurezza un'operazione anziché tre. Tuttavia, se è effettivamente tornato -2
, potresti non avere un corso d'azione ragionevole. Sarebbe inutile sostituire il calcolo più semplice con uno che verifica separatamente un -1
valore e irragionevole nella maggior parte degli ambienti di rilascio sporcare il codice con test che assicurano che le librerie di base funzionino come previsto. In questo caso gli Assert sono ideali.