Assertire in metodi pubblici [duplicato]

9

Sono un fan dell'uso di asserzioni nel codice per verificare le precondizioni. La domanda è: è saggio usare le asserzioni nei metodi pubblici per verificare la precondizione?

La mia opinione personale è che se il mio metodo non può gestire l'assenza di un parametro (o qualche valore non valido) e fa parte di un'API ma non si basa sull'input dell'utente, allora il problema (parametro errato) deve essere gestito durante il processo di sviluppo (almeno con i test di integrazione) e non più tardi quando il software viene utilizzato sul campo. Per questo motivo uso le asserzioni anche nei metodi pubblici.

Intendo qualcosa del genere:

public class SomeMagic implements MagicAPI {

    public WoW doSomeMagic( Stuff source ) {
        assert source != null : "Incorrect use of the API";

        // if assertions are deactivated (should be the case in production environment)
        // this line will throw a NpEx 
        if ( source.isPlainStuff() ) {
            // some magic with a plain stuff
        }

        return Wow.beSurprised;
    }
}
    
posta GeT 09.03.2012 - 10:34
fonte

5 risposte

12

È sensibile al contesto. Una volta ho provato a creare una "linea guida" quando utilizzare le asserzioni e la gestione degli errori. L'ho definito un "compromesso di fiducia" e illustrato in questo modo:

!!!!!!!!!!!!!    a) user input
...!!!!!!!!!!    b) external data input (network, ...) 
......!!!!!!!    c) internal data input (other process)
*.........!!!    d) library (external)
**..........!    e) library (internal)
****.........    f) public functions (team)
********.....    g) public functions (own code)
************.    h) private functions

! extra validation needed (anything can be thrown in), never ever any assumptions!
. standard validation
* assertions only possible

Nel tuo caso (API della libreria interna?) tenderei a convalidare più che usare asserzioni. È molto difficile anticipare tutti gli usi (ab) della libreria dal codice del chiamante e la copertura dei test di integrazione tende ad essere frammentaria. Se non ci sono limiti puoi anche lasciare asserzioni nel codice di produzione per mantenere la convalida (diventerebbero un'eccezione).

    
risposta data 09.03.2012 - 11:25
fonte
4

Secondo me la visibilità dei tuoi metodi non ha alcuna importanza. Dopo tutto, tutti i tuoi metodi privati vengono in definitiva chiamati in ogni caso da metodi pubblici, altrimenti non sarebbero necessari!

Per essere precisi, una precondizione fallita ad un metodo privato non è sempre causata da una precondizione fallita ad un metodo pubblico, ma spesso lo è, e comunque il punto delle asserzioni non è quello di mantenere il punteggio in una partita di gioco di biasimo tra lo sviluppatore della biblioteca e lo sviluppatore dell'applicazione. Se viene violata una condizione preliminare, c'è un errore di programmazione da qualche parte e si desidera essere informati di ciò con un arresto anomalo del runtime o non lo si fa. Questa è la domanda che decide se affermare o meno.

    
risposta data 09.03.2012 - 11:13
fonte
4

Nel caso di una biblioteca pubblica (che altre persone useranno anche) dovresti lanciare un'eccezione invece di mettere assert . Questo è anche il modo in cui è progettata l'API Java.

E un giorno il tuo codice potrebbe essere trasformato in una biblioteca ...

Quindi personalmente lancio sempre IllegalArgumentException in questi casi o come nel tuo esempio specifico può anche essere NullPointerException .

    
risposta data 09.03.2012 - 14:27
fonte
2

Penso che tu abbia capito bene. Le asserzioni sono per mancanza veloce dopo che è stato rilevato un errore del programmatore.

Se sai che l'applicazione si bloccherà o rimarrà in uno stato cattivo / sconosciuto, allora asserisci.

    
risposta data 09.03.2012 - 12:37
fonte
1

Sospetto che la mia possa essere una visione minoritaria, ma personalmente considero le affermazioni in qualsiasi altro ostacolo alle prestazioni come un'ottica prematura.

Generalmente se vale la pena di verificare una pre-condizione in modalità di debug, vale la pena controllare in modalità di rilascio. Ovviamente se hai profilato il tuo codice e hai scoperto che devi eliminare ogni ultimo ciclo di clock da una funzione, allora asserisci di colmare il divario tra nessun controllo di pre-condizione (che potrebbe essere necessario se hai bisogno di rispettare un vincolo di temporizzazione anche nel debug modalità) e velocità in modalità di rilascio.

vale a dire. non disabilitare i controlli di pre-condizione a meno che non sia necessario

    
risposta data 09.03.2012 - 13:48
fonte

Leggi altre domande sui tag