PDA

Ver la Versión Completa : Intentarlo excepto si podemos evitarlo


roman
15-05-2003, 11:00:02
Acabo de leer un mensaje de kinobi en el hilo curiosidad de FieldbyName (http://www.clubdelphi.com/foros/showthread.php?s=&threadid=426) en donde dice:

Escrito originalmente por kinobi
En ese sentido, FieldByName está más en la línea actual de gestión de errores (excepciones), al "obligarte" a utilizar un bloque try ... except para capturar la excepción y actuar en consecuencia.


Me quedé pensando en estas palabras y no entiendo muy bien la intención. ¿Significa que es mejor, por ejemplo, referenciar un objeto entre try-except y esperar la excepción EAccessViolation en lugar de simplemente verificar que sea distinto de nil?

Mi sentir es que los bloques try-except son más adecuados en las situaciones que no están bajo nuestro control, por ejemplo:


try
N := StrToInt(Edit1.Text);
except
on EConvertError do
{ Mandar mensaje de error al usuario }
end;


Aquí estamos en una situación que no controlamos: la falta de pericia del usuario :)

Pero si podemos saber que algo va a fallar de antemano, ¿para qué esperarnos a que se lance la excepción?

En resumen, mi opinión es: inténtalo a menos que de antemano sepas que no se puede.

¿Y ustedes, qué piensan?

// Saludos

Se acerca el día...

andres1569
15-05-2003, 11:33:18
Hola:

Estas palabras de Kinobi hacían referencia a un post mío donde decía que FindField permite esquivar la excepción. En este caso concreto, creo que según la finalidad se justifica un método u otro.

Coincido con la afirmación de Kinobi, la comprobación de si es nil o no puede ocultar un error latente, mientras que al tratar la excepción, o bien tomamos medidas o bien simplemente dejamos que salte el mensajito (ya sea al cliente o a nosotros ) para luego tomar cartas en el asunto. Eso es al menos la teoría actual en cuanto al manejo de errores.

En este caso concreto puedo poner ejemplos donde utilizo FindField simplemente porque es una opción contemplada como probable el que devuelva nil, sin que ello suponga ningún error, simplemente interpreto que ese campo no existe en dicha tabla porque estoy utilizando un procedimiento que afecta a diferentes tablas, y obro en consecuencia. Se podría objetar que puede devolver nil por otras razones como que la tabla no exista en el disco duro etc..., pero hablo de eventos disparados por la misma tabla, en cuyo caso sé casi al 100 % la causa. Ahí me parece innecesario meter un try ... except. Pero como tú bien dices, cuando existe una posibilidad insospechada de que algo vaya mal es mejor tratar la excepción.

Hasta luego

chutipascal
15-05-2003, 13:50:59
Posteado originalmente por roman
Acabo de leer un mensaje de kinobi en el hilo...........Pero si podemos saber que algo va a fallar de antemano, ¿para qué esperarnos a que se lance la excepción?

En resumen, mi opinión es: inténtalo a menos que de antemano sepas que no se puede.

¿Y ustedes, qué piensan?

// Saludos

Se acerca el día...

Hola.

Hay 2 formas de hacer el control de errores. El modo optimista y el modo defensivo. Cuando comprueba una cosa (como lo del nil) estas acotando o definiendo limites para un particular proceso es el modo defensivo, antes de que pase tomas precauciones. Con el modo optimista dejas que el proceso se ejecute aunque pueda ser que salte pero como lo encierras en un try...except recuperas el error por la excepción a partir del except.
Las ventajas del defensivo son que no tienes que ejecutar el código (que presumiblemente puede fallar) para ver que hay un error, sin embargo su principal desventaja es que tienes que definir constantemente los limites de los datos y de los recursos del sistema y muchos de esos 'limites' se nos escaparán.
La ventaja del optimista es que no tienes que preocuparte de acotar nada simplemente pruebas a ver si funciona y si no funciona... recuperas el error por el except. Por 'legibilidad' el encerrar el proceso en un try...except es más fácil de seguir que encerrarlo dentro de unos IFs. También tiene la gran ventaja de que como no has puesto ningún limite no has acotado algo que mañana funcionara y que hoy no puede funcionar (por ej. si modificas el paso de un tipo de argumento a una dll, una tabla de BD que antes no admitía duplicar tal o tal campo) con la programación defensiva tendrás que modificar gran parte de tu código de la otra manera, nada.
Programar optimista esta ,ás en la onda de hoy en día, tal vez por estos motivos y mil más.
Antes programaba en defensivo pero cada vez estoy usando más try...except (aunque reconozco que me cuesta pensar de esa forma todavía).

Un saludo.

bitERROR
24-05-2003, 03:55:11
Buenas gente.

Mi opinión y mi método para capturar ó no un error con try .. except es valorar la importancia del error, por ejemplo, un caso muy común, convertir una cadena a un número:

- Si el único uso que voy a dar al número obtenido es presentarlo en pantalla, haría: try Num := inttostr(Cad) except Num := 0 end;

- Si el número voy a grabarlo directamente en un campo de la base de datos simplemente haría: Num := inttostr(Cad);
ya que en este caso sea cual sea el método de gestionar el posible error, si este se produce tendré que mostrar un mensaje al usuario y no voy a arriesgar a grabar incorrectamente un valor en la base de datos.

Además creo que el mensaje de error, sea más ó menos cuco, no deja de ser un mensaje de error y como tal, una putada :D

Finalmente y en definitiva creo que el try .. except es un mal invento, todo posible error debiera de poder ser detectado antes de ejecutar la instrucción y no esperar a que el error se produzca para capturarlo, salvo contadas ocasiones cambio el except por el finally, para echar atrás operaciones que pudieran quedar colgadas por algún error que no haya podido preveer.

Julià T.
24-05-2003, 05:07:54
Hola a todos:

yo soy de la opinion que las expecciones deben saltar lo menos posible por ello utilizo el StrToIntDef y no el StrToInt.
aunque reconozco que si en una función un poco larga donde pueden fallar varias cosas puede triplicarse el código escrito.

kinobi
24-05-2003, 11:21:07
Hola,

se me había pasado de largo este hilo. Sólo un comentario:

Posteado originalmente por roman
Acabo de leer un mensaje de kinobi en el hilo curiosidad de FieldbyName (http://www.clubdelphi.com/foros/showthread.php?s=&threadid=426) en donde dice:


Escrito originalmente por kinobi
En ese sentido, FieldByName está más en la línea actual de gestión de errores (excepciones), al "obligarte" a utilizar un bloque try ... except para capturar la excepción y actuar en consecuencia.


Me quedé pensando en estas palabras y no entiendo muy bien la intención. ¿Significa que es mejor, por ejemplo, referenciar un objeto entre try-except y esperar la excepción EAccessViolation en lugar de simplemente verificar que sea distinto de nil?

Lo que pretendía decir es que la gestión "moderna" (ojo a las comillas) de errores tiene uno de sus fundamentos en separar el hilo (en el sentido de flujo) de ejecución del código de la propia gestión de errores.

En la programación "tradicional" (ojo otra vez a las comillas), uno tiene que verificar cada paso que da dentro del algoritmo que está implantando para tener la seguridad que todo está bajo control. Con los bloques try ... también tiene que hacerlo, pero separando claramente lo que es el algoritmo en sí y lo que son las situaciones excepcionales o errores que pueden producirse.

Resumiendo, la gestión de los errores es la misma (*) en ambos casos, pero en la "tradicional" va mezclada con el código realmente "útil", y en el caso de los bloques try ... se separa, haciendo que sea más cómoda su gestón.

(*) Bueno, en realidad con los bloques try ... se tiene más versatilidad, ya que no es necesario gestionar la situación excepcional en el mismo bloque de código donde se produce, puede delegarse en bloques superiores.

Saludos.

roman
24-05-2003, 11:39:08
Algo para reforzar mi punto de vista.

De la ayuda de Delphi

Exceptions provide an elegant way to trap runtime errors without halting the program and without awkward conditional statements. The requirements imposed by exception handling semantics impose a code/data size and runtime performance penalty. While it is possible to raise exceptions for almost any reason, and to protect almost any block of code by wrapping it in a try...except or try...finally statement, in practice these tools are best reserved for special situations.

Exception handling is appropriate for errors whose chances of occurring are low or difficult to assess, but whose consequences are likely to be catastrophic (such as crashing the application); for error conditions that are complicated or difficult to test for in if...then statements; and when you need to respond to exceptions raised by the operating system or by routines whose source code you don't control. Exceptions are commonly used for hardware, memory, I/O, and operating-system errors.

Conditional statements are often the best way to test for errors. For example, suppose you want to make sure that a file exists before trying to open it. You could do it this way:


try
AssignFile(F, FileName);
Reset(F); // raises an EInOutError exception if file is not found
except
on Exception do ...
end;

But you could also avoid the overhead of exception handling by using


if FileExists(FileName) then // returns False if file is not found; raises no exception
begin
AssignFile(F, FileName);
Reset(F);
end;



// Saludos

kinobi
24-05-2003, 11:55:16
Hola,

Posteado originalmente por roman
Algo para reforzar mi punto de vista.

De la ayuda de Delphi

[...]

En mi comentario anterior no pretendía defender un tipo de gestión de errores frente a otro, simplemente exponer algunas las diferencias entre uno y otro.

Ahora bien, el argumento de Borland sobre la pérdida de rendimiento al utilizar bloques try ... "suena" a una mala justificación. Utilizando el mismo argumento, no deberíamos utilizar tecnologías orientadas a objeto debido a la sobrecarga de la gestión de las estructuras de datos (tablas de métodos, protección de zonas privadas del objeto, ...) con respecto a una "simple" tabla de símbolos que genera un compilador en un código "sin-objetos". Es más, llevando el argumento a sus límites: ¿por qué utilizar lenguajes de alto nivel y no utilizar código 1010111000....?

El uso de bloques try ..., independientemente al lenguaje escogido, es una técnica (integral, no sólo para casos "especiales") que soluciona una serie de problemas inherentes a la gestión tradicional de errores. Otra cosa es que Borland no haya conseguido implantarla de forma óptima en sus compiladores.

Saludos.

andres1569
24-05-2003, 13:20:22
Hola:

BitERROR escribió:


Finalmente y en definitiva creo que el try .. except es un mal invento, todo posible error debiera de poder ser detectado antes de ejecutar la instrucción y no esperar a que el error se produzca para capturarlo...


Creo que para eso están el try ... except y el try ... finally, para detectar errores. El que aparezca un mensaje en pantalla es algo que puedes controlar tú mismo; sería redundante escribir nuestro propio código que se anticipara a un posible error, de eso se encarga ya la VCL; luego nosotros metemos estas sentencias, capturamos el código de error y obramos en consecuencia. En ocasiones sabemos por donde puede fallar algo y podemos anticiparnos, en otras las excepciones nos dan una información muy valiosa.

Un Saludo

bitERROR
24-05-2003, 16:15:12
A esto llamó yo en contadas ocasiones


... Exceptions are commonly used for hardware, memory, I/O, and operating-system errors.


Nunca os ha pasado de probar le programa y decir ... "vaya no lo está haciendo bien, pero tampoco salta ningún error... que raro".

Si dije que opinaba que try .. except es un mal invento es porque su uso es demasiado sencillo y cómodo, utilizándose tan comunmente que a veces tu propia aplicacion te oculta errores que tu mismo capturaste ... la información es valiosa (he leido ahí arriba), apoyo esta premisa.

Por lo que hace a mezclar código útil con código de validación de posibles errores, es únicamente y por lo general caso de organizar bien lo que es la validación y lo que es el proceso útil al implementar.

No me considero un programador tradicional, try .. except no deja de ser otra herramienta de trabajo, pero la captura de errores mediante try .. except procuro que sea mínima y la empleo en casos sin importancia try num := strtoint(cad) except ... ó en casos excepcionales en que yo no pueda controlar el código hecho por un tercero.

saludos, interesante debate jeje :D

kinobi
24-05-2003, 17:34:21
Hola,

Posteado originalmente por bitERROR
Si dije que opinaba que try .. except es un mal invento es porque su uso es demasiado sencillo y cómodo, utilizándose tan comunmente que a veces tu propia aplicacion te oculta errores que tu mismo capturaste ... la información es valiosa (he leido ahí arriba), apoyo esta premisa.


si una aplicación "oculta errores" utilizando bloques try ... no es un problema del método, en todo caso será que quien lo aplica no proporciona el manejador de excepción adecuado, pero eso no es defecto del método en sí.

Saludos.

roman
24-05-2003, 18:28:46
Posteado originalmente por kinobi
si una aplicación "oculta errores" utilizando bloques try ... no es un problema del método, en todo caso será que quien lo aplica no proporciona el manejador de excepción adecuado, pero eso no es defecto del método en sí.


Aquí estoy totalmente de acuerdo. Independientemente de si se usan o no las excepciones, éstas no son para ocultar errores sino para detectarlos. Es muy común esta codificación:


try
{ Código tortuoso }
except
{ Tratar la excepción que uno imagina }
end;

o peor aún:


try
{ Código tortuoso }
except
{ No hacer nada }
end;


En el primer caso podría saltar una excepción que no previmos y nunca lo sabremos hasta que la aplicación se derrumbe. Y el segundo caso la osadía es inaudita: no voy a hacer caso de ningún posible error, no quiero saber de él

Siempre hay que dejar que las excepciones que no manejamos se manifiesten.

// Saludos

bitERROR
26-05-2003, 02:03:30
Buenass (III)


Originalmente posteado por kinobi
si una aplicación "oculta errores" utilizando bloques try ... no es un problema del método, en todo caso será que quien lo aplica no proporciona el manejador de excepción adecuado, pero eso no es defecto del método en sí.


En mi opinión, lo que comentas es de por si un defecto claro de la implantación por parte de borland del try .. except.

La sencillez del proceso de captura de errores simplifica sobremanera la ocultación de los mismos. Creo que debiera ser más complicado ignorar errores que gestionarlos.

Jejemplo volviendo al StrToInt...:
-Ignorar error:

try
aNum := strtoint(aCad) ;
except
aNum := 0;
end;


-Gestionar error:

try
aNum := strtoint(aCad) ;
except
on e: exception do
if e.ClassType = EConvertError then aNum := 0
else raise;
end;


Aunque este es un ejemplo muy básico, creo que queda claro lo que quiero decir. Está bien pensado el try .. except y obviamente una buena gestión de errores depende de la habilidad y conocimientos del programador. El manejo de las excepciones es un punto clave en toda aplicación y try .. except es en mi opinión excesivamente tolerante.

Me encantaría debatir este tema con unas cervezas de por medio, este es mi tercer post en este tema y creo que siempre nos dejamos algo por decir jeje. Na más, un saludo :)