PDA

Ver la Versión Completa : Excepciones: uso y abuso de la instrucción try/except


dec
14-07-2005, 10:27:49
Hola,

He dudado entre publicar este Hilo o no y es que lo que diré es, desde luego, interesante para mí, pero, no sé hasta qué punto podrá o no importarle a alguien más.

Brevemente. Hasta anoche no supe bien el uso de la instrucción try/except no ya en Delphi, pero, supongo, en cualquier lenguaje que haga uso de esta instrucción o alguna similar.

Algo he leído (reconozco que no lo que debiera) sobre el tema, empero, hasta anoche, tal como digo, no vi la luz, como suele decirse. Me alumbró Ian Marteens (http://www.marteens.com/) en un artículo suyo titulado Excepciones en Freya (http://www.marteens.com/freya_exceptions.html).

Resulta que, como el autor menciona en el segundo o tercer párrafo del artículo susomentado:


La instrucción peor utilizada de estas tres [raise, try/finally, try/except], suele ser try/except. En una aplicación, menos del 10% de los try debe ser un try/except. La explicación está en que muy pocas veces tenemos un plan B para cuando nos falla el primer intento de resolver un contrato.

Pues bien, reconozco que he utilizado mal la instrucción de marras en no pocas ocasiones, a lo que se ve, pero que me prometo desde estas líneas no volver a hacerlo nunca más de este modo.


try
...
except
...
raise;
end;
Es decir: utilizamos realmente la cláusula except para llevar el programa a un estado estable... y repetir la excepción original, de modo que siga su propagación natural.

Probablemente me lo habían indicado con otras palabras; quizás es que no presté la suficiente atención cuando leí sobre el tema; el caso es que por fin alguien ha conseguido meterme en la cabeza "el concepto", que diría un pedante.

Pues nada. Que les recomiendo el artículo (http://www.marteens.com/freya_exceptions.html) en cuestión y que espero que estos párrafos no sean del todo inútiles para quien los lea. Ah, casi se me olvidan: gracias a Ian Marteens (http://www.marteens.com) por este y otros textos suyos.

roman
14-07-2005, 16:27:49
No entendí. ¿Se supone que hay que usar siempre raise para propagar la excepción? En tal caso no me parece lógico. Si la excepción se arregla ¿qué es lo que seguimos propagando?

// Saludos

dec
15-07-2005, 00:49:20
Hola,


No entendí. ¿Se supone que hay que usar siempre raise para propagar la excepción? En tal caso no me parece lógico. Si la excepción se arregla ¿qué es lo que seguimos propagando?

¿De dónde sacas que halla que utilizar siempre raise para propagar una excepción? Yo únicamente tengo ahora claro lo siguiente: ¿Tienes un plan B? Adelante, inténtalo con try/except. ¿No tienes un plan B? Entonces olvídate de try/except.

roman
15-07-2005, 04:23:36
¿De dónde sacas que halla que utilizar siempre raise para propagar una excepción?


¿Yo? De ningún lado. Es lo que parece dar a entender el comentario que pusiste o no me queda claro. Por ello puse que no entendí.

De cualquier forma todo este asunto del plan B me parece un poco raro. No es si tienes o no un plan B, es que debes tener un plan B, de una forma u otra; si hay un código susceptible de generar una excepción, entonces debes manejarla de alguna manera.

// Saludos

lucasarts_18
15-07-2005, 05:01:30
Hola:

Yo siempre utilizo Try...Except, no sé para que sirve el raise..alguien sabe??



procedure TFrmTag.btnAplicarClick(Sender: TObject);
var
cont,i : Integer;
begin
cont := FrmArchivos.LstBoxFile.Items.Count;
for i := 0 to cont - 1 do
if FrmArchivos.LstBoxFile.Selected[i] = True then
try
begin
FrmPowerM.mp3Tag.Title := edtTitulo.Text;
FrmPowerM.mp3Tag.artist := edtArtista.Text;
FrmPowerM.mp3Tag.Album := edtAlbum.Text;
FrmPowerM.mp3Tag.Genre := edtGenero.Text;
FrmPowerM.mp3Tag.Year := edtAno.Text;
FrmPowerM.mp3Tag.SaveTagToFile(FrmArchivos.LstBoxFile.Items.Strings[i]);
end
except
ShowMessage('Para cambiar el tag de un archivo,éste no debe estar ejecutandose');
end;
end;




Saludos y hasta pronto..

mamcx
15-07-2005, 05:03:13
Para medio aclarar (que con plan A y plan B ya me dan ganas del plan C;) ):

El asunto con try..except es muy simple, realmente ...

Uno solo debe usar except si:

1- Es un codigo transaccional: ie. Hay una serie de tareas, un commit y en caso de falla, un rollback.

2- Cuando la excepcion se usa para CORREGIR el problema. Ej, estamos haciendo una conexion a un lugar remoto, y nos salta un error. Supongamos un timeout, y el programa es un cliente FTP que aparte de timeout tiene reintentos... Si la conexion falla se puede corregir (o sea volver a conectar) hasta N reintentos

Pero lo que nunca se debe olvidar (porque las dos reglas anteriores no son absolutas, y se puede resolver la segunda no con excepciones sino con funciones que devuelvan el resultado de la operacion) es que:

JAMAS SE DEBE ESCONDER EL ERROR. NUNCA.

Y eso es todo lo que hay que saber. Ya sea que se de "rollback" o que se "corriga" se debe NOTIFICAR que hubo error, ya sea por medio de un log, un mensaje (no intrusivo, en el caso de la correccione: e.j: El cliente FTP simplemente pone un mensaje que dice: La conexion falla, reintentando en 30 segundos...), un mesagebox o lo que sea. Si se esconde el error como:

try
AbrirArchivo;
except
result := false;

Nos va a dar un total dolor de cabeza el luego adivinar que salio mal.

Como siempre he dicho: Si el programa saca error, es que esta bueno ;) (Miedo al que nunca lo saca!)

dec
15-07-2005, 10:01:29
Hola,


¿Yo? De ningún lado. Es lo que parece dar a entender el comentario que pusiste o no me queda claro. Por ello puse que no entendí.
Supongo, roman, que leerías el artículo de Ian Marteens (http://www.marteens.com) a que me refiero.

Voy a trasladar aquí un buen trozo del artículo en cuestión, que en realidad es el meollo del mismo, al menos, en lo que se refiere a lo que traté yo de declarar en este Hilo:


La instrucción peor utilizada de estas tres, suele ser try/except. En una aplicación, menos del 10% de los try debe ser un try/except. La explicación está en que muy pocas veces tenemos un plan B para cuando nos falla el primer intento de resolver un contrato. Más aún, de ese 10% de frecuencia de uso, la mayoría de los ejemplos seguirán el siguiente patrón:

try
...
except
...
raise;
end;

Es decir: utilizamos realmente la cláusula except para llevar el programa a un estado estable... y repetir la excepción original, de modo que siga su propagación natural. Uno de los principios más importantes de la buena programación es dejar bien claras nuestras intenciones en todo momento. Un try/except puede confundir al programador que intenta comprender el listado... al menos, hasta que encuentre la instrucción final raise. Peor aún: ésta puede haber sido olvidada por el propio autor del código.

Yo lo único que he dicho es que he cometido el error que menciona Ian Marteens (http://www.marteens.com) en no pocas ocasiones, y, efectivamente, reconozco que en muchas ocasiones que utilizé la instrucción try/except no contaba con ningún plan B y a veces terminaba levantando la excepción mediante un Raise ¡dentro de try/except!



JAMAS SE DEBE ESCONDER EL ERROR. NUNCA.

Pues, hombre, depende. Tengo pánico a las palabras jamás, nunca, siempre, etc. Supón algo así, por ejemplo:



var
i: integer;
begin
try
// corregido por vtdeleon
i := StrToInt(cbLinea.text);
except
end;
end;

Piensa que se trata, en el ejemplo anterior, de mostrar un pequeño formulario que solo contenga un ComboBox, en el cual el usuario tuviera que elegir/escribir un número de línea a la que luego nosotros dirigirnos.


Imagina que al usuario le da por escribir un caracter en lugar de un número en el ComboBox. ¿Para qué mostrarle el error? ¿es que no es evidente? ¿es que el usuario no ve por sus propios ojos que una línea se representa mediante su número y no una letra u otro caracter?


Personalmente, en este caso, al menos, no muestro ningún error, ni siquiera creo que interese mostrar la excepción: simplemente ignorarla. El usuario percibirá rápidamente, en mi opinión, que la "acción" al cabo no produjo nada, y todo lo más mostrará de nuevo el formulario, verá que hay solamente números en donde escoger "cargados" en el ComboBox y escogerá uno, si quiere.


Quiere decirse que, en este caso, repito, no creo interesante mostrarle el "EConvertError", porque es más que evidente para el usuario lo que realmente está ocurriendo: por si no lo fuera del todo, en cuanto se limite a escribir o elegir un número verá cómo todo va tal como se espera.


Y aquí se ve a las claras que no hay plan B de por medio. Un plan B, por ejemplo, sería decir "muy bien, usuario, no sé qué escribiste que estoy aquí, dentro de la excepción, pero, para estos casos, tengo preparada una pequeña sorpresa: me dirigiré a la línea 0, para que te chinches".


Eso ya sería un plan B, que, como puede verse arriba, no existe en este caso: el error, la excepción, simplemente es ignorada y punto pelota.;)

vtdeleon
15-07-2005, 13:30:07
var
i: integer;
try
i := cbLinea.text;
except
end;

No creo que eso Compile :P

var
i: integer;
try
i := StrtoInt(cbLinea.text);
except
end;
:D

dec
15-07-2005, 14:58:56
Hola,

Sí; llevas razón vtdeleon, efectivamente, hay que utilizar "StrToInt" para el caso.

yusnerqui
15-07-2005, 16:24:28
Pues ya que hablamos del tema, les propongo este artículo (http://www.clubdevelopers.com/delphi/articulos/lenguaje/except/index.php) el cual lo aborda de forma muy amplia, y saquen sus propias conclusiones:)


Saludos

jachguate
15-07-2005, 16:50:53
Hola.

Lucasarts nos ha dado un buen ejemplo de uno de los errores mas comunes a la hora del uso de try/except.



procedure TFrmTag.btnAplicarClick(Sender: TObject);
var
cont,i : Integer;
begin
cont := FrmArchivos.LstBoxFile.Items.Count;
for i := 0 to cont - 1 do
if FrmArchivos.LstBoxFile.Selected[i] = True then
try
begin
FrmPowerM.mp3Tag.Title := edtTitulo.Text;
FrmPowerM.mp3Tag.artist := edtArtista.Text;
FrmPowerM.mp3Tag.Album := edtAlbum.Text;
FrmPowerM.mp3Tag.Genre := edtGenero.Text;
FrmPowerM.mp3Tag.Year := edtAno.Text;
FrmPowerM.mp3Tag.SaveTagToFile(FrmArchivos.LstBoxFile.Items.Strings[i]);
end
except
ShowMessage('Para cambiar el tag de un archivo,éste no debe estar ejecutandose');
end;
end;



El problema, es que (hablando en términos de marteens) el plan "B" que intenta aplicarse es específico de un tipo de problema, pero se termina aplicando para cualquier condición de excepción, lo cual no siempre será adecuado, tal como lo ilustra el ejemplo actual.

Supongamos por ejemplo, que la propiedad Year, aún cuando es de tipo string, valida que el valor asignado sea un número. La forma "normal" de "romper un contrato" (sigo con marteens) es elevar una excepción, dado que este no se ha cumplido al asignar la cadena "mil novecientos noventa y cinco" a la propiedad year (lo introducido por el usuario). En este caso la excepción será de la clase EConvertError.

En este caso, el usuario segirá recibiendo el mensaje: Para cambiar el tag de un archivo,éste no debe estar ejecutandose :o

Esto no orienta en nada al usuario a corregir su error. Hay que tomar en cuenta también que hay otra serie de excepciones que podrian ocurrir: El disco está lleno, quizas tenga sectores dañados. En windows no es inusual que el sistema se quede sin recursos... también podria ocurrir una guerra nuclear :mad: y el usuario obtendría siempre el mismo mensaje :(.

Esto nos lleva a la situación mas general de comprender que podrá ocurrir una serie de condiciones de excepción para la que no estamos preparados. La regla general es entonces aplicar el "plan b" solo para aquellas que sabemos y queremos tratar, dejando pasar todas las demás.


procedure TFrmTag.btnAplicarClick(Sender: TObject);
var
cont,i : Integer;
begin
cont := FrmArchivos.LstBoxFile.Items.Count;
for i := 0 to cont - 1 do
if FrmArchivos.LstBoxFile.Selected[i] = True then
try
FrmPowerM.mp3Tag.Title := edtTitulo.Text;
FrmPowerM.mp3Tag.artist := edtArtista.Text;
FrmPowerM.mp3Tag.Album := edtAlbum.Text;
FrmPowerM.mp3Tag.Genre := edtGenero.Text;
FrmPowerM.mp3Tag.Year := edtAno.Text;
FrmPowerM.mp3Tag.SaveTagToFile(
FrmArchivos.LstBoxFile.Items.Strings[i]);
except
on EFileInUse do
ShowMessage('Para cambiar el tag de un archivo, éste no debe estar ejecutandose');
end;
end;


Suponiendo que el método elevará la exepción EFileInUse. Ahora, cualquier otra condición de error seguirá abortando la ejecución del código hasta que haya un bloque que si sepa que hacer con ella.

Yo siempre utilizo Try...Except, no sé para que sirve el raise..alguien sabe??
raise es la instrucción con la que se eleva una exepción. Si se usa dentro de un bloque except, reeleva la misma excepción que nos hizo entrar alli.

Hasta luego.

;)

jachguate
15-07-2005, 17:00:30
Uno solo debe usar except si:

1- Es un codigo transaccional: ie. Hay una serie de tareas, un commit y en caso de falla, un rollback.

2- Cuando la excepcion se usa para CORREGIR el problema. Ej, estamos haciendo una conexion a un lugar remoto, y nos salta un error. Supongamos un timeout, y el programa es un cliente FTP que aparte de timeout tiene reintentos... Si la conexion falla se puede corregir (o sea volver a conectar) hasta N reintentos
Me parece un campo de acción muy reducido para el uso de try/except. En general, yo diría que debemos usar un bloque try/except si quiere y sabe como manejar una condición de error producida en el programa, cualquiera que esta sea.

JAMAS SE DEBE ESCONDER EL ERROR. NUNCA.
A menos que sepas que hacer con el error (plan b). Hay muchas condiciones de error que son manejadas por los programas internamente y que no tienen necesariamente que llegar a oidos del usuario, no por desonhestidad, sino porque muchas veces es parte de la solución tratar también estas excepciones adecuadamente de forma automática.

Hasta luego.

;)

mamcx
15-07-2005, 17:02:57
Y quien GARANTIZA que el problema va a ser porque cbLinea.text <> Integral? Y si se quedo el programa sin memoria? Y si hay un overflow? Y si el numero EFECTIVAMENTE es uin integral pero del tipo BigInt? Y si el usuario escribe 1, luego lo borra y queda en ""?

O sea, si saca el error: Es porque cbLinea.text <> Integral o porque cbLinea.text <> vacio? Como ves, minimamente encontramos 2 estados de (posible) error.

Y como sabe el usuario que es un numero? En ese caso, se debe 1)Poner una mascara 2) Ojala un edit que tenga algo que identifique es un numero, por ejemplo esos que desplegan una calculadora...


En mis años de programador he visto que errores IMPOSIBLEs pasan.... las correcciones deben hacerse con bisturi, no con espada, porque cuando se va acumulando codigo asi, se complica la cosa....

Ahora analiza la opcion desde el punto de vista del usuario.... que GARANTIZA que va a saber que hacer? Si no saca un mensje, lo mas seguro es que se puede suponer, el campo es opcional, no obligatorio.

Ahora si lo que quieres es eludir el molesto mensaje de error, hay muchas maneras:

1- Un beep

2- Poner un muñequito o asterisco rojo al lado del control, indicando que paso/que hacer

3- Flashear el control

4- Cambiar el mensaje de Excepcion por un messageboc informativo "Hey chico, es un numero, Ok?"

5- Construir el control para que definitiva y absolutamente, no pueda meter un numero NO integral

Y esas si son soluciones. De lo contrario, llamara el usuario a preguntar que es lo que pasa o se quedara dando vueltas al asunto adivinando el comportamiento oculto del sistema....

dec
15-07-2005, 17:56:51
Hola,

Gracias yusnerqui por el artículo que has enlazado. Por él me he decidido a usar la función "TryStrToInt" en lugar de:


var
i: integer;
begin
try
i := StrToInt(cbLinea.Text);
except
end;
end;



Y como sabe el usuario que es un numero?

Hombre, pues porque el formulario es de 40x40 píxeles, hay un único ComboBox y el Caption del formulario es "Número de línea". Por si fuera poco el ComboBox se llena automáticamente con las líneas disponibles y muestra por defecto la línea actual.


Ahora analiza la opcion desde el punto de vista del usuario.... que GARANTIZA que va a saber que hacer? Si no saca un mensje, lo mas seguro es que se puede suponer, el campo es opcional, no obligatorio.

Por eso dije arriba "en este caso" y frases parecidas: en este caso no hay más campos, solamente hay un ComboBox que pide el número de línea a que se quiere uno dirigir: el usuario mismo eligió del "menú" la opción "Ir al número de línea..." ¿Cómo voy a pensar que no sabe lo que quiere hacer, repito, en este caso? ¿Tan complicado es? No, por cierto.


Y esas si son soluciones. De lo contrario, llamara el usuario a preguntar que es lo que pasa o se quedara dando vueltas al asunto adivinando el comportamiento oculto del sistema....

Soy partidario de no tratar al usuario como a tonto, empero, sí mostrarle los mensajes de errores que sean menester e indicarle incluso la forma de hacer las cosas "un tanto rebuscadas".

Mira, podría hacer algo así: mostrar el formulario con un único ComboBox en el que el usuario tuviera que escribir el número de la línea a la que quiere llegar.

Si el número fuera correcto, estupendo, adelante. Si no fuera un número u ocurriera un error de tipo "EConvertError" volverle a mostrar el formulario y en una "etiqueta" informarle de que es un número lo que tiene que indicar y no otra cosa.

Sin embargo, en este caso, insisto, no veo la necesidad: no creo que sea tan complicado lo que se pretende hacer, creo que el usuario lo entiende perfectamente, no se trata de ningún punto "crítico" del programa que pudiera tener consecuencias catastróficas, en fin.

Y, por cierto, no hay plan B en este caso: no hay para qué. ¿Qué sé yo a la línea que se quiere dirigir el usuario? No lo sé, por lo tanto, dejaré las cosas como están.

roman
15-07-2005, 19:10:30
Yo voy de acuerdo con mamcx. Las excepciones jamás se deben esconder. Pero esto no significa, como dice mi amigo jachguate, que todas deban llegar a oídos (u ojos) del usuario. "tratar la exepción" no es sinónimo de mostrar un mensaje.

Por otra parte es también un error presuponer, como ya lo indicó mamcx que el código va a fallar por una sola posible causa. Para algo está la construcción:


try

except
on EErrorQueSeComoManejar do
begin
end;
end;


cualquier otro error que no sepamos o podamos manejar o que ni siquiera tengamos previsto debemos dejar que se propague.

También, sin ánimo de ofender, creo que al amigo dec le hace falta enfrentarse con usuarios de verdad. Es increible la cantidad de cosas obvias que algunos simplemente no entienden. No es tanto tratar al usuario como tonto, pero la aplicación si debe estar pensada para tontos.


Imagina que al usuario le da por escribir un caracter en lugar de un número en el ComboBox. ¿Para qué mostrarle el error? ¿es que no es evidente? ¿es que el usuario no ve por sus propios ojos que una línea se representa mediante su número y no una letra u otro caracter?


¿Cuántas veces no nos hemos detenido nosostros mismos al programar, a veces durante horas, frente a un error que no entendemos. Vemos una y otra vez la ventana de código y nada, no nos iluminamos. Hasta después de un rato o un descanso, nos damos cuenta de lo obvio del error. ¿Por qué ha de ser distinta la situación del usuario?

Yo, como usuario, agradecería una notificación inmediata de lo que estoy haciendo mal para no perder mi tiempo buscando en el formulario dónde está el error.

// Saludos

dec
15-07-2005, 20:27:10
Hola,


También, sin ánimo de ofender, creo que al amigo dec le hace falta enfrentarse con usuarios de verdad.
No solo no ofendes en absoluto roman, es que, en eso, desde luego, no voy a quitarte la razón.


Es increible la cantidad de cosas obvias que algunos simplemente no entienden.
¿Puedes indicar algunas de ellas por ver si de una vez por todas puedo entenderlas? Estoy seguro de que son muchas las obviedades que se me escapan, pero no me parece mal que me las hagan saber.


¿Cuántas veces no nos hemos detenido nosostros mismos al programar, a veces durante horas, frente a un error que no entendemos. Vemos una y otra vez la ventana de código y nada, no nos iluminamos. Hasta después de un rato o un descanso, nos damos cuenta de lo obvio del error. ¿Por qué ha de ser distinta la situación del usuario?
Porque en este caso lo veo más sencillo así. Enfatizo: en este caso. Naturalmente que está bien hacer saber al usuario, si es menester, los errores de los programas, pero, en este caso, simplemente, no lo veo menester.

Recuerdo el caso: el usuario quiere ir a una línea. El usuario elige del menú la opción para ir a una línea. El usuario se encuentra con un formulario de 40x40 píxeles cuyo título es "número de línea" y que solo contiene un ComboBox que ya tiene cargadas todas las líneas disponibles y muestra la actual. El usuario escribe su nombre... Pues se cierra el formulario y santas pascuas.

El usuario vuelve a abrir el formulario, esto es, vuelve a abrir el menú, selecciona la opción oportuna y se le muestra el mismo formulario de antes. Entonces el usuario escribe un número de línea o elige una y zas, se cierra el formulario y se le muestra el número de línea elegido.

Al cabo me convencen y pongo un mensaje de error, en caso de que el usuario escriba su nombre o cualquier cosa que no sea un número de línea, y le digo: ¿no querías ir a un número de línea en concreto? ¿entonces para qué escribes tu nombre? Por favor, escribe o elige la línea a la que quieras dirigirte.

En fin. Yo creo que aquí el tema no era este en absoluto, pues al cabo todo queda reducido a cómo me parece a mí esto y cómo me parece a mí lo otro. Inicié este Hilo con la sola intención de dar noticia del artículo de Ian Marteens (http://www.marteens.com) el cual me puso de una vez claro el uso de try/except.

Eso sí creo que no se puede discutir, aunque, leyendo el artículo que antes recomendó un compañero que también trata sobre el tratamiento de excepciones, a lo que parece, es un tema sobre el que sí se puede discutir y se lleva discutiendo no poco tiempo.

No sé. Se me ocurre que acaso llegamos a un punto en que tratamos de cierto estilo de hacer las cosas, y esto, ¿quién puede medirlo? Quiero decir, ¿quién puede dar una guía de estilo para esto? ¿No se ve cómo se lee la guía de estilo de estos propios foros? Es probable que sirva de algo, evidentemente sirve, pero, ¿no sigue habiendo otras maneras de hacer las cosas de todos modos?

Y no de hacer las cosas mal, porque puede uno saltarse a veces ciertas reglas para hacer las cosas bien, o como cree que están bien. Pero, bueno, esto ya es demasiado, menudo rollo que he soltado.

Ahora, roman, por favor, hazme saber alguna de esas "cosas obvias que algunos simplemente no entienden". Gracias. ;)

ContraVeneno
15-07-2005, 21:19:36
Cosas que he aprendido hoy:

+ Todas las entradas que haga el usuario son culpables hasta que se demuestre lo contrario.
+ Controla todo lo que puedas controlar con los controles (si no quieres letras, pon un control que no acepte letras :o )
+ Controla solo los errores que sepas/puedas controlar. (me queda muy claro la excepción EErrorQueSeComoManejar :D )
+ El usuario no es tonto, pero el programa debe estar diseñado para tontos.
+ Al usuario le gusta saber cuando hizo algo mal. (En algunos casos será necesario mostrar un mensaje, en otros casos con un BIP es suficiente; pero SIEMPRE indicarle al usuario que algo no resulto como debería).

Tengo la confianza de que gracias a su ayuda y colaboración, seguiré aprendiendo. Gracias a todos.

roman
15-07-2005, 21:27:07
¿Puedes indicar algunas de ellas por ver si de una vez por todas puedo entenderlas? Estoy seguro de que son muchas las obviedades que se me escapan, pero no me parece mal que me las hagan saber.


Un par de ejemplos:

Problema: El usuario no puede entrar al sistema, le dice que los datos son incorrectos; su hijo- que sabe computación -dice que el sistema está mal hecho.

Razón: en el recuadro que dice:

Escriba se fecha de nacimiento (dd-mm-aaaa)

el usuario escribe 1983/05/31

(¿Qué no es obvio? ¡Le estoy indicando el formato de la fecha!)

Conclusión: (desafortunadamente) el hijo tiene razón

Solución: antes de mandar los datos al servidor, verificar el formato y mandar un mensaje pertinente en caso de que sea incorrecto.

Problema: El alumno no pudo inscribirse, el sistema nunca le presentó el comprobante.

Razón: El alumno cerró la ventana con el resumen de datos sin oprimir el botón que decía:

"Para terminar su inscripción imprima su comprobante"

Claro que estos errores no encajan directamente con las excepciones (de hecho el del combo tampoco), pero son verídicos y muestran el tipo de cosas que podemos dar por obvias y qe el usuario no las ve.

Y el que sea un formulario de 40x40 no es pretexto. ¿Te imaginas qué pasaría si en un código de apenas unas cuantas líneas, el compilador no tuviera a bien decirnos: "Missing operator or semicolon" ¿Es obvio que los parámetros de una función deben ir separados por comas!

Pero de cualquier forma, una construcción como


try
...
except
end;


jamás debe hacerse. Me parece que ya lo dijo mamcx; al hacer esto escondes todas las excepciones posibles, no sólo las que uno prevee o piensa que pueden suceder.


El usuario vuelve a abrir el formulario, esto es, vuelve a abrir el menú, selecciona la opción oportuna y se le muestra el mismo formulario de antes. Entonces el usuario escribe un número de línea o elige una y zas, se cierra el formulario y se le muestra el número de línea elegido.


Esto me recuerda al experimento del perrito que tiene que abrir una reja con uno de dos botones. Un botón abre la rejay el otro le da un toque eléctrico. Así has-ta-que-se-e-du-que, ¡no faltaba más!

:D


En fin. Yo creo que aquí el tema no era este en absoluto, pues al cabo todo queda reducido a cómo me parece a mí esto y cómo me parece a mí lo otro.

Por el contrario, yo creo que este es precisamente el tema. Abriste el hilo comentando que el mencionado artículo te había hecho por fin entender cómo se usan las excepciones y has visto qe el tema no es tan inmediato y se presta a muchos estilos y circunstancias.

El mismo artículo, a mi no me queda claro.


Yo lo único que he dicho es que he cometido el error que menciona Ian Marteens en no pocas ocasiones, y, efectivamente, reconozco que en muchas ocasiones que utilizé la instrucción try/except no contaba con ningún plan B y a veces terminaba levantando la excepción mediante un Raise ¡dentro de try/except!


Pero, ¿cuál es el error a que se refiere Marteens? Porque a juzgar por su descripción de la cláusula fault en Freya da la impresión de que justamente recomienda propagar la excepción. Para mi, hay excepciones que deen propagarse y otras no, depende de las circunstancias y objetivos.

// Saludos

dec
15-07-2005, 22:03:18
Hola,

Los problemas que me has mostrado roman, aun con ser posibles y todo eso, no tienen nada que ver con lo que yo hago "para dirigir al usuario a una línea". De todos modos te agradezco los comentarios igual.

Por eso he recalcado arriba que estaba refiriéndome a un caso en concreto sobre el que había tomado una decisión, un caso concreto, que, claro está, no tiene porqué parecerse a otros casos concretos, por eso son concretos.


Pero de cualquier forma, una construcción como

try
...
except
end;

jamás debe hacerse. Me parece que ya lo dijo mamcx; al hacer esto escondes todas las excepciones posibles, no sólo las que uno prevee o piensa que pueden suceder.
Bueno, en este caso, me parece a mí que pocas excepciones podrían darse salvando el "EConvertError" presumible y ocultado al usuario porque personalmente lo creí mejor.

De todas maneras ya dije más arriba que había pasado a utilizar la función "TryStrToInt" y ese patrón de uso de try/except no es algo habitual en lo poco que escribo.


Esto me recuerda al experimento del perrito que tiene que abrir una reja con uno de dos botones. Un botón abre la rejay el otro le da un toque eléctrico. Así has-ta-que-se-e-du-que, ¡no faltaba más!
¡Hombre, menuda comparación! Personalmente calculaba que el usuario se diera cuenta del "error" a la primera, de verdad lo digo: no estoy de acuerdo en absoluto de tratar al usuario como a tonto, porque yo soy usuario y a mí no me gusta que me traten como a tonto.

Así que no entiendo eso de "El usuario no es tonto, pero el programa debe estar diseñado para tontos." ¿En qué quedamos? ¿El usuario es tonto o no lo es? Porque si no lo es no podemos diseñar un progama para tonto: ¿en qué quedamos?


El mismo artículo, a mi no me queda claro.
Pero es que me parece normal roman. Poniéndome un tanto en tu lugar prácticamente estoy por aseverar que haría lo mismo que tú en este caso. Creo que lo mismo no lo leen igual dos personas. Una saca unas conclusiones, otra otras.


Pero, ¿cuál es el error a que se refiere Marteens?
¡Pues si es en lo que estamos de acuerdo! En que no deben emplearse patrones como la excepción try/except "vacía", para tapar errores, sin ir más lejos.

Y que tampoco se debe levantar una excepción dentro de una instrucción try/except, pues que sería levantar la misma excepción dos veces: para eso está raise.

Que si no se tiene un plan B, es decir, si no se sabe o no se puede o no se quiere tratar una excepción la instrucción try/except sobra, porque, precisamente, sirve justamente para cuando hay un plan B.

Con plan B se refiere Marteens (http://www.marteens.com) a otra forma de hacer las cosas en caso de que de la primera forma que se pensó no salgan bien: puede que sea de perogrullo pero es que creo que no dirá el referido autor en vano que solamente para un 10% de las excepciones tenemos un plan B.


Porque a juzgar por su descripción de la cláusula fault en Freya da la impresión de que justamente recomienda propagar la excepción
¡Claro! Precisamente porque la gente lo hace mal. Precisamente porque Ian Marteens (http://www.marteens.com) presupone que lo van a seguir haciendo mal quiere él poner un granito de arena para que aún así las cosas puedan salir mejor. Pero te remito al comienzo del artículo, porque el autor lo explica mejor que yo.


Para mi, hay excepciones que deen propagarse y otras no, depende de las circunstancias y objetivos.
Pues como en esto, salvando las distancias que puede haber entre tú y yo mirando lo que tú sabes y lo que yo no sé, también estamos de acuerdo, digo, que, al cabo al cabo la suma de acuerdos es mayor que la de desacuerdos.

Actualización:


Personalmente calculaba que el usuario se diera cuenta del "error" a la primera (...)

¡Y que además no pensaba soltarle ninguna descarga! Es por esto que actualizo mi mensaje, para preguntar, ¿sabe alguien si, de la misma manera que puede hacerse sonar un ¡Beeep! es posible soltar una descarga al usuario de una aplicación hecha con Delphi? Es broma, a mí no se me ocurre pensar algo así.

ContraVeneno
15-07-2005, 22:46:43
Originalmente publicado por dec
Así que no entiendo eso de "El usuario no es tonto, pero el programa debe estar diseñado para tontos." ¿En qué quedamos? ¿El usuario es tonto o no lo es? Porque si no lo es no podemos diseñar un progama para tonto: ¿en qué quedamos?
El siguiente ejemplo ilustra de manera MUY CLARA la justificación para la frase: "El usuario no es tonto, pero el programa debe estar diseñado para tontos" y cito:

Originalmente publicado por Roman
¿Te imaginas qué pasaría si en un código de apenas unas cuantas líneas, el compilador no tuviera a bien decirnos: "Missing operator or semicolon" ¿Es obvio que los parámetros de una función deben ir separados por comas!

Estoy totalmente seguro que un compilador no es apto para tontos, sin embargo, debe estar preparado por si ocurre una tontería.

dec
16-07-2005, 00:49:04
Hola,

Aunque entendiendo por dónde quieres ir, si no estoy equivocado, no puedo estar de acuerdo contigo en que el cierre de una instrucción, esto es, el punto y coma sea una tontería.

Prueba de ello es el aviso del compilador, más allá, prueba de ello es que el compilador no continuará adelante hasta que no se solucione "esa tontería".

¿Alguien puede explicarme qué es un programa diseñado para tontos? ¡No conozco ninguno! Si no es un programa "malicioso", que busca la ingenuidad del usuario o su carencia de conocimientos, para vete a saber qué.

Cualquier programa está pensado para alguien y aun alguienes. Y se presupone a ese alguien la capacidad de entender lo que quiere hacer. Porque un programa puede ser al mismo tiempo una herramienta: el usuario habrá de saber qué quiere hacer con ella.

Si PhotoShop, por poner un caso, fuera un programa hecho para tontos hasta yo podría hacer lindas imágenes, pero esto no es así: prueba de que PhotoShop no es un programa para tontos.

Vale. Podría hacer cualquier cosa que pareciera una imagen, pero todos sabemos lo que da de sí un programa como PhotoShop y ni por pienso sabría yo hacer algo como lo que por ejemplo estoy recordando ahora.

Delphi no es un programa para tontos. ¿O sí? Yo diría que no. Pero es un programa. Yo tengo entre manos un programa ahora y no lo estoy haciendo para tontos, puedo prometerlo. Porque no sabría cómo hacerlo, aunque quisiera.

Los asistentes para Windows (cualquiera de ellos) no están hechos para tontos. Simplifican, esconden, "hacen cosas". Si el usuario no quiere ir más allá yo no creo que sea tonto, es que simplemente no necesita más. ¿Para qué darle lo que no necesita? No es tonto: sabe lo que quiere.

Es verdad que no siempre (http://buscon.rae.es/draeI/SrvltGUIBusUsual?LEMA=tonto&TIPO_HTML=2&FORMATO=ampliado&sourceid=mozilla-search). lamentablemente.

En todo caso creo que esto sería para debatirse, en el sentido de que seguramente aún no tenemos claro lo que el uno piensa que piensa el otro (por lo menos yo me incluyo en esa cuenta) y así será cuestión de dejar claro que, pase lo que pase, esto no pasaría nunca a mayores.

¡Pero yo no hago programas para tontos, que conste! ;)

marceloalegre
18-07-2005, 14:41:01
Lo que dice roman es correcto, sin seguir hablando de lo mismo, eso tiene que ser asi: LOS PROGRAMAS TIENEN QUE SER HECHOS PARA TONTOS...
es increible, las malas intepretaciones que puede tener la gente de las cosas!
yo basicamente utilizo mucho los try/except y siempre tenes q usar plan b,, muchas veces un aviso,, SIEMPRE, siempre los uso..

Saludos!

mamcx
18-07-2005, 15:49:10
Me parece que el asunto se aclara muy facil. En parte, estoy de acuerdo que las personas tienen mucho potencial, y tratarlas de forma despectiva no es lo mejor. Por otro lado, el que una persona tenga un PHd en Ingenieria quantica-nuclear de plataformas intelesterales biologicamente interconexas, no lo hace *necesariamente* capacitado para usar DOS y darle dir *.* ;) Si esta persona no conoce el programa/sistema se vera tan tonto como nosotros tratando de definir que es la fisica quantica....

Me parece que podriamos extractar varias lecciones:

1- Ocultar complejidad: Bueno. Si voy al medico necesito que me responda : "Nene, tenes como una fiebre altisima, ve!. Por si te preguntan tenes una bacteria amorfa, llamada niMeAcuerdoComoSeLlama piluris bla bla, pero en fin, a la camita y mucha naranja!". Es mejor "El archivo Tata.tutu no se encuentra" a lo que sea que diga el compilador/OS.

2- Evitar/Corregir el problema: Bueno. Como dice DEC, que saque un mensaje de error por SIMPLEMENTE seleccionar un item en una lista, no solo es (ahi si) tonto, sino que deberia tomarse como una ofensa capital! Es responsabilidad de la persona con la mejor informacion y mas cercana a la solucion (o sea nosotros) manejar el asunto.

3- Ignorar/Ocultar informacion: MALO. El asunto es que hay NIVELES a la hora de dar informacion... Debe saber el usuario FINAL TODO el mensaje de error, con call stack, version del compilador, mensaje de excepcion, direccion del servidor, etc??? (gracias, dira el hacker!!!) Normalmente, no. Debe saber todos y cada uno de los errores que saca el programa? Indiscutiblemente NO.

Pero lo que le puede interesar al ADMINISTRADOR del sistema/red, es muy diferente. Y lo que necesita saber el PROGRAMADOR es mucho mas. Es por eso que unas cosas deben sacar mensaje de error, escandalosamente (= TODO LO QUE NO ESPERABAMOS) otras debe ser mensajes agradables (= LO QUE EL USUARIO ESPERARIA QUE SE LE INFORMARA, ie: Que el archivo no se encontro donde se le dijo) otras deben quedar en un log (para el personal tecnico) y tal vez el resto solo se debe ver en una version del ejecutable/exe ESPECIAL para depuracion, con los assert activados, con una estrategia AGRESIVA de logeo de mensaje y sin nada que enmascare el problema (desactivando los mensajes lindos, por ejemplo). Esto si que le salva la vida cuando se requiere...

4- Dar una respuesta general a una pregunta especifica: MALO. Si ya sabemos que va a sacar un mensaje a la hora de convertir el numero de caracteres a integer, porque poner un un manejo general de la excepcion? SI YA SABEMOS QUE VA A PASAR, pues digamoselo al compilador! Y de esa manera, el codigo queda explicito: Si pones EConvertError el proximo programador vera la intencion de la excepcion de forma clara.

roman
01-08-2005, 17:30:54
En parte, estoy de acuerdo que las personas tienen mucho potencial, y tratarlas de forma despectiva no es lo mejor


Pero, ¿quién habló de tratarlas de forma despectiva? Lo dicho. Cuando el compilador me saca a mí un mensaje diciéndome que falta un punto y coma no me siento tratado despectivamente. Por el contrario, si el compilador, o cualquier otro programa me avisa rápida y oportunamente de un dato mal ingresado, por tonto que sea, más bien me siento agradecido.

// Saludos

Lepe
01-08-2005, 18:13:13
Cuando el compilador me saca a mí un mensaje diciéndome que falta un punto y coma no me siento tratado despectivamente
Yo si. :D :D :p ;)

mamcx
01-08-2005, 18:27:18
No me referia a sacar los mensajes (o no), sino a la actitud que uno tiene hacia los demas (en este caso los usuarios o clientes).



Cuando uno considera que estos son "tontos", la imagen que se tiene afecta de una u otra manera la forma en como hacemos las cosas. Otra cosa es reconocer que las personas, incluso las que en teoria son inteligentes, puedan hacer cosas tontas de vez en cuando.

Y a veces, realmente hacemos que nuestros usarios actuen de forma muy tonta. Un concepto que lei, y es que una manera de hacer que la gente (=usuarios) sean un poco menos miserables (osea mas felices!) es darle una sensacion de control...



Cuánto más sientes que puedes controlar tu entorno y que las cosas que haces funcionan, más feliz eres. Si estás frustrado, enfadado y contrariado, es porque probablemente te ha ocurrido algo que no puedes controlar: aunque sea algo pequeño. La barra espaciadora de tu teclado no va bien. Cuando tecleas, algunas palabras se quedan pegadas. Esto es frustrante, porque le has dado al espacio y no ha pasado nada. La llave de tu casa no funciona bien. Cuando intentas girarla, se atasca. Otra pequeña frustración. Estas cosas se acumulan; estas son las cosas que nos hacen infelices día a día. Incluso aunque parezcan demasiado insignificantes para explayarse con ellas (quiero decir, hay gente en África muriéndose de hambre, por el amor de Dios, no me puedo enfadar con la barra del espacio), no obstante, afectan a nuestro humor.



Este articulo de Joel (español) me gusto mucho:

http://spanish.joelonsoftware.com/uibook/chapters/1.html

Es sobre como hacer interfaces de usuario, por ejemplo, si estoy haciendo algo tonto, pero no recibo, de alguna manera, indicacion de ello, entonces me voy a sentir infeliz.

Para un usuario (generalmente), los programas deberian de ser como la experiencia de un buen carro: Excelente suspencion, frena cuando se le dice, pita si se le va a acabar la gasonlina, etc... Para un programador, debe ser como manejar un avion: Lucecitas y pitidos por todos lados, porque el grado de posibles errores es mayor...



Los mensajes de error y la manera como se manejan las excepciones pueden ayudar o desfavorecer el grado de control de un usuario sobre el programa. Para un programador, se necesita los mensajes mas constantemente, mas visiblemente y mas informativamente. Realmente me frustra que me saque el Delphi un Exeption at addres 0x8.... que no me dice nada, pero es peor que no lo haga...



Los mensajes de error pueden dar mas control, bien usados.





"El archivo tutu.tata no existe" Ok, esta bien, eso lo puedo manejar, si algo, le pregunto al que sabe de sistemas: Estoy en control.



El programa se cierra sin avisar! Eso si es frustrante, no se que hacer (hice algo mal? Que?) El windows tiene un virus! A correr el antivirus. Listo. Nada. Desfragmentar? Ok. Vuelvo al programa, hago lo mismo. Se cierra. Formateo? Pregunto, no me dicen nada... arrghhhh!!!!!



"El formato de la fecha es incorrecto" Ok, no sabia que las fechas tenian formato: Llamo a soporte tecnico y me dicen que hago. Estoy en control.



La fecha se ingreso, sin verificar. Los saldos contables NO CUADRAN!. Me equivoque? Reviso todas mis transacciones. ESTAN BIEN! Reviso otra vez?? El jefe me hecha la culpa! LLamo a soporte tecnico (sinceramente no sabran todavia)...


En fin. Es la idea... Volviendo a la actitud: Muy estupido pensar que el defragmentar CORRIGE un problema-En serio hay usuarios que luego de hablar con tantos tecnicos piensan que la ruta a la solucion es: Antivirus, Degramentar, reinstalar- Pero que se le va a hacer: Como puede saber que paso? Sin un mensaje de error, asi sea un Exception address at 0x8000 que saque DENTRO del programa, todo se puede pensar... Es por eso que volviendo al temas: Los errores no se pueden ocultar. Solo se debe filtrar la cantidad, frequencia y alarma de los mismos, es nuestra responsabilidad. Y si no hay tiempo para hacer eso: No enmascarar los errores. Al menos los errores escandalosos permiten tener un grado, aunque pequeño, de control, un camino mas probable de solucion...

roman
01-08-2005, 18:45:47
Creo entonces, que estamos totalmente de acuerdo. En mi opinión las aplicaciones deben estar hechas a prueba de tontos pero sin que esto signifique tratar al usuario como tal. Me parece muy atinada tu observación referente a la sensación de control, y esto aplica a toda la interfaz en general. Una aplicación puede ser muy buena pero si no se diseña la interfaz pensando en el usuario final- quien es el que tendrá que lidiar con ella día con día -gran parte de su valor se pierde. A no ser que no haya otra opción, yo, como usuario, generalmente escojo aplicaciones potentes pero que de entrada den la sensación (y lo sean) de ser fáciles de usar.

// Saludos

trohan
13-02-2008, 17:02:49
Hola estoy tratando de hacer un programita que me escanee la red y que me borre el documents and settings de las maquinas encontradas. Mas o menos he logrado parte de esto, pero me da error cuando trata de borrar al usuario que esta logueado y algunos otros. Quisiera saber de que forma se puede evitar estos errores para que el programa no se detenga y continue borrando. Es decir como se usaria el try...except aqui.

ixMike
13-02-2008, 17:06:46
... borre el documents and settings de las maquinas encontradas...

:confused::eek::D:D:D:D:D jejeje


¿cuanto tardarán? :rolleyes:

sevilla19742
05-03-2008, 18:23:07
¿Te imaginas qué pasaría si en un código de apenas unas cuantas líneas, el compilador no tuviera a bien decirnos: "Missing operator or semicolon" ¿Es obvio que los parámetros de una función deben ir separados por comas!
sevilla19742