Cattura le eccezioni nel livello di servizio senza nascondere i bug

0

Immaginiamo di avere un servizio CustomerService :

public class CustomerService
{
    public Customer GetCustomer(string customerName)
    {
        if(string.IsNullOrWhiteSpace(customerName))
            throw new ArgumentNullException(nameof(customerName));

        try
        {
            var customer = customerRepository.GetByName(customerName);
            return customer;
        }
        catch(Exception ex)
        {
            _logger.Error(ex);
            throw;
        }
    }
}

Questo servizio è utilizzato in un controller MyController :

public class MyController : Controller
{
     /* Properties */

     public ActionResult CustomerStuff(string customerName)
     {
          try
          {
              var customer = _customerService.GetCustomer(customerName);
              return View(customer);
          }
          catch (Exception ex)
          {
              // Redirect to error page, etc...
          }
     }
}

Il problema con questo è che nascondo possibile ArgumentNullException che è probabilmente causato da un bug nel mio codice. Non mi aspetto mai che passi nulla da null a GetCustomer , ma catch(Exception) in MyController nasconde questa eccezione con il resto delle eccezioni. D'altra parte, in produzione, desidero reindirizzare gli utenti se qualcosa va storto in CustomerService , perché ad es. si è verificato un timeout di connessione.

Come si può risolvere questo problema senza tonnellate di codice, come ad esempio:

try
{

}
catch (Exception ex) when (!(ex is ArgumentNullException))
{
    // handle timeouts, network availability, etc..
}

Una possibile soluzione che riesco a vedere è la creazione di un'eccezione personalizzata, ad esempio ServiceException e il lancio all'interno di try/catch in GetCustomer metodo. C'è qualche altra tecnica che è forse più comune?

    
posta FCin 18.06.2018 - 11:05
fonte

1 risposta

2

Cambia il tuo servizio in:

public class CustomerService
{
    public Customer GetCustomer(string customerName)
    {
        try
        {
            if(string.IsNullOrWhiteSpace(customerName))
                throw new ArgumentNullException(nameof(customerName));

            var customer = customerRepository.GetByName(customerName);
            return customer;
        }
        catch(Exception ex)
        {
            _logger.Error(ex);
            throw;
        }
    }
}

In questo modo, il tuo logger intercetta l'errore dell'argomento, insieme a tutti gli altri errori. Il controller non richiede quindi alcuna logica speciale per gestire eccezioni specifiche.

    
risposta data 18.06.2018 - 11:53
fonte

Leggi altre domande sui tag