2009-12-03 15 views
6

¿Existe alguna norma de mejores prácticas o de la industria para lanzar excepciones desde una API de kit de herramientas?Definición de excepciones que se pueden generar desde un kit de herramientas API

¿Deberían los métodos de cara al usuario capturar y cerrar Exception en algún tipo de CustomException para que los usuarios solo tengan que preocuparse de que CustomException salga de la API?

¿O es la convención que simplemente dejen que los burbujas salgan?

Nos preocupamos por poder documentar todas las excepciones posibles que pueden arrojar nuestros métodos API. (Por ejemplo, si nuestro método API llama al Stream.Write(), que arroja 4 o 5 excepciones, tendríamos que documentar todas esas, además de otras excepciones que podrían lanzar otros métodos).

Estábamos pensando en hacer algo como esto:

public void customerFacingApiMethod(){ 
    try { 
     //api functionality goes here 
    } catch (Exception e) { 
     throw new CustomException(e); 
    } 
} 

Respuesta

13

En mi opinión, tener la API arrojando solo un tipo de excepción es una mala idea. Una de las cosas buenas con diferentes excepciones es que puede elegir capturar diferentes tipos de excepciones y manejarlas de manera diferente. La eliminación de excepciones en un solo tipo de excepción eliminaría esa facilidad.

Utilice los tipos de excepción proporcionados por el marco cuando corresponda, y cree sus propios tipos de excepción personalizados para situaciones específicas cuando corresponda. Y, sobre todo, asegúrese de documentar para cada método qué excepciones pueden arrojar.

+1

+1 por no ocultar los detalles de la excepción interna – Oded

+0

En principio, estamos de acuerdo. Pero, ¿qué sucede si una de las llamadas que hacemos cambia una excepción que arroja, ahora nuestra documentación no está sincronizada? O qué pasa si su documentación es incorrecta y hay una excepción lanzada que no está documentada. –

+3

¿y qué pasa si qué pasa si? Puede que si muere usted mismo, el punto es que está destruyendo la característica más importante de las excepciones, que es que están tipadas. – Fred

1

No me gusta. Si ajusta todas las excepciones en una CustomException, será difícil detectar excepciones específicas sin buscar dentro del objeto para InnerExcpetion (posiblemente múltiples niveles profundos si su API también usa otras API que hacen lo mismo). Si hay una OutOfMemoryException, me gustaría saberlo sin tener que buscarla.

1

No utilice la misma excepción para todas.

Necesita los diferentes tipos de excepciones para poder separar un caso de otro. Para cualquier cosa que permita que fluya hasta que un bloque genérico de manejador de excepciones lo atrape, parecerá k, pero está impidiendo la recuperación de otro código, acciones adicionales que operan en casos específicos.

Puede envolver un conjunto de excepciones, si se ajustan a un escenario específico que puede manejar el código de llamada. No olvide que algunas excepciones marco ya comunican bien la situación.

1

Lo que dice Fredrik Mork es muy cierto. También me gustaría agregar que puede documentar fácilmente las excepciones que se lanzan con comentarios xml (y GhostDoc).

Para que un usuario de la API pueda buscar en la documentación para ver qué excepciones se pueden lanzar. Sin embargo, hay un inconveniente.

Si usted tiene un profundo pila de llamadas dentro de su API y sobre todo si la complejidad ciclomática llega a ser alta (es decir, num de posibles ramas) no se puede recuperar todas las posibles excepciones que pueden ser lanzadas (tal vez por el tiempo de ejecución?)

Así Yo recomendaría lanzar solo si algo si la recuperación no es posible y solo lanzar en la capa superior de su API, es decir, no más profunda que 2 de profundidad. Y capte todas las excepciones que se lanzan más profundamente en su callstack y devuelvalas como InnerException o algo así.

3

Cuando arroje excepciones, asegúrese de que las excepciones dirigidas al usuario son todas relevantes para lo que el usuario realmente hizo mal con respecto a su conjunto de herramientas. Eso podría significar atrapar o fusionar diferentes excepciones del sistema de archivos en una sola excepción, pero nunca debería simplemente atrapar Excepción y lanzar una nueva, eso no le está diciendo al usuario del juego de herramientas qué hicieron mal.

3

Debe seguir los mismos conceptos que .NET Framework. Sus usuarios ya usan el marco, por lo que saben cómo funciona y esperan cierto comportamiento.

  • lanzar una excepción derivada de ArgumentException si un argumento desde el cliente no es válida (uso ArgumentNullException, ArgumentOutOfRangeException, etc., según corresponda).
  • Lanza una excepción derivada de IOException para errores de E/S.

Etc ...

En la documentación, establecen claramente las condiciones previas para su API pública e indicar las excepciones que serán lanzados cuando fallan (como MSDN hace).

1

Hay dos tipos de excepciones a considerar (ignorando StackOverflowException, etc., que no se puede hacer nada al respecto de todos modos):

  1. Aquellos que son causados ​​por problemas externos (como el archivo IO), que tiene que ser manejado.
  2. Los que siempre se pueden evitar con una entrada validada correctamente.

Por lo general, tiene sentido que las excepciones de tipo IO pasen por la pila de llamadas sin modificar, ya que no hay nada que realmente pueda hacer al respecto. Las excepciones a esto serían errores anticipados por los cuales podría hacer reintentos, o preguntarle al usuario qué hacer, si su API opera a nivel de la GUI (lo cual sería bastante inusual).

Solo asegúrese de documentar qué excepciones de este tipo pueden arrojar sus métodos API.

Del segundo tipo (excepciones que siempre se pueden evitar), estas excepciones pueden ser generadas por su API en malas entradas, pero nunca deben pasarse por la pila de llamadas desde los niveles inferiores. La entrada a todo lo que llame debe validarse para que estos errores no ocurran, y si, por alguna razón, pueden ocurrir, entonces estas excepciones deben completarse. De lo contrario, el código que usa su API tendrá que lidiar con excepciones en el nivel incorrecto de abstracción.

Y una vez más, asegúrese de documentar qué tipo de entrada no generará excepciones, y qué tipo de excepciones esperar si se rompen estas reglas.

En todos los casos, genere excepciones que tengan sentido para el usuario de su API, no para la persona que programa la API.

1

El problema con la captura de System.Exception en el caso general es que al hacerlo, estás diciendo efectivamente "No tengo idea de por qué esto falló, y está bien, porque sé que puedo continuar de todos modos ! "

Eso rara vez, si alguna vez, es cierto.

Concluir todas las excepciones en un único tipo de excepción personalizado significa que sus consumidores simplemente captarán ese tipo, que es el equivalente moral de la captura de System.Exception. Si bien puede cumplir con alguna política/regla FXCop haciendo eso, en realidad todavía está atrapando System.Exception.

Para su política de excepción, comenzaría por preguntar esto: "Si no supiera con qué esta API realmente habló, ¿qué tipo de excepción esperaría obtener de vuelta?" Y recuerde que un método es una solicitud a un objeto para hacer algo, y una excepción es la forma en que el objeto le informa que no pudo, y por qué.

0

Si crea un tipo de excepción único para usar en su API, su significado será impreciso para las aplicaciones cliente que se encuentren con ese tipo de excepción. En su lugar, considere crear una jerarquía de clase de excepciones para su API.

Para ello, en primer lugar definir un tipo de excepción abstracta de base:

CustomException 

... y luego derivan tipos de excepciones más específicas de la misma. Por ejemplo:

CustomFooException 
CustomBarException 
CustomFizException 
CustomFuzException 

La base abstracta tipo CustomException no sean lanzados directamente desde su API. Sin embargo, un cliente de su API puede detectar el tipo de excepción base CustomException si no le importa qué excepción derivada específica fue lanzada desde su API.

Para más información sobre la idea de desarrollar una jerarquía de clases de excepción, consulte this answer y otras respuestas a esta pregunta: Why create custom exceptions in .NET?

Véase también this answer que introduce la idea de hacer la clase base abstracta de la jerarquía de excepciones.

Cuestiones relacionadas