2010-03-25 17 views
17
// 
// To Throw 
void PrintType(object obj) 
{ 
    if(obj == null) 
    { 
     throw new ArgumentNullException("obj") 
    } 
    Console.WriteLine(obj.GetType().Name);  
} 

// 
// Not to Throw 
void PrintType(object obj) 
{ 
    if(obj != null) 
    { 
     Console.WriteLine(obj.GetType().Name); 
    } 
} 

¿Qué principio mantener?Para tirar o no tirar

personalmente prefiero la primera uno su ejemplo amistoso con el desarrollador (notificado sobre cada una "anomalía"). El segundo es decir fácil de usar (deje que el usuario continúe trabajando incluso si "dentro" no todo funciona bien).

Creo que es más complicado encontrar errores y errores en la fase de mantenimiento cuando silenciosamente dejas que las cosas continúen. Si algo sale mal, no se le notificará de inmediato, y algunas veces tendrá errores muy alejados de la causa principal del error, y se perderá mucho tiempo para encontrarlo.

¿Qué opinas?

+1

¿Cómo silenciosamente falla informar un error "fácil de usar"? ¿Qué más está mal que está siendo enmascarado por este enfoque "fácil de usar"? –

+0

@ S.Lott: con "fácil de usar" me refiero a que el usuario primero no verá extraños (para ello) mensajes de excepción, y en segundo lugar permitirá continuar haciendo una acción (incluso incompleta), en lugar de una falla de aplicación o algo similar si las excepciones no se manejan adecuadamente. – serhio

+3

Las excepciones deben ser * excepcionales *. ¿Esto justifica una excepción? No puedo decir, sin saber más acerca de su situación. – Thomi

Respuesta

7

Si el cuerpo del método maneja el obj nulo correctamente (en otras palabras, obj! = Null no es un requisito), entonces no hay necesidad de lanzar una excepción.

En todos los demás casos: Tiro. Deje que el cliente asuma la responsabilidad de su entrada defectuosa.

33

El segundo es letal. Fallar silenciosamente es siempre lo que no debe hacer. Supongamos que este fuera el sistema bancario en el banco que posee su cuenta. ¿Te gustaría si hubiera un problema para pagar tu salario y el sistema lo ignoró silenciosamente?

+6

+1: ¿Cómo es "amigable" pretender que el error no existe? –

+3

Depende de las invariantes de cada función. ¿* * Null * es un valor válido? Es el argumento opcional? Si se trata de un error en la aplicación, el aborto debería ser el camino, si se trata de una rara condición excepcional, entonces es apropiado tirarlo. De lo contrario, si el parámetro es opcional, ignorarlo es apropiado. –

+0

La pregunta parece suponer que la excepción no generará notificación de usuario. Si lo estoy leyendo bien, esa suposición es errónea. – msw

0

Considerar el uso de Null Object pattern es muy útil para no saturar el código con try-catch, comprobaciones nulas (o dios no permita que se cometan errores).

+2

Entonces, en lugar de saturar su código con excepciones, ¿los abarrotamos de abstracciones innecesarias? Los errores son errores, si tiene un conjunto de entradas bien definido y alguien viola ese contrato ... es hora de lanzar. – Nix

+0

@Nix Si es un error, pero muchas veces no lo es. –

3

Throw.

Deje que el llamante de una función determine si es lo suficientemente importante como para lanzar una excepción al usuario en un valor nulo, pero la función en sí debería arrojarse debido al argumento no válido.

0

En este ejemplo particular, no dar nada a una impresora es como decir "imprimir nada", por lo que funciona como debería.

Sé que esto es un ejemplo, pero es solo para aclarar que esto es relativo.

Si su código muestra mensajes fáciles de usar sobre excepciones de alguna manera, ¿qué diferencia hace? el primero sería tanto desarrollador como amigable para el usuario.

1

Yo diría que depende de su preferencia (desarrollador). Desde la perspectiva del usuario, nunca debería ver una excepción no controlada, pero eso no significa que no pueda usar excepciones.

Prefiero la primera, porque creo que null es una construcción totalmente innecesaria (y molesta), así que me esfuerzo por codificar sin ella. Si hay un null en algún lugar, alguien cometió un error, por lo que lo mejor es simplemente irse a pique en lugar de pretender que todo está bien.

Al final depende de lo que usted considera que es la semántica del método. Si se supone que el método acepta nulos, entonces debe elegir la opción número dos. Si se supone que el método solo acepta argumentos reales (que prefiero), entonces debe elegir la opción número uno.

0

Realmente depende de cuáles son sus invariantes. Si el parámetro es optiona, ignorar un parámetro null es correcto, pero si el parámetro es obligatorio, eso ocultará un error en su aplicación. Además, y dependiendo del idioma, si el invariante es suficientemente malo, puede considerar una tercera opción: abortar la aplicación.

Todas las discusiones sobre si se debe utilizar o no excepciones siempre se pueden asignar a la decisión sobre si la situación es excepcional o no, y si es excepcional, tirar o más bien abortar la aplicación depende de si es recuperable o no.

1

Siempre Throw, excepto en código de depuración/diagnóstico. Es muy embarazoso tener una NullPointerException que se produce en el código de producción en un punto donde solo se debe generar un mensaje de depuración, p.

log.debug("id of object is " + obj.getId()) 

donde el registrador está desactivado y obj es nulo.

1

Es muy subjetivo, pero siempre prefiero ignorar los errores no fatales o recuperables. Póngalos en registros, si es necesario, pero si sabe cómo continuar, hágalo.

Tenga en cuenta que cuando digo fatal, en realidad depende de la función en sí. Diga, hay una función API que obtiene ID y un puñado de otros parámetros. Supongamos que esta ID también puede adivinarse a partir de esas otras cosas que se transmiten. La función de la API debería adivinar si puede, pero la función en algún lugar que hace todo el trabajo debería obtener una identificación no nula y arrojar de lo contrario. Porque la función API de alto nivel no es fatal, sabe cómo adivinarla, pero para la función de bajo nivel es fatal, se supone que debe hacer algo con esa ID y con valor nulo no puede continuar.

Todos los errores fatales deben tenerse en cuenta, por supuesto.

+0

esto es más complicado de encontrar errores y errores en la fase de mantenimiento cuando silenciosamente dejas que las cosas continúen. Si algo sale mal, no se le notificará de inmediato, y algunas veces tendrá errores muy alejados de la causa principal del error, y se perderá mucho tiempo para encontrarlo. – serhio

+0

No, realmente no.En primer lugar, en presencia de pruebas, es probable que detecte el error; en segundo lugar, hay funciones de bajo nivel que deberían detectar errores y funciones de alto nivel que deberían evitarlas. – vava

+0

He editado mi publicación para aclarar lo que quise decir con "error fatal". – vava

4

Lanzar una excepción (si nulo es un error) parece mucho mejor que ignorar silenciosamente un error.

hay una tercera opción que puede considerar:

void PrintType(object obj) 
{ 
    Console.WriteLine(obj.GetType().Name); 
} 

Esto también se produce una excepción cuando obj es nula. La ventaja de esto es que implica menos código. La desventaja de este enfoque es que es más difícil determinar si obj puede ser nulo.

+0

tenga en cuenta que en lugar de ArgumentNullException ("obj") puede escribir 'ArgumentNullException (" No se puede imprimir un objeto nulo ")' para ser más explícito. – serhio

0

identificación va a

vacío TipoImpresión (objeto obj) { Console.WriteLine (obj.GetType() Nombre.); }

+0

esto fue un ejemplo. En lugar de ArgumentNullException ("obj") , podría escribir 'ArgumentNullException (" No se puede imprimir un objeto nulo ")' para ser más explícito. – serhio

0

tercera opción, la mitad en pseudocódigo:

// To Throw A Clean Error 
void PrintType(object obj) 
{ 
    if(obj == null) 
    { 
     throw new ArgumentNullException(STANDARD_ERROR_MESSAGE, obj) 
    } 

    Console.WriteLine(obj.GetType().Name);  
} 

puede recogerla todos errores y se envuelven en un solo lugar, por lo que el usuario ve texto estándar:

Ha habido un error. Si persiste este error , póngase en contacto con un administrador .

O agregue algunos errores, todos ellos fáciles de usar, y los mostrará directamente al usuario. "Ha occurido un error de conexión." "Ha ocurrido un error de autenticación". "Ha ocurrido un error del sistema". Y así.

En el back-end, tienen todos los errores y se ha registrado su seguimiento de pila, por lo que puede utilizar la información de depuración de esa manera.

0

Realmente depende de lo que la función está definida para hacer. El aspecto más importante es tener un comportamiento claramente definido y que la función lo implemente correctamente.

Ahora, si la pregunta es si es mejor definir la función para aceptar nulo e imprimirla, o para no aceptarla y lanzar una excepción, diría que la última, porque probablemente sea menos propensa a errores para el usuario para comprobar nulo antes de llamar a la función, si eso es una posibilidad.

+0

al desarrollar su función, no puede estar seguro de si el usuario revisará el objeto o no. Esto es cierto, sin embargo, que a veces ese tipo de verificaciones se realizan en una cadena si obj! Null/si obj! Null/si obj! Null/si obj! Null ... – serhio

1

Si api si está expuesto afuera, siempre haga una comprobación de argumentos y arroje una excepción basada en argumentos para que el usuario de la API pueda obtener el resultado.

Cuestiones relacionadas