2011-01-28 16 views
30

Por lo general, pongo todo de mi código de método principal dentro de un bloque try/catch, así:Código de método principal totalmente dentro de try/catch: ¿es una mala práctica?

public static void Main(string[] args) 
{ 
    try 
    { 
     // code 
    } 
    catch (Exception e) 
    { 
     // code 
    } 
} 

hago esto por si acaso alguna excepción logran deslizarse fuera del resto de la lógica del programa, lo que permite que haga algo al respecto, como mostrarlo a la consola, registrarlo en un archivo, etc. Sin embargo, me han dicho que esto es una mala práctica.

¿Crees que es una mala práctica?

+2

depende de lo que viene como '// code' –

+1

Pregunta relacionada: http: // stackoverflow.com/questions/2730078/in-c-how-do-i-know-which-exceptions-to-catch –

Respuesta

38

Envolver cualquier pieza de código en un bloque try/catch sin una buena razón es una mala práctica.

En el modelo de programación .NET, las excepciones se deben reservar para casos o condiciones verdaderamente excepcionales. Debe solo tratar de detectar excepciones que realmente puede hacer algo acerca de. Además, difícilmente debería tomar la clase base System.Exception (pero preferiría captar las clases de excepciones derivadas más específicas que puede manejar). Y si se produce una excepción verdaderamente inesperada durante el curso de la ejecución de su programa, usted realmente debería bloquearse.

Obviamente, la respuesta "correcta" tendría que hacerse caso por caso, dependiendo de lo que esté sucediendo dentro de ese marcador de posición // code en su bloque catch. Pero si está pidiendo una regla general o una "mejor práctica", siempre debe tener una razón específica para detectar excepciones, no simplemente envolver todo su código en un bloque try/catch gigante como una cuestión de rutina sin pensarlo. .

Tenga en cuenta que si simplemente está tratando de detectar cualquier excepción no controlada que pueda ocurrir con el propósito de registrar o informar errores, debe usar el AppDomain.UnhandledException event. Este es un evento solo de notificación, por lo que no le permite hacer esas excepciones, pero es el lugar correcto para implementar su funcionalidad de registro o informe de errores después de que su aplicación se haya bloqueado.


EDIT: Como estaba poniendo al día en mi lectura del excelente blog de Raymond Chen, "The Old New Thing", me di cuenta de que había publicado recientemente un artículo sobre un tema similar. Es específico de COM, en lugar de .NET Framework, pero los conceptos generales con respecto al manejo de errores son igualmente aplicables a ambos entornos. Pensé en compartir un par de gemas del artículo aquí, en apoyo de mi opinión [aparentemente bastante controvertida].

Históricamente, COM realizó una prueba gigante/excepto alrededor de los métodos de su servidor. Si su servidor encontró lo que normalmente sería una excepción no controlada, el gigante try/except lo detectaría y lo convertiría en el error RPC_E_SERVERFAULT. A continuación, marcó la excepción como manejada, de modo que el servidor permaneció en ejecución, con lo que "mejoró la solidez al mantener el servidor en funcionamiento incluso cuando se encontró con un problema".

Eso sí que fue un flaco servicio.

El hecho de que se haya producido una excepción no controlada significa que el servidor se encontraba en un estado inesperado. Al detectar la excepción y decir "No te preocupes, todo está bien", terminas dejando un servidor dañado funcionando.

[. . . ]

Capturar todas las excepciones y dejar que el proceso continúe ejecutándose supone que un servidor puede recuperarse de una falla inesperada. Pero esto es absurdo. Ya sabes que el servidor está increíblemente bien: ¡se colgó!

Mucho mejor es dejar que el servidor se bloquee para poder capturar el volcado de fallo en el punto de la falla. Ahora tienes una oportunidad de luchar para descubrir qué está pasando.

Puedes [y deberías] leer todo el artículo aquí en su blog: How to turn off the exception handler that COM "helpfully" wraps around your server.

+1

@gridzbi: ¿Está bien? Hazlo en el evento 'AppDomain.UnhandledException'. Para eso está * diseñado *. Envolver tu código en un bloque try/catch es generalmente una idea * mala *, especialmente para algo como esto. Una excepción verdaderamente no controlada de la que no se puede hacer nada ** debe ** causar que su aplicación falle. La tala es una preocupación secundaria, y se ha hecho una provisión para ello. –

+4

Nunca diga "nunca". Hay muchos casos en los que debe atrapar System.Exception. Por ejemplo, si está procesando una llamada a un complemento arbitrario, que puede arrojar algo, pero debe matarlo elegantemente si algo falla. O si está interpretando un código arbitrario introducido por un usuario, que puede arrojar absolutamente cualquier cosa, en este caso debe mostrar un seguimiento de la pila a un usuario y regresar a la réplica. –

+0

@ SK-logic: No estoy familiarizado con las instancias en las que el usuario puede plantear sus propias excepciones. Y sí, supongo que puede haber bibliotecas de terceros que se equivocan y que lanzan 'System.Exception', pero eso no es excusa para tragar * todo * de tu código con un bloque try/catch. Eso sí, el resto de mi respuesta es bastante insoportable sobre tener que decidir esto caso por caso; la forma en que percibo la pregunta original es como una de "mejores prácticas", no "¿está esto alguna vez concebiblemente justificado?" –

6

Si está haciendo lo más inteligente que puede con el error, es una buena práctica. Para eso es para try/catch.

Si solo está tirando el error (o lo está registrando y tirándolo) — especialmente si lo hace independientemente del tipo de excepción — que se considera una mala práctica.

Esto podría plantear la pregunta: ¿y si lo más inteligente es registrarlo y tirarlo? Quiero decir que sería un caso excepcional. Pero en la práctica, mi código afirmaría lo contrario. Supongo que me entrego a mucha mala práctica.

+0

Estoy de acuerdo, excepto que nunca debería atrapar 'System.Exception'. Vería una excepción derivada más específica de la que * podría * posiblemente hacer algo al respecto. –

0

Eso depende de lo que haga si detecta un error. Si acaba de capturar todos los errores aparecen para manejarlos correctamente - mala práctica. Diría que es una mala práctica, incluso si solo inicias sesión allí, registrate localmente.

Si realmente hacer algo para recuperar el error (por ejemplo, se arrojó a sí mismo ya saben qué hacer al respecto) - Votaría OK :)

1

Definitivamente, sí, es una mala práctica, a use Exception class

Debería preocuparse por los tipos de excepción, sin cortar todas las excepciones en catch block, evitando que informen al sistema del error.

La clase de excepción es una clase base, y es una excepción de nivel superior que se puede atrapar en el código. Utilice las Excepciones más específicas en el bloque catch, específicamente, el único que su código genera en un bloque try {...} catch {...}, y solo si puede resolverse efectivamente en ese nivel particular (en un función, donde try ... catch block está declarado)

4

Estoy de acuerdo con el 90% de lo que dice Cody. Hay algunas situaciones similares al ejemplo de complemento donde es posible que desee capturar excepciones del sistema. Aquí hay otro ejemplo, considere consumir un servicio web WCF .

Objetivo: consuma el servicio y deseche incluso si se encuentra un error. Permita que el error burbujee.

public static bool DoRemoteWebServiceWork() 
{ 
    bool result; 
    RemoteWebServiceClient client = new RemoteWebServiceClient(); 
    try 
    { 
     result = client.DoWork(); 
     client.Close(); 
    } 
    catch (Exception) 
    { 
     client.Abort(); //dispose 
     throw;//This service is critical to application function. The application should break if an exception is thrown. 
     //could log end point and binding exceptions to avoid ignoring changes to the remote service that require updates to our code. 
    } 
    return result; 
} 

Meta: consumir el servicio y disponer incluso si se encuentra un error. Evite que el error burbujee.

public static bool DoRemoteWebServiceWork() 
{ 
    bool result; 
    RemoteWebServiceClient client = new RemoteWebServiceClient(); 
    try 
    { 
     result = client.DoWork(); 
     client.Close(); 
    } 
    catch (Exception) 
    { 
     client.Abort(); //dispose 
     //throw; //This service is auxiliary to the applications primary function. We have no influence over the service and therefore cannot fix it. 
     //could log end point and binding exceptions to avoid ignoring changes to the remote service that require updates to our code. 
    } 
    return result; 
} 
Cuestiones relacionadas