Lo mantengo simple.
Una biblioteca tiene un tipo de excepción base extendido desde std ::: runtime_error (que es de C ++ se aplica según corresponda a otros lenguajes). Esta excepción toma una cadena de mensaje para que podamos iniciar sesión; cada punto de lanzamiento tiene un mensaje único (generalmente con una ID única).
Eso es todo.
Nota 1 : En las situaciones en las que alguien que atrapa la excepción puede arreglar las excepciones y reiniciar la acción. Agregaré excepciones derivadas para cosas que se pueden arreglar de manera única y única en una ubicación remota. Pero esto es muy muy raro (recuerde que es poco probable que el receptor esté cerca del punto de lanzamiento, por lo que solucionar el problema será difícil (pero todo depende de la situación)).
Nota 2 : a veces la biblioteca es tan simple que no vale la pena darle su propia excepción y std :: runtime_error funcionará. Solo es importante tener una excepción si la capacidad de distinguirlo de std :: runtime_error puede proporcionar al usuario suficiente información para hacer algo con él.
Nota 3 : Dentro de una clase, generalmente prefiero códigos de error (pero estos nunca escaparán a través de la API pública de mi clase).
Mirando sus compensaciones:
Las compensaciones que veo incluyen:
Más clases de excepción pueden permitir niveles muy finos de manejo de errores para usuarios de API (propensos a errores de configuración o datos de usuario, o archivos no encontrados)
¿Más excepciones realmente te dan un control de grano más fino? La pregunta es si el código de captura realmente puede corregir el error en función de la excepción. Estoy seguro de que hay situaciones como esa y en estos casos debería tener otra excepción. Pero todas las excepciones que ha enumerado anteriormente, la única corrección útil es generar una gran advertencia y detener la aplicación.
Más clases de excepción permiten incrustar información específica de error en la excepción, en lugar de solo un mensaje de cadena o código de error
Esta es una gran razón para usar excepciones. Pero la información debe ser útil para la persona que la está almacenando en caché. ¿Pueden usar la información para realizar alguna acción correctiva? Si el objeto es interno a su biblioteca y no se puede utilizar para influir en ninguna de las API, entonces la información es inútil. Debes ser muy específico para que la información que se arroje tenga un valor útil para la persona que puede atraparla. La persona que lo atrapa generalmente está fuera de su API pública, por lo tanto, adapte su información para que pueda usarse con cosas en su API pública.
Si todo lo que pueden hacer es registrar la excepción, entonces es mejor simplemente lanzar un mensaje de error en lugar de muchos datos. Como el receptor generalmente generará un mensaje de error con los datos. Si crea el mensaje de error, entonces será coherente en todos los receptores, si permite que el receptor construya el mensaje de error, podría obtener el mismo error informado de manera diferente dependiendo de quién llama y captura.
Menos excepciones, pero incrustando un código de error que puede usarse como una búsqueda
Debe determinar el clima, el código de error se puede utilizar de manera significativa. Si puede, entonces debería tener su propia excepción. De lo contrario, sus usuarios ahora deben implementar sentencias de cambio dentro de allí catch (que anula el punto de tener que catch maneje automáticamente las cosas).
Si no puede, ¿por qué no utilizar un mensaje de error en la excepción (no es necesario dividir el código y el mensaje hace que sea difícil buscarlo).
Devolver códigos de error y marcas directamente desde funciones (a veces no es posible desde subprocesos)
Devolver códigos de error es excelente internamente. Le permite corregir errores allí y luego, y debe asegurarse de corregir todos los códigos de error y tenerlos en cuenta. Pero filtrarlos en su API pública es una mala idea. El problema es que los programadores a menudo se olvidan de verificar los estados de error (al menos con una excepción, un error no verificado forzará a la aplicación a cerrar un error no manejado y, por lo general, corromperá todos sus datos).
Implementado un evento o sistema de devolución de llamada en caso de error (evita el desbobinado de la pila)
Este método a menudo se usa junto con otro mecanismo de manejo de errores (no como alternativa). Piensa en tu programa de Windows. Un usuario inicia una acción seleccionando un elemento del menú. Esto genera una acción en la cola de eventos. La cola de eventos eventualmente asigna un hilo para manejar la acción. Se supone que el subproceso maneja la acción y, finalmente, regresa al grupo de subprocesos y espera otra tarea. Aquí una excepción debe ser atrapada en la base por el hilo encargado del trabajo. El resultado de detectar la excepción generalmente generará un evento para el bucle principal que eventualmente generará un mensaje de error para el usuario.
Pero a menos que pueda continuar ante la excepción, la pila se va a desenrollar (al menos para el hilo).