linea guida sui metodi void che non generano eccezioni

0

Nel nostro codebase ho visto un metodo simile al seguente:

public void doSomething() {
    try {
        ...
    } catch (Exception e) {
        ...
        //log something
        ...
    }
}

Il chiamante non ha modo di sapere se il metodo ha fatto quello che dovrebbe. Ci sono delle linee guida generali su Java per non scrivere metodi void che non generano eccezioni?

    
posta hrishikeshp19 25.06.2015 - 23:35
fonte

2 risposte

4

First of all this method is not unit testable.

Non c'è nulla nel codice che hai citato che impedisce che sia coperto dai test unitari.

La presenza di try / catch è irrilevante:

  • Puoi verificare la situazione in cui non ci sono errori e verificare se gli effetti collaterali di questo metodo corrispondono alle aspettative.

  • Puoi anche verificare la situazione in cui viene prodotta un'eccezione e assicurarti che il messaggio previsto sia effettivamente registrato (si spera che il framework di registrazione possa essere sostituito con una simulazione).

Ciò significa che è possibile ottenere una copertura del ramo al 100% nonostante la cattura globale dell'eccezione. Parlando del problema globale, questo non è qualcosa che vuoi veramente nel tuo codice base (a meno che non ci sia un throw dentro un catch ), ma questo non ha nulla a che fare con i test unitari.

Ciò si applica anche se il metodo stava rilevando solo un'eccezione specifica, ad esempio FileNotFoundException , ma potrebbero esserci altre eccezioni generate, come StackOverflowException . Puoi quindi avere tre test:

  • La situazione ordinaria con effetti collaterali previsti,

  • La situazione in cui FileNotFoundException viene generata e il messaggio di log previsto viene aggiunto,

  • La situazione in cui StackOverflowException viene lanciata; qualsiasi framework di test di unità decente consente di verificare che l'eccezione sia effettivamente lanciata in un caso testato (e il test fallirà se il metodo non genera l'eccezione prevista).

Are there any general Java guidelines on not writing void methods that do not throw exceptions?

Con "non lanciare eccezioni", suppongo tu intenda piuttosto "prendere tutte le eccezioni".

  • Le eccezioni di cattura non hanno nulla di sbagliato non appena il metodo sa come gestire i casi eccezionali. Ad esempio, un metodo che accede al file di configurazione e incontra FileNotFoundException può invece fallback alla configurazione predefinita, senza riportare alcuna eccezione al chiamante. Questo va bene.

  • Catching exceptions globally (that is catch (Exception) ) è leggermente più problematico. I casi in cui i metodi sono in grado di gestire una situazione eccezionale qualsiasi sono molto rari. Ci sono ancora due eccezioni:

    1. Un metodo può catturare qualsiasi eccezione e quindi lanciare la stessa eccezione (preferibilmente senza rompere lo stack). Ciò, ad esempio, abilita la registrazione: un metodo registra un'eccezione e quindi consente al chiamante di gestirli.

    2. Un metodo che è in cima allo stack può catturare qualsiasi eccezione, perché la scelta è piuttosto limitata: o si cattura l'eccezione, o si lascia il programma in crash. Gli sviluppatori potrebbero preferire in questo caso catturare tutto, anche le eccezioni che non possono affrontare e, ad esempio, presentare all'utente una finestra di dialogo user-friendly che rende possibile riportare l'eccezione al team di sviluppatori.

risposta data 25.06.2015 - 23:51
fonte
2

In generale, un'eccezione è adatta a questo e la miglior pratica che dovresti seguire è: "Se un metodo non può fare il suo lavoro, dovrebbe generare un'eccezione."

Comprensibilmente, è possibile che il flusso di esecuzione continui senza eccezioni. Lo spazio .NET gestisce questo abbastanza bene e fornisce una convenzione per i metodi che non generano eccezioni. I metodi che iniziano con "Prova" restituiscono sempre un valore booleano e non generano eccezioni.

Il vantaggio di questo approccio è che puoi scrivere test sul metodo DoWork per verificare che le eccezioni vengano generate quando previsto, e viceversa non vengono generate eccezioni quando chiami l'equivalente Try.

public void DoWork() {
   // try to do the work, and if it fails, throw
}

public bool TryDoWork() {
   try {
      DoWork();
      return true;
   } 
   catch {
      return false;
   }
}

In alternativa, se questa non è la tua tazza di tè, un altro approccio consiste nel prendere in giro il tuo Logger e scrivere test che catturino gli errori registrati.

Due esempi di supporto:

  1. Pulisci codice - di Robert C Martin
  2. Lavorare efficacemente con il codice legacy - di Michael Feathers
risposta data 25.06.2015 - 23:56
fonte

Leggi altre domande sui tag