2012-07-03 12 views
7

Actualmente estoy en un punto muy crucial en mi desarrollo de aplicaciones móviles multiplataforma y podría realmente usar algo de experiencia (como woah) .Manejo de errores de .NET: try/catch VS event VS valor de retorno/status-fields

Para dar un contexto (lo que puede ayudar a responder, espero), estoy desarrollando una aplicación móvil en .NET basada en el práctico marco MonoCross, utilizando VS2010U (no MonoDevelop, sin embargo, eso es para IOS) . La primera plataforma de destino es Android, luego en los "puertos" de IOS y Windows Phone (no realmente si hago las cosas bien).

Ahora que tengo una base sólida, que incluye Business Logic, Data Access Layer, Base de datos, REST webservice, etc. Estoy trabajando e intentando trabajar en el manejo de errores, pero no estoy seguro de qué El mejor enfoque para esto es.

Me dijeron que los bloques try-catch pueden ser éxitos de rendimiento (que es un gran problema en este caso), ¿es
cierto? ¿Debería usarlos con moderación, o simplemente abofetearlos donde sea que se pueda lanzar una excepción? (Me gustaría usarlos en todas mis llamadas a la API SQLite, ya que no sé qué diablos es que están haciendo la mitad del tiempo) .

¿Está utilizando las devoluciones de llamada de eventos como algo malo para el manejo de errores? Se me recomendó usar estos siempre que sea posible , a diferencia de try-catch, por motivos de rendimiento, pero no quiero romper ninguno de los principios y paradigmas de diseño y terminar con el código sloppy-gauh-loppy en todas partes.

La tercera opción, que tiene la menor cantidad de sobrecarga, pero es infinitamente irritante para tratar con, son campos de estado y valores devueltos.

¿Qué piensan? Supongo que estoy buscando alguna dirección general, y tal vez algunas sugerencias sobre dónde y cuándo usar cada una, y cualquier otra técnica que probablemente haya omitido. Por favor, avíseme si se necesitan más detalles, ya que me gustaría darlos.

¡Gracias por tomarse un tiempo para esto!

+0

capturar excepciones es más lento que otras formas de manejo de errores, eso es cierto.El procesamiento de eventos depende completamente de cómo se manejan los eventos. Un valor de retorno sería menos intensivo. Lo más probable es que pueda usar cualquiera de ellos sin problemas, a menos que esté procesando muchos miles de llamadas por segundo. – Wug

+0

Definitivamente voy a tener esto en cuenta. Muy buen punto, gracias! – samosaris

+0

Excelente publicación para el manejo de excepciones en .NET: http://www.codeproject.com/Articles/9538/Exception-Handling-Best-Practices-in-NET – samosaris

Respuesta

1

Algunas veces, la teoría no se alinea con una implementación particular, pero imagino que Mono ya tenía estos conceptos en su lugar por un tiempo.

Un tiempo de ejecución adecuado siempre favorece el rendimiento en el caso de excepción libre. Idealmente, en el caso de que no se genere ninguna excepción, un bloque try/catch debería funcionar como si el contenido del bloque try se ejecutara por sí mismo, y un bloque try/finally se ejecutara como si los contenidos de los bloques try y finally fueran ejecutado en orden Cuando se utiliza un intérprete de códigos de bytes CIL, generalmente no es posible realizar estas operaciones sin gastos generales, como menciono aquí. Sin embargo, un compilador JIT o AOT decente (como el que obtiene con Mono) produce código que se ejecuta tan rápido en el caso exento de excepciones como lo haría si se omitieran las construcciones try/catch/finally.

If en su lugar, elija una estrategia de códigos de error, su aplicación terminará ejecutando partes de su código de manejo de errores incluso cuando no se produce un error (pasando un parámetro extra a los métodos, calculando y probando los códigos de retorno, etc.). Por lo tanto, su objetivo es restringir el uso del manejo de excepciones a casos realmente excepcionales. Esta estrategia conduce a una aplicación robusta (manejo de errores adecuado) sin degradación del rendimiento para los casos de éxito críticos para el rendimiento.

¹ Esto no es 100% exacto en el caso de un bloque try/finally incrustado en el cuerpo de un ciclo de computación numérico, pero la posibilidad de que tenga un impacto de rendimiento observable cuando se usa adecuadamente para casos excepcionales es prácticamente nulo en este punto. Específicamente, un JIT try/finally JIT compilado para X86 incluirá un código que se asemeja a instrucciones push/pop/jmp (rama local) en comparación con el mismo método sin el bloque try/finally. Esto es menos sobrecarga que una llamada a un método definido como: public static void Foo() {}

+0

dooood ... ¡qué tal las manzanas! gracias por estas gemas. déjame adivinar, ¿rodar datsun y un camero? – samosaris

+0

@SamusArin My Datsun tiene el motor de un Camaro: http://www.280z28.org/images/z/IMG_2020.jpg –

+0

gangsta oficial! te pones duro con un bloque pequeño chevy v8! verdaderamente épico. – samosaris

1

Use try/catch en caso de que desee para detectar la excepción esperada. Por lo general, determinar el flujo de trabajo por excepciones no es una buena opción, pero podría ser el único en el caso de las operaciones de IO. Por ejemplo, escribe en un dispositivo externo que de repente perdió la conexión. En este caso, su programa recibirá una excepción, pero tendrá que manejarlo como un error habitual.

+0

Tigran: para aclarar, usa try/catch cuando espera que se produzca una excepción (por ejemplo, cuando tiene un presentimiento, la llamada a veces puede causar un problema/una excepción). Por el contrario, ¿no te molesta poner try/catch alrededor de las llamadas que están "normalmente" bien? – samosaris

+0

@SamusArin: exactamente. – Tigran

+0

Ok, gracias, creo que puedo manejar eso (heh, sin juego de palabras). – samosaris

4

Creo que lo que hizo que su programa sea feo está haciendo el manejo de excepciones en cualquier parte, a pesar de que tenemos buenos patrones de manejo de excepciones.

Este tipo de funcionalidades que va a pasar todo lo que sobre la base de código se llama Cross Las preocupaciones de corte como la explotación forestal, la seguridad, auditoría, control de excepciones y ....

se pueden encontrar buenos patrones aquí http://msdn.microsoft.com/en-us/library/ee658105.aspx#ExceptionManagement.

Vale la pena mencionar que no recomendaría el uso de EntLib como se recomienda en los documentos de Microsoft.

Si busca la Programación Orientada a Aspectos (AOP), encontrará buenos recursos. Y la última pista es que las implementaciones utilizarán una Dependencia de Inyección/Frameworks IoC para abordar estas preocupaciones.

+1

totalmente moley, ¡es un papel realmente bueno! gracias otra vez Jani, ¡ese hombre! – samosaris

+0

@SamusArin Me comprometí a ayudarte anoche :-) –

+0

+1 porque el código de manejo de excepciones es feo y tedioso. – Wug

2

Me gustaría usarlos en todas mis llamadas a la API de SQLite, ya que no sé qué diablos están haciendo la mitad del tiempo.

Si usted está diciendo que son usando una biblioteca para la interconexión con SQLite, es probable que esta biblioteca API ya están lanzando excepciones en ciertos casos de error. Por supuesto, cuando este es el caso, debe usar try/catch alrededor de estas llamadas y manejar estas situaciones erróneas.

Este es siempre el caso cuando usted no ha escrito ese código usted mismo, cuando está usando la biblioteca de otra persona.

Cómo manejas estos errores es tu decisión.

Mi consejo:

  • estoy contra devoluciones de llamada/eventos para la mayoría de los casos. En su mayoría, deberían utilizarse cuando la API que produce un error es asincrónica y el flujo del programa ya no es evidente por eso.
  • Lanzar excepciones es de hecho más lento que los códigos de estado/valores-de-retorno, pero se puede utilizar de forma segura en cualquier plataforma móvil hoy en día en cualquier situación donde la aplicación no sea de tiempo crítico. Los juegos móviles usan lanzamientos de excepción y son críticos en el tiempo (tipo de).
  • Lanzar excepciones proporciona una mejor legibilidad del código, en mi opinión, es algo subjetivo, y es una buena manera de saltar fuera del contexto actual en caso de error.
+0

Sí, estoy usando la API System.Data.SQLite, y sí, algunos de los métodos los arrojan (acabo de decompilar con dotPeek), así que intentaré capturarlos en consecuencia. Un gran consejo, ¡muchas gracias! – samosaris