Club Delphi  
    Paypal   FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Coloboración Paypal con ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 15-07-2005
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.142
Poder: 36
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,

Cita:
Empezado por roman
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.
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
  #2  
Antiguo 15-07-2005
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por dec
¿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
Responder Con Cita
  #3  
Antiguo 15-07-2005
Avatar de lucasarts_18
lucasarts_18 lucasarts_18 is offline
Miembro
 
Registrado: mar 2005
Ubicación: Villa Alemana,Chile
Posts: 1.087
Poder: 23
lucasarts_18 Va por buen camino
Hola:

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

Código Delphi [-]
 
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..
Responder Con Cita
  #4  
Antiguo 15-07-2005
Avatar de jachguate
jachguate jachguate is offline
Miembro
 
Registrado: may 2003
Ubicación: Guatemala
Posts: 6.254
Poder: 30
jachguate Va por buen camino
Hola.

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

Cita:
Empezado por lucasarts_18
Código Delphi [-]
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

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 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.

Código Delphi [-]
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.

Cita:
Empezado por lucasarts_18
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.

__________________
Juan Antonio Castillo Hernández (jachguate)
Guía de Estilo | Etiqueta CODE | Búsca antes de preguntar | blog de jachguate
Responder Con Cita
  #5  
Antiguo 15-07-2005
Avatar de mamcx
mamcx mamcx is offline
Moderador
 
Registrado: sep 2004
Ubicación: Medellín - Colombia
Posts: 3.941
Poder: 27
mamcx Tiene un aura espectacularmamcx Tiene un aura espectacularmamcx Tiene un aura espectacular
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!)
__________________
El malabarista.
Responder Con Cita
  #6  
Antiguo 15-07-2005
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.142
Poder: 36
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,

Cita:
Empezado por roman
¿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 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:

Cita:
Empezado por Marteens
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:
Código Delphi [-]
  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 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!


Cita:
Empezado por mamcx
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:


Código Delphi [-]
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.
__________________
David Esperalta
www.decsoftutils.com

Última edición por dec fecha: 15-07-2005 a las 15:00:52. Razón: (corrección del texto)
Responder Con Cita
  #7  
Antiguo 15-07-2005
Avatar de vtdeleon
vtdeleon vtdeleon is offline
Miembro
 
Registrado: abr 2004
Ubicación: RD & USA
Posts: 3.236
Poder: 26
vtdeleon Va por buen camino
Cita:
Empezado por dec
Código Delphi [-]
   var
     i: integer;
   try
     i := cbLinea.text;
   except
   end;
No creo que eso Compile :P
Código Delphi [-]
    var
      i: integer;
    try
      i := StrtoInt(cbLinea.text);
    except
    end;
__________________
Van Troi De León
(Not) Guía, Code vB:=Delphi-SQL, ¿Cómo?
Viajar en el tiempo no es teóricamente posible, pues si lo fuera, ya estarían aqui contándonos al respecto!
Responder Con Cita
  #8  
Antiguo 15-07-2005
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.142
Poder: 36
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,

Sí; llevas razón vtdeleon, efectivamente, hay que utilizar "StrToInt" para el caso.
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
  #9  
Antiguo 15-07-2005
Avatar de yusnerqui
yusnerqui yusnerqui is offline
Miembro
 
Registrado: mar 2004
Ubicación: Cuba
Posts: 679
Poder: 23
yusnerqui Va por buen camino
Pues ya que hablamos del tema, les propongo este artículo el cual lo aborda de forma muy amplia, y saquen sus propias conclusiones


Saludos
__________________
Lo importante no es llegar primero, sino saber llegar.

Para que puedas llegar mejor lee la Guia de Estilo

Responder Con Cita
  #10  
Antiguo 15-07-2005
Avatar de mamcx
mamcx mamcx is offline
Moderador
 
Registrado: sep 2004
Ubicación: Medellín - Colombia
Posts: 3.941
Poder: 27
mamcx Tiene un aura espectacularmamcx Tiene un aura espectacularmamcx Tiene un aura espectacular
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....
__________________
El malabarista.
Responder Con Cita
  #11  
Antiguo 15-07-2005
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.142
Poder: 36
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,

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

Código Delphi [-]
 var
   i: integer;
begin
   try
     i := StrToInt(cbLinea.Text);
   except
   end;
 end;

Cita:
Empezado por mamcx
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.

Cita:
Empezado por mamcx
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.

Cita:
Empezado por mamcx
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.
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
  #12  
Antiguo 15-07-2005
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
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:

Código Delphi [-]
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.

Cita:
Empezado por dec
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
Responder Con Cita
  #13  
Antiguo 15-07-2005
Avatar de jachguate
jachguate jachguate is offline
Miembro
 
Registrado: may 2003
Ubicación: Guatemala
Posts: 6.254
Poder: 30
jachguate Va por buen camino
Cool

Cita:
Empezado por mamcx
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.

Cita:
Empezado por mamcx
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.

__________________
Juan Antonio Castillo Hernández (jachguate)
Guía de Estilo | Etiqueta CODE | Búsca antes de preguntar | blog de jachguate
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro


La franja horaria es GMT +2. Ahora son las 03:54:44.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi