Mi rendo conto che mentre la domanda non ha tag di linguaggio, probabilmente sta parlando implicitamente di "lingue del caffè". Ma solo per completezza, vorrei menzionare il consenso apparente un po 'divergente nel mondo C ++.
Ci sono tre cose in cui i programmatori C ++ saranno in genere interessati:
- Avrà overheading zero nei build ottimizzati? (Cioè, può essere "compilato"?)
- Posso usarlo per intercettare un debugger proprio nel punto in cui è stato rilevato l'errore?
- Posso usarlo per segnalare problemi dalle funzioni dichiarate
noexcept
?
In passato, ho affrontato il primo problema scrivendo un codice come questo
int
factorial(const int n)
{
if (CHECK_ARGS)
{
if (n < 0)
throw std::invalid_argument {"n < 0"};
}
int fac = 1;
for (int i = 2; i <= n; ++i)
fac *= i;
return fac;
}
dove CHECK_ARGS
è #define
d a una costante in fase di compilazione, in modo che il compilatore possa eliminare completamente tutto il codice di verifica degli argomenti nelle build ottimizzate. (Non sto dicendo che compilare i check out sia una cosa buona in generale, ma credo che un utente dovrebbe avere l'opzione per compilarli.)
Mi piace ancora di questa soluzione che il codice di controllo degli argomenti sia chiaramente visibile raggruppato in if
. Tuttavia, il secondo e il terzo problema non sono risolti da questo. Pertanto, ora mi sto appoggiando di più verso l'utilizzo di una macro assert
per il controllo degli argomenti.
Gli standard di codifica potenziati sono d'accordo con questo:
What About Programmer Errors?
As a developer, if I have violated a precondition of a library I'm using, I don't want stack unwinding. What I want is a core dump or the equivalent - a way to inspect the state of the program at the exact point where the problem was detected. That usually means assert()
or something like it.
C'è stata una conversazione molto interessante tenuta da John Lakos in CppCon'14 intitolata Programmazione difensiva eseguita a destra ( parte 1 , parte 2 ). Nella prima parte del suo discorso, discute la teoria dei contratti e il comportamento indefinito. Nella seconda parte, presenta ciò che considero un'ottima proposta per il controllo sistematico degli argomenti. In sostanza, propone macro di asserzione che consentono all'utente di selezionare la quantità di budget (in termini di utilizzo della CPU) che è disposta a donare alla libreria per il controllo degli argomenti e fa in modo che la biblioteca faccia un uso saggio di tale budget. Come aggiunta, l'utente può anche installare una funzione di gestione degli errori globale che verrà chiamata nel caso in cui venga rilevato un contratto interrotto.
Riguardo all'aspetto che una funzione è privata, non penso che questo significhi che mai debba controllarne gli argomenti. Potremmo fidarci più del nostro codice per non violare il contratto di una funzione interna, ma sappiamo anche che non siamo perfetti. Il controllo degli argomenti nelle funzioni interne è altrettanto utile nel rilevare i nostri bug, quanto nelle funzioni pubbliche per il rilevamento di errori nel codice client.