Lanciare e catturare eccezioni nella stessa funzione / metodo

9

Ho scritto una funzione che richiede un input all'utente finché l'utente non immette un numero intero positivo (un numero naturale). Qualcuno ha detto che non dovrei lanciare e catturare eccezioni nella mia funzione e lasciare che sia il caller della mia funzione a gestirle.

Mi chiedo cosa ne pensano gli altri sviluppatori di questo. Probabilmente sto anche sfruttando le eccezioni nella funzione. Ecco il codice in Java:

private static int sideInput()
{
    int side = 0;
    String input;
    Scanner scanner = new Scanner(System.in);

    do {
        System.out.print("Side length: ");
        input = scanner.nextLine();
        try {
            side = Integer.parseInt(input);
            if (side <= 0) {
                // probably a misuse of exceptions
                throw new NumberFormatException();
            }
        }
        catch (NumberFormatException numFormExc) {
            System.out.println("Invalid input. Enter a natural number.");
        }
    } while (side <= 0);

    return side;
}

Sono interessato a due cose:

  1. Devo lasciare che il chiamante si preoccupi delle eccezioni? Il punto della funzione è che rimpicciolisce l'utente fino a quando l'utente non immette un numero naturale. Il punto della funzione è negativo? Non sto parlando di UI (l'utente non è in grado di uscire dal ciclo senza input corretto), ma di input in loop con eccezioni gestite.
  2. Diresti che l'affermazione del lancio (in questo caso) è un abuso di eccezioni? Potrei facilmente creare un flag per verificare la validità del numero e generare il messaggio di avviso basato su quel flag. Ma questo aggiungerebbe più linee al codice e penso che sia perfettamente leggibile così com'è.

Il fatto è che spesso scrivo una funzione di input separata. Se l'utente deve inserire un numero più volte, creo una funzione separata per l'input che gestisce tutte le eccezioni e le limitazioni di formattazione.

    
posta usr 22.11.2011 - 21:13
fonte

5 risposte

10

Il punto di un'eccezione è che consente a un metodo di dire a quel chiamante che è entrato in uno stato in cui non può continuare normalmente, senza costringerti a incorporare un codice di errore nel valore di ritorno.

Nel tuo caso, il tuo metodo sa esattamente cosa fare quando l'input non è maggiore di 0. L'unica ragione per cui stai salvando le righe qui è perché ti capita di lanciare la stessa eccezione che avresti se l'input non fosse un numero. Tuttavia, l'eccezione che stai lanciando non rappresenta correttamente il motivo per cui il tuo codice non apprezza l'input. Se qualcun altro dovesse venire a vedere questo codice, dovrebbe impiegare più tempo a cercare di vedere esattamente come funzionano le cose.

    
risposta data 22.11.2011 - 21:28
fonte
4

Questo è un cattivo uso delle eccezioni. Per cominciare, un numero non positivo non è un'eccezione di formato.

Perché usare le eccezioni? Se sai quale input non è consentito, non interrompere il ciclo finché non ottieni input validi dall'utente, qualcosa di simile al seguente:

while (true)
{
   // Get user input.
   String input = scanner.nextLine();

   try
   {
      side = Integer.parseInt(input);

      break;
   }
   catch (NumberFormatException ex)
   {
      // Inform user of invalid input.
      System.out.println("Invalid input. Enter a natural number.");
   }
}
    
risposta data 22.11.2011 - 21:20
fonte
0

Rileva solo eccezioni se intendi fare qualcosa che è rilevante per la chiamata al metodo corrente; la pulizia, la logica di errore, ecc. In questo caso, la cattura è semplicemente l'invio di un messaggio alla console, non è rilevante per il metodo sideInput, quindi può essere gestita più in alto nella catena di chiamate / stack.

Si può sbarazzarsi del try / catch qui e semplicemente documentare la chiamata del metodo:

//Throws NumberFormatException if read input is less than 0
private static int sideInput()

Uno ha ancora bisogno di gestire quell'eccezione più in alto nella catena di chiamate / stack!

    
risposta data 23.11.2011 - 04:55
fonte
0

Non dovresti lanciare e catturare la stessa eccezione in un metodo, ma penso che il blocco catch catturerà la stessa eccezione che stai lanciando, quindi non lo stai davvero buttando.

Se parseInt ha avuto esito positivo, non è un NumberFormatException .

se il lato è inferiore a zero, devi lanciare un NegativeSideLengthException ;

Crea un'eccezione personalizzata / di bussiness chiamata NegativeSideLengthException

public class NegativeSideLengthException extends Exception
{


    public NegativeSideLengthException(Integer i)
    {
        super("Invalid negative side length "+i);        
    }

}

Quindi sideInput genera NegativeSideLengthException

private static int sideInput() throws NegativeSideLengthException
{
    int side = 0;
    String input;
    Scanner scanner = new Scanner(System.in);

    do {
        System.out.print("Side length: ");
        input = scanner.nextLine();
        try {
            side = Integer.parseInt(input);
            if (side <= 0) {
                throw new NegativeSideLengthException(side);
            }
        }
        catch (NumberFormatException numFormExc) {
            System.out.println("Invalid input. Enter a natural number.");
        }
    } while (side <= 0);

    return side;
}

Puoi persino (se vuoi) aggiungere un altro blocco catch per catturare NegativeSideLengthException e non avere il metodo per lanciarlo.

do {
    System.out.print("Side length: ");
    input = scanner.nextLine();
    try {
        side = Integer.parseInt(input);
        if (side <= 0) {
            throw new NegativeSideLengthException(side);
        }
    }
    catch (NumberFormatException numFormExc) {
        System.out.println("Invalid input. Enter a natural number.");
    } catch (NegativeSideLengthException e){
        System.out.println("Invalid input. Enter a non-negative number.");
    }
} while (side <= 0);

Le bandiere non sono un buon modo per gestire le eccezioni.

    
risposta data 03.10.2012 - 15:13
fonte
-1

Le eccezioni sono cose da incubo, portano più complessità di quelle che risolvono.

In primo luogo, se non rilevi le eccezioni, il chiamante può fare solo on error resume next , cioè dopo una settimana, anche se non sai cosa può lanciare la tua funzione e cosa farne:

{
    ...
}
catch(OutOfMemory, CorruptedMemory, BadData, DanglingPointers, UnfinishedCommit)
{
    Console.WriteLine("Nothing to see here, move on.");
    Console.WriteLine("The app is very stable, see, no crashing!");
}

In sostanza, se li prendi, devi avere un'ottima conoscenza dei contratti e delle garanzie di eccezione. Succede raramente in un mondo reale. E anche il tuo codice sarà difficile da leggere.

Inoltre, la cosa divertente è che se hai davvero qualche possibilità di gestire le eccezioni hai bisogno di un vero linguaggio RAII, che è un po 'umoristico, dal momento che Java e .NET riguardano esclusivamente le eccezioni ...

Ripeti questa operazione ancora una volta, ma ...:

link

link

link

    
risposta data 22.11.2011 - 21:53
fonte

Leggi altre domande sui tag