Prova il dilemma Catch and Flow Control

2

Sono consapevole che fare Controllo del flusso su un programma utilizzando un blocco try-catch è una cattiva pratica, ma non riesco a vedere come farlo in un altro modo quando l'errore rilevato richiede un reindirizzamento dell'esecuzione del codice.

Ad esempio, supponiamo di avere una schermata in cui l'utente fa clic su un pulsante e sui pulsanti fai clic su Esegui del codice. Dopo che il codice termina l'esecuzione, reindirizzo l'utente a una nuova schermata ....

... Ma l'esecuzione del codice può fallire e, in tal caso, devo informare l'utente dell'errore e reindirizzarlo alla schermata precedente.

Il modo in cui lo farò è:

try
{
     ExcuteCode();
     NavigateToNextScreen();
} 
catch(Exception e) 
{
     Log.Write(e);
     ShowErrorMessage();
     GoBack();
} 

Anche se lo cambio in:

bool hasError = false;

try
{
     ExecuteCode();
} 
catch(Exception e) 
{
      Log.Write(e);
      ShowErrorMessage();
      hasError = true;
 } 

  if(hasError) { GoBack(); } 
  else { NavigateToNextScreen();} 

Sta ancora facendo Controllo del flusso all'interno del blocco try-catch .

Quindi, esiste un modo consigliato per gestirlo correttamente ed evitare questa cattiva pratica?

    
posta mFeinstein 10.07.2015 - 05:34
fonte

2 risposte

7

Sembra che tu abbia frainteso cosa si intende quando le persone dicono che non dovresti usare eccezioni per il controllo del flusso nel tuo programma.

Lanciare un'eccezione e catturare quell'eccezione altrove nel tuo programma cambia il flusso di controllo del programma. In questo modo, la gestione delle eccezioni è un costrutto di controllo del flusso, proprio come un ciclo while o un'istruzione goto.

Ciò che distingue la gestione delle eccezioni a prescindere da altri costrutti di controllo del flusso è che la gestione delle eccezioni può consentire di uscire più chiamate di funzioni contemporaneamente, ma anche quella potenza rende costose le operazioni perché l'ambiente di runtime deve capire quale blocco di cattura saltare a.

Il costo relativo della gestione delle eccezioni è la fonte per l'adagio di non usarli per il controllo del flusso, ma ciò che si intende in realtà è che non si dovrebbero usare eccezioni per realizzare un flusso attraverso il programma che dovrebbe accadere con qualsiasi la regolarità.
Le eccezioni sono uno strumento perfetto se si verifica un errore ed è necessario eseguire il salvataggio di più livelli del proprio stack di chiamate. Sono esattamente lo strumento sbagliato per saltare fuori da un loop perché hai trovato quello che stavi cercando.

    
risposta data 10.07.2015 - 08:23
fonte
1

Ci sono molti modi per affrontarlo. Ecco solo due idee:

  • Avvolgi il tuo try-catch in un metodo con tipo di ritorno booleano, indicando se ExecuteCode () ha avuto successo. Il flusso di controllo viene quindi deciso sul sito di utilizzo, dove viene visualizzato il messaggio di errore e si ritorna in caso di errore. È simile alla tua seconda versione, ma invece di modificare direttamente una variabile che viene utilizzata per il flusso di controllo, devi solo restituire lo stato del risultato e non fare ipotesi sul flusso di controllo del chiamante.

  • Cambia il lancio di eccezioni in un modello simile alla convalida. Questo è come il booleano, ma senza un tentativo di cattura. In caso di errore, ExecuteCode restituisce un oggetto Failure con la descrizione del problema. In questo modo è possibile modificare il controllo del flusso in base al valore del risultato, senza che sia necessario conoscere il codice di rilevamento degli errori.

In generale, la maggior parte dei modi a cui riesco a pensare si basa sull'avere un tipo migliore per ExecuteCode. Quando ExecuteCode () non restituisce nulla, ma genera l'eccezione, questo è essenzialmente ciò che richiede di spostare la logica in try e catch. Un tipo di reso migliore ti consente semplicemente di delegare le decisioni sul flusso di controllo in base a quello.

    
risposta data 10.07.2015 - 07:38
fonte

Leggi altre domande sui tag