2008-12-03 8 views
12

Estoy desarrollando un contenedor para una biblioteca de funciones de terceros que interactúa con algún hardware especial. Básicamente, quiero encapsular las funciones dll (bool Connect(), void Disconnect(), etc.) en un MyHardwareObject con métodos de conexión y desconexión.Cuándo volver a lanzar una excepción, cuándo devolver FALSO?

La función Connect del dll puede arrojar algunas excepciones específicas, por ejemplo, cuando el hardware no está presente. Para la aplicación, la información sobre por qué falló el método de conexión se considera sin importancia, por lo que la información adicional contenida en la excepción no es necesaria.

¿Cuál es la mejor forma de manejar esas excepciones, devolviendo false, o dejando la excepción no controlada aquí y atrapandola en el nivel que de otro modo manejaría el hecho de que el método de conexión retornó false?

bool MyHardwareObject.Connect() 
{ 
    try 
    { 
     ThirdPartyLibrary.Connect(); 
    } 
    catch (SomeException) 
    { 
     return false; 
    } 
    return true; 
} 

A diferencia de

bool MyHardwareObject.Connect() 
{ 
    ThirdPartyLibrary.Connect(); 
    return true; 
} 

(o en el segundo caso mejor void MyHardwareObject.Connect(), ya que cualquiera de vuelta verdad, o lanzar una excepción?)

O qué más se puede hacer? Y lo más importante: ¿por qué?

Respuesta

7

Es realmente difícil elegir sabiamente entre las excepciones y los códigos de retorno. Depende de muchas cosas, y la forma en que se manejan los errores en el resto de la base de código sería la más importante: mantente constante.

Últimamente, me inclino más hacia "no lanzar una excepción si no vale la pena". Nuestras excepciones hacen mucho trabajo: registran cosas, crean rastros de pila, etc. Si solo quiero convertir una cadena en un entero, lanzar una excepción si la cadena de entrada tiene el formato incorrecto probablemente no valga la pena. Por otro lado, tengo objetos que simplemente no quiero en mi sistema si no se pueden construir a partir de los datos adecuados, y en ese caso sus constructores generan excepciones.

Si el resto de la base de código no le da ninguna pista sobre cómo hacerlo, me gusta esta regla general: imagine que lanzar una excepción hace que su computadora emita un pitido fuerte. Mientras puedas aguantarlo, tirar está bien.

9

En mi opinión, el primer caso es sin duda mejor que el segundo. Usted quiere su biblioteca de hardware para envolver la biblioteca de terceros de forma que sus usuarios no tengan que saber exactamente qué contiene.
Si necesita más detalles sobre el manejo de errores además de verdadero o falso, podría considerar volver a lanzar su propia excepción, traduciendo la excepción de la biblioteca de terceros a algo más consistente con su propio código.

6

Dejaría pasar las excepciones. Si no lo hace, está enmascarando información potencialmente importante que podría ser útil más adelante. Sé que no lo está usando ahora, pero qué sucede si decide en el futuro manejar la recuperación de manera diferente según el tipo de error. En ese momento, tendrá que deshacer todo el código que haya escrito para enmascarar la excepción. Si bien no estoy de acuerdo con @MadKeithV en hacer que sea verdadero/falso, creo que tiene un punto para envolver la excepción en su propia excepción que tiene, posiblemente, una mejor semántica para su aplicación.

+0

Bueno, no estaba sugiriendo enmascarar información importante, pero considerando seriamente qué información es importante transmitir, y qué información debería manejarse de manera segura por Connect fallando o teniendo éxito, en lugar de pasar ciegamente todas las excepciones. Así que creo que estamos de acuerdo en su mayoría. –

0

Creo que el principio detrás del mecanismo de excepción es la teoría "fail fast".

¿Desea que la aplicación de su cliente "falle rápido" es que la conexión no es correcta?
En caso afirmativo, simplemente devuelva la excepción o encapsule la excepción en una excepción aplicativa propia.

Si el cliente ignora esa excepción, su aplicación se detendrá.

return false significa que el cliente puede ignorar el problema, su aplicación aún puede colgarse, pero "más adelante" ...

1

¿Es esta biblioteca de terceros requerido para su programa a ejecutar, o solo agregar una poca funcionalidad adicional, que, aunque es agradable, no es necesaria? Además, es probable que el hardware falle. Finalmente, ¿cuántos tipos de excepciones puede arrojar el hardware sobre usted?

Si la biblioteca no es realmente necesaria para ejecutar su programa, sin duda debe detectar la excepción en algún momento, pero es posible que desee hacerlo más arriba.

Si el hardware puede arrojar múltiples tipos de excepciones, es más probable que desee volver a lanzar la excepción ya que simplemente devolver un valor hará que pierda parte de la información. Sin embargo, usted dijo que al cliente no le importa por qué falló, solo que sí, así que esto no debería ser un problema.

Por último, si la falla del hardware es habitual, es más probable que desee devolver un código de error (o falso en este caso) que si la falla es común.

Creo que en su caso realmente se reduce a la primera pregunta. Si realmente no necesita esta biblioteca, devuelva falso y asegúrese de que esté claramente documentado que la operación puede fallar por razones completamente arbitrarias y que deben verificar el valor de retorno. Si necesita que funcione, vuelva a lanzar la excepción y permita que se propague a donde pueda salir graciosamente.

+0

Es obligatorio: la interfaz con este hardware es la tarea principal de la aplicación. ¿Te entiendo correctamente? No usarías un valor de retorno, porque alguien podría usar simplemente llamando a 'MyObject.Connect()', sin verificar el valor de retorno, como en 'if (! MyObject.Connect()) ... ¿? – Treb

3

Sugeriría el segundo. Será responsabilidad del que llama manejar la excepción y tomar la acción correcta de acuerdo con la excepción. Supongamos que Connect lanza AccountExpiredException, NetworkUnavailableException, InvalidCredentialsException, etc. (estos son solo ejemplos). Puedo pedirle al usuario que "solucione" la excepción (póngase en contacto con el administrador, compruebe su cable de red, compruebe el nombre de usuario/contraseña). Incluso sugeriría eliminar el valor de retorno (indicador) y simplemente dejarlo sin efecto. Eche un vistazo al método SqlConnection Open, es como Connect, no devuelve un valor sino que arroja una excepción. de tragar la excepción como esta

bool MyHardwareObject.Connect() 
{ 
    try 
    { 
     ThirdPartyLibrary.Connect(); 
    } 
    catch (SomeException) 
    { 
     return false; 
    } 
    return true; 
} 

no es una buena idea en mi humilde opinión. Te recomendaría implementar un patrón IDisposable. Solo mis 2 centavos.

6

Lea esto: http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html

En resumen:

¿La persona que llama tienen ningún uso para el valor de retorno? ¿Se puede recuperar o es un error el fin del mundo? Si se trata de un problema menor, use un código de retorno. Si los diferentes estados ocurren con la misma frecuencia (50% del tiempo falla, 50% funciona), use un código de retorno porque la persona que llama debe manejar la situación de todos modos y una excepción no ayuda.

¿Desea omitir información adicional (como la configuración de un tercero para que alguien pueda depurar lo que sucedió más tarde)? Use una excepción

Cuestiones relacionadas