Utilizzo di "eccezioni di cattura" per migliorare la leggibilità, buona o cattiva?

9

Nella sezione Quando utilizzare l'eccezione in The Pragmatic Programmer , il libro scrive che invece di:

retcode = OK;
     if (socket.read(name) != OK) {
      retcode = BAD_READ;
    }
     else {
      processName(name);
       if (socket.read(address) != OK) {
        retcode = BAD_READ;
      }
       else {
        processAddress(address);
         if (socket.read(telNo) != OK) {
          retcode = BAD_READ;
        }
         else {
          //  etc, etc...
        }
      }
    }
     return retcode;

, preferiscono:

 retcode = OK;
     try {
      socket.read(name);
      process(name);
      socket.read(address);
      processAddress(address);
      socket.read(telNo);
      //  etc, etc...
    }
     catch (IOException e) {
      retcode = BAD_READ;
      Logger.log( "Error reading individual: " + e.getMessage());
    }
     return retcode;

semplicemente perché sembra più ordinato. Sono all per il codice più recente, tuttavia non è necessario rilevare eccezioni a un collo di bottiglia delle prestazioni?

Posso capire che dovremmo rinunciare all'ottimizzazione minuscola per il codice più ordinato (almeno il 99% delle volte), tuttavia da quello che so, le eccezioni di cattura appartengono alla classe di codice che ha un ritardo notevole in runtime. Quindi mi chiedevo qual è la giustificazione che il secondo pezzo di codice sia preferito rispetto al primo codice?

O meglio, quale codice preferiresti?

    
posta Pacerier 04.11.2011 - 13:54
fonte

4 risposte

18

Le eccezioni sono in genere solo più lente se vengono effettivamente lanciate. Di solito, le eccezioni in situazioni come questa sono rare, quindi non è qualcosa di cui dovresti preoccuparti. Dovresti solo preoccuparti delle prestazioni delle eccezioni se accadono continuamente e quindi sono un fattore significativo.

Il secondo codice è migliore perché è molto più semplice seguire la logica. La gestione degli errori è ben localizzata. L'unica obiezione è che se si utilizzano le eccezioni, utilizzare le eccezioni. Non rilevare le eccezioni e quindi restituire un codice di errore.

    
risposta data 04.11.2011 - 14:30
fonte
6

Bene, come si dice anche, le eccezioni dovrebbero gestire i casi eccezionali , e poiché si tratta di un caso eccezionale (cioè qualcosa che accade in pochi e lontani tra loro) direi che questo si applica qui pure.

Inoltre, consiglierei contro l'ottimizzazione di micro cose come questa. Concentrati maggiormente sulla leggibilità del codice , poiché passerai molto più tempo a leggere il codice che a scrivere un nuovo codice.

Per assicurarti davvero che si tratti di un collo di bottiglia nelle prestazioni, esegui qualche profilazione e analizzi e concentrati sulle attività più critiche basate su tale analisi.

    
risposta data 04.11.2011 - 14:44
fonte
6

I can understand that we should give up minuscule optimization for neater code (at least 99% of the times), however from what I know, catching exceptions belong to the class of code which have a noticeable delay in runtime.

Da dove lo sai? Come definisci il "ritardo evidente"?

Questo è esattamente il tipo di mito di prestazioni vago (e completamente sbagliato) che porta a inutili premature ottimizzazioni.

Lanciare e catturare un'eccezione può essere lento rispetto all'aggiunta di due numeri, ma è completamente insignificante rispetto alla lettura dei dati da un socket. Probabilmente potresti lanciare e catturare migliaia di eccezioni nello stesso momento in cui hai letto un singolo pacchetto di rete. E non stiamo parlando di migliaia di eccezioni qui, solo una singola.

    
risposta data 04.11.2011 - 15:36
fonte
6

Sono d'accordo con le risposte che hai già detto che si tratta di un caso eccezionale, quindi è ragionevole usare la gestione delle eccezioni.

Affrontare le tue prestazioni riguarda più direttamente, penso che tu debba mantenere un senso di scala riguardo alle cose. Lanciare / catturare un'eccezione in queste circostanze è probabile che richieda un ordine di un microsecondo. Poiché il controllo di flusso procede, è lento - molte volte più lento delle normali dichiarazioni if , nessuna domanda al riguardo.

Allo stesso tempo, tieni presente che quello che stai facendo qui è la lettura dei dati da una rete. A 10 megabit al secondo (lento per una rete locale, ma piuttosto veloce come le connessioni Internet), è sullo stesso ordine del tempo di leggere un byte di informazioni.

Ovviamente, questo sovraccarico si verifica solo quando si lancia anche l'eccezione - quando non viene lanciata, di solito c'è poco o nessun sovraccarico (almeno da quello che ho visto, l'overhead più significativo non è t dalla gestione dell'eccezione stessa, come dall'aggiunta di più potenziali flussi di controllo, rendendo il codice più difficile da ottimizzare per il compilatore abbastanza bene).

In questo caso, quando viene generata un'eccezione, i tuoi dati di scrittura nel registro. Data la natura del logging, è molto probabile che il tuo flushing venga emesso non appena lo scrivi (per assicurarti che non vada perso). Scrivere su disco è (ancora una volta) un'operazione piuttosto lenta - è necessario un SSD di classe enterprise abbastanza veloce per arrivare addirittura a decine di migliaia di IOP / secondo. Un disco utilizzato per la registrazione potrebbe essere facilmente limitato a qualcosa come centinaia di IOP al secondo.

In conclusione: ci sono casi in cui la gestione delle eccezioni può essere significativa, ma questo quasi certamente è non uno di essi.

    
risposta data 04.11.2011 - 15:29
fonte

Leggi altre domande sui tag