Asserzioni in funzioni private - Dove disegnare la linea?

2

Usiamo asserzioni per verificare comportamenti illegali che non dovrebbero accadere se tutto funziona come dovrebbe, come usare NULL come argomento quando chiaramente non dovrebbe.

Questo è tutto molto bene quando scrivi funzioni pubbliche dato che non ti puoi fidare che il programmatore che le utilizzerà non commetterà un errore. Ma che dire delle funzioni private, che non saranno accessibili dall'esterno? Naturalmente, la funzione che usa quelle funzioni private può contenere un bug (cioè hai fatto un errore), ma dovremmo sempre usare asserzioni in funzioni private? C'è una riga in cui possiamo dire "Ehi, non abbiamo bisogno di un'affermazione qui perché, a causa delle precedenti affermazioni e dell'uso della funzione privata, possiamo supporre che i parametri siano sempre sicuri"?

Ora sono un po 'scettico riguardo a quest'ultima parte - possiamo mai presumere che le cose siano sempre come dovrebbero?

    
posta gablin 25.03.2011 - 22:47
fonte

5 risposte

3

Onestamente, a meno che non si scriva sul serio il codice critico dell'ora, l'uso dell'asserzione in qualsiasi forma si presenti (potrebbe essere semplice come controllare i valori di ritorno o convalidare i parametri passati) è estremamente utile specialmente nel software di produzione. Posso identificare almeno 2 ragioni per cui questo è vero.

Innanzitutto, i clienti / clienti non vogliono che il loro software si arresti in modo anomalo. Se il tuo software esplode (qualunque cosa ciò significhi) sembra molto peggio da una reputazione e un punto di vista della soddisfazione del cliente che semplicemente fallendo con garbo. Spesso potresti ricevere feedback come "Questa caratteristica sembra essere rotta, ma il resto del sistema funziona bene ... volevo solo farti sapere ... la sua non alta priorità." Se esplodono, il tuo software sembra scadente.

In secondo luogo, ha un valore inestimabile da un punto di vista del debug. Il tuo codice avrà bug. Non mi interessa quanto pensi di essere bravo, qualcosa si spezzerà. Se disponi di assegni o asserzioni e possiedi un modo per notificare o registrare questa condizione, sarà sempre più facile e veloce trovare e risolvere il problema.

Terzo e so che ho detto che ne avevo solo due, definire l'interfaccia pubblica. Se qualcuno sta modificando il tuo codice puoi ancora fare "asserzione" che la funzione privata è privata? Dal punto di vista della manutenzione, affermazioni o verifiche sono un vero toccasana. Non so quante volte ho visto un bug relativo al fatto che il C std lib non controlla i puntatori nulli ... cioè. strdup (). Semplice e semplice, è solo una buona programmazione difensiva usare asserzioni e / o assegni.

    
risposta data 26.03.2011 - 05:04
fonte
1

Now I myself am a bit skeptical about that last part - can we ever safely assume that things are always as they should be?

Sì, possiamo, subito dopo averlo affermato naturalmente.

Le asserzioni sono buone. Evita il calcolo costoso in asserzione e ottimizza il controllo:

// C (in debug mode)
// unlikely is a hint to the compiler that the branch is unlikely to be taken
#define assert(x) if(unlikely(!(x))) { abort(); }

Le asserzioni ti portano:

  • un ulteriore livello di sicurezza (in aggiunta ai test)
  • aiuto con il debug (quando leggi la funzione cercando il bug, le asserzioni in cima stabiliscono le precondizioni)

L'unica domanda è cosa fare in caso di attivazione di un'asserzione.

Personalmente, raccomando un comportamento diverso tra la build di Debug e Release:

  • in Debug: abort e assicurati di ottenere un dump della memoria. In questo modo non puoi trascurarlo e hai (quasi) tutto il necessario per rintracciarlo.
  • nella versione: throw (e registra, se possibile), in questo modo, puoi recuperare con garbo, che è importante per un prodotto consegnato o un server in esecuzione.

Quest'ultimo aspetto è ovviamente un pio desiderio, se la profilazione mostra che alcune affermazioni causano un impatto sulle prestazioni, allora dovrai spogliarle dalla build di rilascio (e scrivere un commento che indichi perché sono state rimosse).

    
risposta data 27.03.2011 - 14:11
fonte
0

Bene, c'è un argomento legittimo se dovresti usare le affermazioni affatto , ma se lo fai, perché vuoi usarle meno nelle tue funzioni? Se mai, dovresti gestire l'errore in modo più garbato in un'interfaccia pubblica (?)

Non dovrebbero funzionare come tali, ma per renderlo il più chiaro possibile (in secondo luogo solo per un controllo di tipo statico) in quale contesto si suppone di utilizzare la funzione. Pensa a loro come un commento che dice "// questo argomento non dovrebbe mai essere nullo", ma dove lo vuoi veramente dire.

Dopo tutto, se fai hai ragione, non ti importa se sono lì o no. E se non lo fai (e credimi, succederà prima o poi), preferiresti che l'errore fosse immediatamente chiaro? O sepolto nell'implementazione della funzione (o peggio, nel risultato)?

    
risposta data 26.03.2011 - 00:25
fonte
0

Le asserzioni sono generalmente buone per lo sviluppo, buone per i test e utili per la documentazione.

L'unico vero problema è se c'è un colpo di performance inaccettabile. Se è così, rimuovili alla compilazione finale. Se no, allora lasciali.

    
risposta data 26.03.2011 - 00:35
fonte
0

Alcuni linguaggi (Scala, Haskell) hanno tipi speciali invece di controlli null, chiamati Option e Maybe.

Nelle lingue tipizzate staticamente, puoi di per sé attuare molti controlli con il sistema dei tipi.

Forse hai un framework con test unitari, per prevenire errori prevedibili.

Controllare i tuoi metodi privati in un modo o nell'altro mi sembra più importante di come controllarlo.

    
risposta data 27.03.2011 - 00:26
fonte

Leggi altre domande sui tag