¿Cuándo está bien usar el manejo de excepciones para la lógica de negocios?


Creo que se acepta que como regla general en Java (y tal vez cualquier lenguaje con manejo de excepciones) uno debe tratar de evitar el uso de manejo de excepciones para manejar la lógica de negocios. En general, si se espera que ocurra una determinada situación, uno debe comprobarla y manejarla más directamente que confiar en el manejo de excepciones para hacer la comprobación por usted. Por ejemplo, lo siguiente no se considera una buena práctica:

try{
  _map.put(myKey, myValue);
} catch(NullPointerException e){
  _map = new HashMap<String, String>();
}

En lugar de inicialización perezosa se debe lograr más como esto:

if(_map == null){
  _map = new HashMap<String, String>();
}
_map.put(myKey, myValue);

Por supuesto, podría haber una lógica mucho más compleja que simplemente manejar la inicialización perezosa. Así que dado que este tipo de cosas es generalmente mal visto...¿cuándo, si es que alguna vez, es una buena idea confiar en que ocurra una excepción para que ocurra cierta lógica de negocios? ¿Sería preciso decir que cualquier caso en el que uno se sienta obligado a usar este enfoque realmente está resaltando una debilidad de la API que se está utilizando?

Author: Michael McGowan, 2011-03-21

5 answers

Siempre que la excepción pueda ser anticipada pero no evitada.

Digamos, si está confiando en una API externa de algún tipo para analizar datos, y esa API ofrece métodos de análisis pero nada que indique si una entrada determinada puede analizarse o no (o si si el análisis puede tener éxito o no depende de factores fuera de su control, pero la API no proporciona llamadas a funciones apropiadas), y el método de análisis arroja una excepción cuando la entrada no puede analizarse.

Con una adecuada diseñado API, esto debe reducirse a una cantidad en algún lugar en el rango de "virtualmente nunca "a"nunca".

No veo absolutamente ninguna razón para usar el manejo de excepciones como un medio de control de flujo normal en el código. Es caro, es difícil de leer (basta con mirar su primer ejemplo; me doy cuenta de que probablemente se escribió muy rápido, pero cuando _map no se ha inicializado, lo que termina con es un mapa vacío, tirando la entrada que estaba tratando de agregar), y llena el código con en gran parte inútiles bloques try-catch, que pueden muy bien ocultar problemas reales. De nuevo tomando su propio ejemplo, ¿qué pasaría si la llamada a _map.add() fuera a lanzar un NullPointerException por alguna razón otro que _map siendo null? De repente, estás recreando silenciosamente un mapa vacío en lugar de agregarle una entrada. Lo que estoy seguro de que realmente no tengo que decir puede conducir a cualquier número de errores en lugares completamente no relacionados en el código debido a un estado inesperado...

Editar: Solo para ser claro, la respuesta anterior está escrita en el contexto de Java. Otros idiomas pueden (y aparentemente, lo hacen) diferir en el costo de implementación de las excepciones, pero otros puntos aún deben mantenerse.

 29
Author: Michael Kjörling,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-21 13:30:25

Lanzar una excepción es una operación relativamente costosa en C++, y extremadamente costosa en Java. Solo por razones de eficiencia, nunca tiene sentido evitar un control explícito y aceptar una excepción en su lugar. Supongo que podría ser capaz de justificarlo en algunos casos raros donde comprobar si se lanzaría una excepción es muy complejo o casi imposible,pero por lo demás, yo diría que la respuesta es "casi nunca."

 11
Author: Ernest Friedman-Hill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-21 13:14:07

Esta es realmente una pregunta de discusión, y la respuesta depende del diseño de su sistema.

Mi instinto es siempre una manta nunca, pero he visto varios sistemas implementar errores de negocio utilizando excepciones. Personalmente lo encuentro repugnante, pero realmente entiendo la ventaja de romper un proceso de negocio tan pronto como sabes que falló, manejar tu fracaso ( por ejemplo, revertir tu Unidad de Trabajo) y devolver el error a la persona que llama, tal vez con información adicional.

Una posible desventaja, es que es realmente sencillo hacer el manejo de errores a través de varias clases diferentes, por lo que la definición de lo que sucede cuando el proceso falla es realmente difícil de deducir del código.

De todos modos no hay una sola respuesta aquí, es necesario sopesar ambos enfoques, y a veces combinarlos.

Con respecto a su ejemplo, no veo ninguna ventaja para el uso de excepciones para el control de flujo, especialmente en un " bueno "(diseñado para funcionar) escenario.

 1
Author: AK_,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-30 08:52:08

Hay una razón por la que las excepciones son objetos. También hay una razón por la que los diseñadores del lenguaje Java dividen todos los Throwables en 2 tipos principales: marcados y sin marcar.

¿Es una buena idea confiar en un excepción que ocurre con certeza lógica de negocio para ocurrir?

Sí. Absolutamente. Deberías leer El Capítulo 9 de "Effective Java, Second Edition". Está todo ahí. Bien explicado y esperándote.

 0
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-21 13:36:03

Si se trata de una condición de error que en realidad es parte de la lógica de negocio, está bien usar Excepciones. Por ejemplo:

try{
   // register new user
   if(getUser(name) != null)
      throw new MyAppException("Such user already exists");
   //other registration steps......
}catch(MyAppException ex){
   sendMessage(ex.getMessage());
}
 -2
Author: Ma99uS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-21 13:26:36