¿Cuándo lanzar una excepción?


Tengo excepciones creadas para cada condición que mi aplicación no espera. UserNameNotValidException, PasswordNotCorrectException etc.

Sin embargo, me dijeron que no debía crear excepciones para esas condiciones. En mi UML esas SON excepciones al flujo principal, así que ¿por qué no debería ser una excepción?

¿Alguna orientación o mejores prácticas para crear excepciones?

Author: Kwan Cheng, 2008-09-17

30 answers

Mi pauta personal es: se lanza una excepción cuando se encuentra que una suposición fundamental del bloque de código actual es falsa.

Ejemplo 1: digamos que tengo una función que se supone que examina una clase arbitraria y devuelve true si esa clase hereda de List. Esta función hace la pregunta: "¿Es este objeto un descendiente de List?"Esta función nunca debe lanzar una excepción, porque no hay áreas grises en su operación-cada clase individual hereda o no hereda de la lista, por lo que la respuesta es siempre "sí" o "no".

Ejemplo 2: digamos que tengo otra función que examina una Lista y devuelve true si su longitud es más de 50, y false si la longitud es menor. Esta función hace la pregunta, " ¿Esta lista tiene más de 50 elementos?"Pero esta pregunta hace una suposición-asume que el objeto que se le da es una lista. Si le doy un NULL, entonces esa suposición es falsa. En ese caso, si la función devuelve true o falso, entonces está rompiendo sus propias reglas. La función no puede devolver nada y afirmar que respondió a la pregunta correctamente. Así que no regresa - lanza una excepción.

Esto es comparable a la falacia lógica "pregunta cargada". Cada función hace una pregunta. Si la entrada que se da hace que la pregunta sea una falacia, entonces lanza una excepción. Esta línea es más difícil de dibujar con funciones que devuelven void, pero la conclusión es: si las suposiciones de la función acerca de sus entradas se violan, debe lanzar una excepción en lugar de regresar normalmente.

El otro lado de esta ecuación es: si encuentra que sus funciones lanzan excepciones con frecuencia, entonces probablemente necesite refinar sus suposiciones.

 548
Author: The Digital Gabeg,
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
2008-11-06 21:55:18

Porque son cosas que sucederán normalmente. Las excepciones no son mecanismos de control de flujo. Los usuarios a menudo obtienen contraseñas incorrectas, no es un caso excepcional. Las excepciones deben ser algo verdaderamente raro, UserHasDiedAtKeyboard tipo situaciones.

 275
Author: blowdart,
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
2015-07-19 11:24:39

Mis pequeñas directrices están fuertemente influenciadas por el gran libro "Code complete":

  • Use excepciones para notificar sobre cosas que no deben ser ignoradas.
  • No use excepciones si el error se puede manejar localmente
  • Asegúrese de que las excepciones estén al mismo nivel de abstracción que el resto de su rutina.
  • Las excepciones deben reservarse para lo que es verdaderamente excepcional.
 55
Author: Commander Keen,
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-11-19 18:43:08

NO es una excepción si el nombre de usuario no es válido o la contraseña no es correcta. Esas son cosas que usted debe esperar en el flujo normal de la operación. Las excepciones son cosas que no forman parte de la operación normal del programa y son bastante raras.

EDIT: No me gusta usar excepciones porque no se puede saber si un método lanza una excepción con solo mirar la llamada. Es por eso que las excepciones solo deben usarse si no puede manejar la situación de una manera decente (piense " fuera de memoria " o "la computadora está en llamas").

 34
Author: EricSchaefer,
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
2008-09-17 13:09:38

Una regla general es usar excepciones en el caso de algo que normalmente no se puede predecir. Algunos ejemplos son la conectividad de la base de datos, el archivo que falta en el disco, etc. Para los escenarios que puede predecir, es decir, los usuarios que intentan iniciar sesión con una contraseña incorrecta, debe usar funciones que devuelvan booleanos y sepan cómo manejar la situación con gracia. No quieres terminar abruptamente la ejecución lanzando una excepción solo porque alguien escribió mal su contraseña.

 24
Author: japollock,
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
2008-09-16 21:13:19

Otros proponen que no se utilicen excepciones porque el mal inicio de sesión es de esperar en un flujo normal si el usuario escribe mal. No estoy de acuerdo y no entiendo el razonamiento. Compáralo con abrir un archivo.. si el archivo no existe o no está disponible por alguna razón, el framework lanzará una excepción. Usar la lógica anterior fue un error de Microsoft. Deberían haber devuelto un código de error. Lo mismo para el análisis, webrequests, etc., sucesivamente..

No considero una mal inicio de sesión parte de un flujo normal, es excepcional. Normalmente el usuario escribe la contraseña correcta, y el archivo existe. Los casos excepcionales son excepcionales y está perfectamente bien usar excepciones para ellos. Complicar su código propagando valores de retorno a través de n niveles en la pila es un desperdicio de energía y resultará en un código desordenado. Haz lo más simple que pueda funcionar. No optimices prematuramente usando códigos de error, cosas excepcionales por definición rara vez ocurren, y las excepciones no cuestan nada a menos que las tires.

 22
Author: Bjorn Reppen,
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
2008-09-16 21:39:01

Las excepciones son un efecto algo costoso, si por ejemplo tiene un usuario que proporciona una contraseña no válida, normalmente es una mejor idea devolver una bandera de error, o algún otro indicador de que no es válida.

Esto se debe a la forma en que se manejan las excepciones, la verdadera entrada incorrecta y los elementos de parada crítica únicos deben ser excepciones, pero no información de inicio de sesión fallida.

 15
Author: Mitchel Sellers,
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
2008-09-16 21:11:17

Creo que solo deberías hacer una excepción cuando no hay nada que puedas hacer para salir de tu estado actual. Por ejemplo, si está asignando memoria y no hay ninguna que asignar. En los casos que mencione, puede recuperarse claramente de esos estados y puede devolver un código de error a su persona que llama en consecuencia.


Verá un montón de consejos, incluso en las respuestas a esta pregunta, que debe lanzar excepciones solo en circunstancias "excepcionales". Eso parece superficialmente razonable, pero es un consejo defectuoso, porque reemplaza una pregunta ("cuándo debo lanzar una excepción") con otra pregunta subjetiva ("qué es excepcional"). En su lugar, siga los consejos de Herb Sutter (para C++, disponible en el artículo del Dr. Dobbs Cuándo y Cómo usar excepciones, y también en su libro con Andrei Alexandrescu, C++ Coding Standards ): lanzar una excepción si, y solo si

  • no se cumple una condición previa (lo que típicamente hace uno de los siguientes imposible) o
  • la alternativa no cumpliría una condición posterior o
  • la alternativa no mantendría un invariante.

¿Por qué es esto mejor? ¿No reemplaza la pregunta con varias preguntas sobre precondiciones, postcondiciones e invariantes? Esto es mejor por varias razones relacionadas.

  • Las precondiciones, postcondiciones e invariantes son diseño características de nuestro programa (su interno API), mientras que la decisión de throw es un detalle de implementación. Nos obliga a tener en cuenta que debemos considerar el diseño y su implementación por separado, y nuestro trabajo al implementar un método es producir algo que satisfaga las restricciones de diseño.
  • Nos obliga a pensar en términos de precondiciones, postcondiciones e invariantes, que son las solo suposiciones que los llamantes de nuestro método deben hacer, y se expresan con precisión, lo que permite el acoplamiento suelto entre los componentes de nuestro programa.
  • Ese acoplamiento suelto nos permite refactorizar la implementación, si es necesario.
  • Las post-condiciones e invariantes son comprobables; resulta en código que puede ser fácilmente probado unitariamente, porque las post-condiciones son predicados que nuestro código de prueba unitaria puede verificar (assert).
  • Pensar en términos de post-condiciones produce naturalmente un diseño que tiene éxito como post-condición, que es el estilo natural para usar excepciones. El la ruta de ejecución normal ("feliz") de su programa se presenta linealmente, con todo el código de manejo de errores movido a las cláusulas catch.
 13
Author: Raedwald,
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
2018-08-01 11:58:06

Yo diría que no hay reglas estrictas sobre cuándo usar excepciones. Sin embargo, hay buenas razones para usarlos o no usarlos:

Razones para usar excepciones:

  • El flujo de código para el caso común es más claro
  • Puede devolver información de error compleja como un objeto (aunque esto también se puede lograr usando el parámetro error "out" pasado por referencia)
  • Los idiomas generalmente proporcionan alguna facilidad para administrar la limpieza ordenada en el caso de la excepción (try / finally en Java, usando en C#, RAII en C++)
  • En el caso de que no se lance ninguna excepción, la ejecución puede a veces ser más rápida que verificar los códigos de retorno
  • En Java, las excepciones verificadas deben declararse o capturarse (aunque esto puede ser una razón en contra)

Razones para no utilizar excepciones:

  • A veces es excesivo si el manejo de errores es simple
  • Si las excepciones no están documentadas o declaradas, pueden ser no capturadas llamando al código, que puede ser peor que si el código de llamada simplemente ignoró un código de retorno (salida de la aplicación vs falla silenciosa - que es peor puede depender del escenario)
  • En C++, el código que usa excepciones debe ser seguro para excepciones (incluso si no las lanza o atrapa, pero llama a una función de lanzamiento indirectamente)
  • En C++, es difícil saber cuándo puede lanzar una función, por lo tanto, debe estar paranoico sobre la seguridad de las excepciones si las usa
  • Lanzar y atrapar excepciones es generalmente significativamente más caro en comparación con la comprobación de un indicador de retorno

En general, estaría más inclinado a usar excepciones en Java que en C++ o C#, porque soy de la opinión de que una excepción, declarada o no, es fundamentalmente parte de la interfaz formal de una función, ya que cambiar su garantía de excepción puede romper el código de llamada. La mayor ventaja de usarlos en Java IMO, es que sabes que tu llamante DEBE manejar la excepción, y esto mejora la posibilidad de comportamiento correcto.

Debido a esto, en cualquier idioma, siempre derivaría todas las excepciones en una capa de código o API de una clase común, de modo que llamar al código siempre puede garantizar capturar todas las excepciones. También consideraría malo lanzar clases de excepción que son específicas de la implementación, al escribir una API o biblioteca (es decir, ajustar excepciones de capas inferiores para que la excepción que recibe su llamante sea comprensible en el contexto de su interfaz).

Nota que Java hace la distinción entre excepciones generales y de tiempo de ejecución en el sentido de que estas últimas no necesitan ser declaradas. Solo usaría clases de excepción en tiempo de ejecución cuando sepa que el error es el resultado de un error en el programa.

 10
Author: Robert,
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
2008-09-16 23:28:50

Las clases de excepción son como las clases "normales". Se crea una nueva clase cuando "es" un tipo diferente de objeto, con diferentes campos y diferentes operaciones.

Como regla general, debe intentar equilibrar el número de excepciones y la granularidad de las excepciones. Si su método lanza más de 4-5 excepciones diferentes, probablemente puede combinar algunas de ellas en excepciones más "generales", (por ejemplo, en su caso "AuthenticationFailedException"), y usando la excepción mensaje para detallar lo que salió mal. A menos que su código maneje cada una de ellas de manera diferente, no necesita crear muchas clases de excepción. Y si lo hace, debería devolver una enumeración con el error que ocurrió. Está un poco más limpio así.

 5
Author: Shachar,
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
2008-09-16 21:14:00

Si es código que se ejecuta dentro de un bucle que probablemente causará una excepción una y otra vez, entonces lanzar excepciones no es una buena cosa, porque son bastante lentas para N grande.Pero no hay nada malo en lanzar excepciones personalizadas si el rendimiento no es un problema. Solo asegúrese de que tiene una excepción base que todos heredan, llamada excepción base o algo por el estilo. BaseException hereda el sistema.Exception, pero todas tus excepciones heredan BaseException. Usted puede incluso tener un árbol de tipos de Excepción para agrupar tipos similares, pero esto puede o no ser excesivo.

Por lo tanto, la respuesta corta es que si no causa una penalización de rendimiento significativa (que no debería a menos que esté lanzando muchas excepciones), entonces adelante.

 5
Author: Charles Graham,
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
2008-09-16 21:19:22

Estoy de acuerdo con japollock hasta allí throw lanzar una aceptación cuando no está seguro sobre el resultado de una operación. Llamadas a APIs, acceso a sistemas de archivos, llamadas a bases de datos, etc. Cada vez que se está moviendo más allá de los" límites " de sus lenguajes de programación.

Me gustaría añadir, siéntase libre de lanzar una excepción estándar. A menos que vaya a hacer algo "diferente" (ignorar, correo electrónico, registro, mostrar esa cosa de la imagen de la ballena de Twitter, etc.), entonces no se moleste con excepciones personalizadas.

 3
Author: dclaysmith,
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
2008-09-17 00:01:15

La regla general para lanzar excepciones es bastante simple. lo hace cuando su código ha entrado en un estado NO VÁLIDO IRRECUPERABLE. si los datos se ven comprometidos o no puede cancelar el procesamiento que se produjo hasta el momento, debe cancelarlo. de hecho, ¿qué más puedes hacer? su lógica de procesamiento eventualmente fallará en otro lugar. si usted puede recuperarse de alguna manera entonces hacer eso y no lanzar excepción.

En su caso particular si se vio obligado a hacer algo tonto como aceptar el retiro de dinero y solo entonces comprobar usuario / pasword debe terminar el proceso lanzando una excepción para notificar que algo malo ha sucedido y evitar más daños.

 3
Author: goran,
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-12-19 11:22:35

En general, desea lanzar una excepción para cualquier cosa que pueda suceder en su aplicación que sea "Excepcional"

En su ejemplo, ambas excepciones parecen que las está llamando a través de una validación de contraseña / nombre de usuario. En ese caso, se puede argumentar que no es realmente excepcional que alguien escriba mal un nombre de usuario / contraseña.

Son "excepciones" al flujo principal de su UML pero son más "ramas" en el procesamiento.

Si ha intentado acceder su archivo passwd o base de datos y no podría, eso sería un caso excepcional y justificaría lanzar una excepción.

 2
Author: Gord,
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
2008-09-16 21:17:03

En primer lugar, si los usuarios de tu API no están interesados en fallas específicas y de grano fino, entonces tener excepciones específicas para ellos no tiene ningún valor.

Dado que a menudo no es posible saber qué puede ser útil para sus usuarios, un mejor enfoque es tener las excepciones específicas, pero asegurarse de que hereden de una clase común (por ejemplo, std::exception o sus derivados en C++). Eso le permite a su cliente detectar excepciones específicas si así lo desea, o la excepción más general si no me importa.

 2
Author: Jason Etheridge,
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
2008-09-16 21:17:41

Las excepciones están destinadas a eventos que son comportamientos anormales, errores, fallas, etc. Comportamiento funcional, error del usuario, etc., debe ser manejado por la lógica del programa en su lugar. Dado que una cuenta o contraseña incorrecta es una parte esperada del flujo lógico en una rutina de inicio de sesión, debería ser capaz de manejar esas situaciones sin excepciones.

 2
Author: Joe Skora,
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
2008-09-16 22:02:53

Tengo problemas filosóficos con el uso de excepciones. Básicamente, usted está esperando que ocurra un escenario específico, pero en lugar de manejarlo explícitamente, está empujando el problema para que se maneje "en otro lugar."Y dónde está ese" otro lugar " puede ser una suposición de cualquiera.

 2
Author: Dan,
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
2008-09-17 18:43:45

Yo diría que generalmente todo fundamentalismo conduce al infierno.

Ciertamente no querrá terminar con un flujo impulsado por excepciones, pero evitar excepciones por completo también es una mala idea. Hay que encontrar un equilibrio entre ambos enfoques. Lo que no haría es crear un tipo de excepción para cada situación excepcional. Eso no es productivo.

Lo que generalmente prefiero es crear dos tipos básicos de excepciones que se utilizan en todo el sistema: Excepción lógica y Excepción técnica. Estos pueden distinguirse por subtipos si es necesario, pero generalmente no es necesario.

La excepción técnica denota la excepción realmente inesperada, como que el servidor de la base de datos no funciona, la conexión al servicio web lanzó la IOException y así sucesivamente.

Por otro lado, las excepciones lógicas se utilizan para propagar la situación errónea menos grave a las capas superiores (generalmente alguna validación resultado).

Tenga en cuenta que incluso la excepción lógica no está destinada a ser utilizada regularmente para controlar el flujo del programa, sino más bien para resaltar la situación en la que el flujo realmente debería terminar. Cuando se usa en Java, ambos tipos de excepción son subclases RuntimeException y el manejo de errores está altamente orientado a aspectos.

Por lo tanto, en el ejemplo de inicio de sesión, podría ser aconsejable crear algo como AuthenticationException y distinguir las situaciones concretas por valores de enumeración como UsernameNotExisting, PasswordMismatch etc. Entonces usted no va a terminar en tener una gran jerarquía de excepciones y puede mantener los bloques de captura en nivel mantenible. También puede emplear fácilmente algún mecanismo genérico de manejo de excepciones, ya que tiene las excepciones categorizadas y sabe bastante bien qué propagar al usuario y cómo.

Nuestro uso típico es lanzar la LogicalException durante la llamada al Servicio Web cuando la entrada del usuario no era válida. La Excepción obtiene marshalled al detalle SoapFault y luego se vuelve a desmalled a la excepción en el cliente, lo que resulta en mostrar el error de validación en un campo de entrada de página web determinado, ya que la excepción tiene una asignación adecuada a ese campo.

Esta no es ciertamente la única situación: no es necesario golpear el servicio web para lanzar la excepción. Usted es libre de hacerlo en cualquier situación excepcional ( como en el caso de que necesite fallar-rápido) - es todo a su discreción.

 2
Author: Petr Macek,
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-09-30 01:44:05

La razón principal para evitar lanzar una excepción es que hay una gran cantidad de sobrecarga involucrada con lanzar una excepción.

Una cosa que el artículo siguiente establece es que una excepción es para condiciones y errores excepcionales.

Un nombre de usuario incorrecto no es necesariamente un error de programa, sino un error de usuario...

Aquí hay un punto de partida decente para las excepciones dentro de. NET: http://msdn.microsoft.com/en-us/library/ms229030 (VS.80).aspx

 1
Author: Sam,
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
2008-09-16 21:14:43

Lanzar excepciones hace que la pila se desenrolle, lo que tiene algunos impactos en el rendimiento (se admite que los entornos administrados modernos han mejorado en eso). Todavía lanzar y atrapar excepciones repetidamente en una situación anidada sería una mala idea.

Probablemente más importante que eso, las excepciones están destinadas a condiciones excepcionales. No deben usarse para el flujo de control ordinario, porque esto dañará la legibilidad de su código.

 1
Author: Arno,
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
2008-09-16 21:21:14

Tengo tres tipos de condiciones que cojo.

  1. La entrada incorrecta o faltante no debe ser una excepción. Utilice tanto la expresión regular js del lado del cliente como la del lado del servidor para detectar, establecer atributos y reenviar a la misma página con los mensajes.

  2. La AppException. Por lo general, esta es una excepción que detecta y agrega en su código. En otras palabras, estos son los que usted espera (el archivo no existe). Registrarlo, establecer el mensaje, y reenviar de nuevo al error general pagina. Esta página generalmente tiene un poco de información sobre lo que sucedió.

  3. La Excepción inesperada. Estos son los que no conoces. Regístrelo con los detalles y reenviarlos a una página de error general.

Espero que esto ayude

 1
Author: Michael,
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
2008-09-16 21:54:36

La seguridad se combina con su ejemplo: No debe decirle a un atacante que existe un nombre de usuario, pero la contraseña es incorrecta. Esa es información adicional que no necesitas compartir. Simplemente diga " el nombre de usuario o contraseña es incorrecto."

 1
Author: anon,
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
2008-09-16 23:10:36

La respuesta simple es, siempre que una operación es imposible (debido a la aplicación O porque violaría la lógica de negocio). Si se invoca un método y es imposible hacer lo que el método fue escrito para hacer, lanzar una excepción. Un buen ejemplo es que los constructores siempre lanzan ArgumentExceptions si una instancia no se puede crear usando los parámetros suministrados. Otro ejemplo es InvalidOperationException, que se lanza cuando una operación no se puede realizar debido al estado de otro miembro o miembros de la clase.

En su caso, si se invoca un método como Login(nombre de usuario, contraseña), si el nombre de usuario no es válido, de hecho es correcto lanzar un UserNameNotValidException, o PasswordNotCorrectException si la contraseña es incorrecta. El usuario no puede iniciar sesión usando los parámetros suministrados(es decir, es imposible porque violaría la autenticación), así que lanza una excepción. Aunque podría tener sus dos excepciones heredar de ArgumentException.

Dicho esto, si desea NO lanzar una excepción porque un error de inicio de sesión puede ser muy común, una estrategia es crear un método que devuelva tipos que representan diferentes errores. He aquí un ejemplo:

{ // class
    ...

    public LoginResult Login(string user, string password)
    {
        if (IsInvalidUser(user))
        {
            return new UserInvalidLoginResult(user);
        }
        else if (IsInvalidPassword(user, password))
        {
            return new PasswordInvalidLoginResult(user, password);
        }
        else
        {
            return new SuccessfulLoginResult();
        }
    }

    ...
}

public abstract class LoginResult
{
    public readonly string Message;

    protected LoginResult(string message)
    {
        this.Message = message;
    }
}

public class SuccessfulLoginResult : LoginResult
{
    public SucccessfulLogin(string user)
        : base(string.Format("Login for user '{0}' was successful.", user))
    { }
}

public class UserInvalidLoginResult : LoginResult
{
    public UserInvalidLoginResult(string user)
        : base(string.Format("The username '{0}' is invalid.", user))
    { }
}

public class PasswordInvalidLoginResult : LoginResult
{
    public PasswordInvalidLoginResult(string password, string user)
        : base(string.Format("The password '{0}' for username '{0}' is invalid.", password, user))
    { }
}

A la mayoría de los desarrolladores se les enseña a evitar Excepciones debido a la sobrecarga causada por lanzarlas. Es genial ser consciente de los recursos, pero generalmente no a expensas del diseño de su aplicación. Esa es probablemente la razón por la que se le dijo no tirar sus dos excepciones. Si usar excepciones o no generalmente se reduce a la frecuencia con la que se producirá la excepción. Si es un resultado bastante común o bastante esperable, es cuando la mayoría de los desarrolladores evitarán Excepciones y en su lugar crearán otro método para indicar un error, debido al supuesto consumo de recursos.

Aquí hay un ejemplo de cómo evitar el uso de excepciones en un escenario como el descrito anteriormente, usando el patrón Try ():

public class ValidatedLogin
{
    public readonly string User;
    public readonly string Password;

    public ValidatedLogin(string user, string password)
    {
        if (IsInvalidUser(user))
        {
            throw new UserInvalidException(user);
        }
        else if (IsInvalidPassword(user, password))
        {
            throw new PasswordInvalidException(password);
        }

        this.User = user;
        this.Password = password;
    }

    public static bool TryCreate(string user, string password, out ValidatedLogin validatedLogin)
    {
        if (IsInvalidUser(user) || 
            IsInvalidPassword(user, password))
        {
            return false;
        }

        validatedLogin = new ValidatedLogin(user, password);

        return true;
    }
}
 1
Author: Chris,
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
2008-09-17 05:24:54

En mi opinión, la pregunta fundamental debería ser si uno esperaría que la persona que llama quisiera continuar el flujo normal del programa si ocurre una condición. Si no lo sabe, tenga métodos doSomething y trySomething separados, donde el primero devuelve un error y el segundo no, o tenga una rutina que acepte un parámetro para indicar si se debe lanzar una excepción si falla). Considere una clase para enviar comandos a un sistema remoto y reportar respuestas. Cierto los comandos (por ejemplo, reiniciar) harán que el sistema remoto envíe una respuesta pero luego no responda durante un cierto período de tiempo. Por lo tanto, es útil poder enviar un comando "ping" y averiguar si el sistema remoto responde en un período de tiempo razonable sin tener que lanzar una excepción si no lo hace (la persona que llama probablemente esperaría que los primeros intentos de "ping" fallaran, pero uno finalmente funcionaría). Por otro lado, si uno tiene una secuencia de comandos como:

  exchange_command("open tempfile");
  exchange_command("write tempfile data {whatever}");
  exchange_command("write tempfile data {whatever}");
  exchange_command("write tempfile data {whatever}");
  exchange_command("write tempfile data {whatever}");
  exchange_command("close tempfile");
  exchange_command("copy tempfile to realfile");

Uno querría que el fallo de cualquier operación abortara toda la secuencia. Si bien se puede verificar cada operación para asegurarse de que tenga éxito, es más útil que la rutina exchange_command() lance una excepción si un comando falla.

En realidad, en el escenario anterior puede ser útil tener un parámetro para seleccionar una serie de modos de manejo de errores: nunca lanzar excepciones, lanzar excepciones solo para errores de comunicación, o lanzar excepciones en cualquier caso en que un comando no devuelve una indicación de "éxito".

 1
Author: supercat,
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
2010-06-24 16:45:18

Para mí, la excepción debe lanzarse cuando falla una regla técnica o de negocios requerida. por ejemplo, si una entidad de automóvil está asociada con una matriz de 4 neumáticos ... si un neumático o más son nulos ... una excepción debe ser disparada "NotEnoughTiresException", porque se puede capturar en diferentes niveles del sistema y tener un significado significativo a través del registro. además si sólo tratamos de controlar el flujo de null y evitar la instanciación del coche . puede que nunca nunca encontremos la fuente del problema , porque el neumático no se supone que sea nulo en primer lugar .

 1
Author: Genjuro,
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-10-06 15:32:51

Puede usar excepciones un poco genéricas para esas condiciones. Por ejemplo, ArgumentException está destinado a ser utilizado cuando algo sale mal con los parámetros de un método (con la excepción de ArgumentNullException). En general, no necesitaría excepciones como LessThanZeroException, NotPrimeNumberException, etc. Piensa en el usuario de tu método. El número de las condiciones que querrá manejar específicamente es igual al número del tipo de excepciones que su método necesita lanzar. De esta manera, puede determinar qué excepciones detalladas tendrá.

Por cierto, siempre intente proporcionar algunas formas para que los usuarios de sus bibliotecas eviten excepciones. TryParse es un buen ejemplo, existe para que no tengas que usar int.Analiza y atrapa una excepción. En su caso, es posible que desee proporcionar algunos métodos para verificar si el nombre de usuario es válido o la contraseña es correcta para que sus usuarios (o usted) no tengan que hacer mucho manejo de excepciones. Esto se espera que resulte en más código readble y mejor rendimiento.

 0
Author: Serhat Ozgel,
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
2008-09-16 21:19:53

En última instancia, la decisión se reduce a si es más útil lidiar con errores a nivel de aplicación como este utilizando el manejo de excepciones, o a través de su propio mecanismo de lanzamiento en casa como devolver códigos de estado. No creo que haya una regla dura y rápida sobre cuál es mejor, pero consideraría:

  • ¿Quién está llamando a tu código? ¿Es una API pública de algún tipo o una biblioteca interna?
  • ¿Qué idioma estás usando? Si es Java, por ejemplo, a continuación, lanzar un (comprobado) exception pone una carga explícita en su llamador para manejar esta condición de error de alguna manera, en lugar de un estado de retorno que podría ser ignorado. Eso podría ser bueno o malo.
  • ¿Cómo se manejan otras condiciones de error en la misma aplicación? Las personas que llaman no querrán tratar con un módulo que maneja los errores de una manera idiosincrática a diferencia de cualquier otra cosa en el sistema.
  • ¿Cuántas cosas pueden salir mal con la rutina en cuestión, y cómo se manejarían de manera diferente? Considere la diferencia entre una serie de bloques catch que manejan diferentes errores y un interruptor en un código de error.
  • ¿Tiene información estructurada sobre el error que necesita devolver? Lanzar una excepción le da un mejor lugar para poner esta información que simplemente devolver un estado.
 0
Author: eli,
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
2008-09-16 21:26:25

Hay dos clases principales de excepción:

1) Excepción del sistema (por ejemplo, conexión a la base de datos perdida) o 2) Excepción de usuario. (por ejemplo, validación de entrada de usuario, 'la contraseña es incorrecta')

Me pareció útil crear mi propia Clase de Excepción de Usuario y cuando quiero lanzar un error de usuario quiero ser manejado de manera diferente (es decir, error de recursos que se muestra al usuario), entonces todo lo que necesito hacer en mi controlador de errores principal es verificar el tipo de objeto:

            If TypeName(ex) = "UserException" Then
               Display(ex.message)
            Else
               DisplayError("An unexpected error has occured, contact your help  desk")                   
               LogError(ex)
            End If
 0
Author: Crusty,
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
2008-09-17 01:28:33

Algunas cosas útiles en las que pensar al decidir si una excepción es apropiada:

  1. Qué nivel de código desea que se ejecute después de que ocurra la excepción candidata, es decir, cuántas capas de la pila de llamadas deben relajarse. Por lo general, desea manejar una excepción lo más cerca posible de donde ocurre. Para la validación de nombre de usuario/contraseña, normalmente manejaría los errores en el mismo bloque de código, en lugar de dejar que una excepción aparezca. Así que una excepción es probablemente no sea apropiado. (OTOH, después de tres intentos fallidos de inicio de sesión, el flujo de control puede cambiar a otro lugar, y una excepción puede ser apropiada aquí.)

  2. ¿Este evento es algo que le gustaría ver en un registro de errores? No todas las excepciones se escriben en un registro de errores, pero es útil preguntar si esta entrada en un registro de errores sería útil, es decir, trataría de hacer algo al respecto, o sería la basura que ignoraría.

 0
Author: Mike Kantor,
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
2008-09-17 02:10:20

"PasswordNotCorrectException" no es un buen ejemplo para usar excepciones. Es de esperar que los usuarios obtengan sus contraseñas incorrectas, por lo que no es una excepción en mi humilde opinión. Probablemente incluso se recupere de él, mostrando un mensaje de error agradable, por lo que es solo una comprobación de validez.

Las excepciones no controladas detendrán la ejecución eventualmente, lo cual es bueno. Si está devolviendo códigos falsos, nulos o de error, tendrá que lidiar con el estado del programa por sí mismo. Si se olvida de comprobar las condiciones en algún lugar, su programa puede seguir funcionando con datos incorrectos, y puede que tenga dificultades para averiguar qué sucedió y dónde.

Por supuesto, podría causar el mismo problema con las sentencias catch vacías, pero al menos detectar esas es más fácil y no requiere que entienda la lógica.

Así que como regla general:

Úsalos donde no quieras o simplemente no puedas recuperarte de un error.

 0
Author: DanMan,
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-12-10 11:53:34