Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Otros entornos y lenguajes > Lazarus, FreePascal, Kylix, etc.
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #21  
Antiguo 31-05-2015
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
Sigo avanzando.
Esta nueva propuesta está dentro de todo funcionando, según las pruebas que he estado llevando a cabo. El diseño si captura las excepciones generadas por TFileStream y genera las propias.

Un típico modo de uso, sería algo:

Código Delphi [-]
try
  LogOperation('SaveMatrix');
  Converter.SaveMatrix(myM1, TArrayOrientation(rgDir.ItemIndex + 1), myFile);
  LogFile(myFile);
 except
  on E: EConverterException do
    LogException(E);
end;

LogOperation() y LogException() son dos métodos que he implementado en un sistema básico para prueba de caja blanca (y algo de "caja gris") que van registrando en un Memo a modo Log cada test que se realiza.
En el caso de LogException() se busca capturar las excepciones y mostrar el nombre de la clase y el mensaje.

He advertido que el algoritmo tiene dos bugs que ya he procedido a eliminar:
1. Al momento de hacer una lectura del Identificador inicial debiera de invocar, por seguridad es apropiado hacer previamente un Seek(0, soFromBeginning)
2. Al momento de proceder a leer los datos de igual forma se debe posicionarse en el primer elemento y para ello es necesario un Seek(INI_DATA_M, soFromBeginning) siendo INI_DATA_M una constante apropiada para el caso de un archivo diseñado para matrices.

Estos mismos problemas detectados fueron eliminados en el método LoadVector.

Esta versión optimiza el indexado del posicionamiento al leer la data. Inicialmente procedía con dos ciclos anidados. Gracias a la tan bella matemática se puede prescindir de un ciclo y directamente hacer la correspondencia entre el índice Idx del dato y su posición [i, j] en la matriz tanto en un lectura columna por columna como fila a fila.

Estoy abierto a las sugerencias.

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #22  
Antiguo 01-06-2015
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Hola Marcelo.

Este fin de semana tuve algo de tiempo libre para leer con detenimiento todo lo planteado por ti y Mario. ¡Cuántas cosas me gustaría decir! Como procurar la redacción en un sólo idioma y de manera más comprensible. O evitar en lo posible escribir métodos de más de 20 líneas de código. Pero intentaré enfocarme en lo principal de tu planteamiento técnico.

El uso canónico de un bloque Try-Finally es:
Código Delphi [-]
  // 1. Código para hacer algo que deseamos luego deshacer, ocurra lo que ocurra.  Crear, abrir, poner...
  Try
    // 2. Código que opera sobre lo hecho por el punto 1 y que tiene potencial de elevar una excepción.
  Finally
    // 3. Código que deshace lo hecho antes del Try.  Destruir, cerrar, quitar...
  End;
El uso canónico de un bloque Try-Except es:
Código Delphi [-]
  // 4. Código para hacer algo que, en caso de ocurrir un problema, quisiéramos deshacer.  Crear, abrir, poner...
  Try
    // 5. Código que podría generar alguna excepción sobre la cual deseamos tener control.
  Except
    { 6. Código que deshace lo hecho antes del Try (destruir, cerrar, quitar...) y/o trata de forma particular la
      excepción generada (por clase, código de error, etc.). }
  End;
El punto 6 consiste, generalmente, en tomar alguna diligencia de control, liberar algún recurso que previamente se cargó en memoria, registrar o reportar una bitácora de incidencias, o anexar/convertir la excepción en otra excepción. Pero casi siempre este tratamiento termina elevando una excepción (propagando la misma o instanciando otra) al llamador. En algunas ocasiones el punto 4 podría ser opcional.

Por otra parte, además de la muy mala práctica de sofocar excepciones (atraparlas solo "para que no estorben"), existe cierta práctica no muy buena (y afortunadamente poco difundida) de atrapar una excepción para convertirla en un código de resultado. Nunca hagas eso a menos que no tengas alternativa. Es más válido que un método de aplicación envuelva a un método de API, atrapando una excepción de esa API para transformarla en una excepción más propia de la aplicación (algo que ya veo haces). Aunque también es válido dejar que la excepción original aparezca en la pantalla del usuario. Lo más malo es que aparezca cualquier mensaje de error, no que el mensaje de error sea algo "geek". Claro, podría ser deseable que las excepciones digan algo entendible, pero no olvidemos que son eso: excepciones que no debieran presentarse.

Dada la introducción anterior, me permito poner en seudocódigo cómo podría ser tu método LoadMatrix:
Código Delphi [-]
LoadMatrix
Begin
  CheckMatrix (M);  // CheckMatrix no sólo verifica, también eleva excepción en caso de encontrar invalidez.
  —Punto 1. Crear FileStream

  Try
    —Punto 2. Uso del FileStream:
    Try
      —Punto 5. Leer archivo, verificar datos y elevar excepciones de tu clase en caso de inconsistencias.
    Except;
      —Punto 6. Atrapar excepciones conocidas o esperadas de FileStream y convertirlas en una excepción de tu clase.
    End;
    // Termina punto 2 (uso del FileStream).
  Finally3. Destruir FileStream
  End;
End;
Espero que esta participación sea de alguna ayuda.
Responder Con Cita
  #23  
Antiguo 01-06-2015
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Ah, pero resulta que el punto 1, es para ti punto 5 también. Entonces apliquemos la misma lógica:
Código Delphi [-]
LoadMatrix
Begin
  CheckMatrix (M);  // CheckMatrix no sólo verifica, también eleva excepción en caso de encontrar invalidez.

  Try
    —Punto 1 y 5. Crear FileStream

    Try
      —Punto 2. Uso del FileStream:
      Try
        —Punto 5. Leer archivo, verificar datos y elevar excepciones de tu clase en caso de inconsistencias.
      Except;
        —Punto 6. Atrapar excepciones conocidas o esperadas de FileStream y convertirlas en una excepción de tu clase.
      End;
      // Termina punto 2 (uso del FileStream).
    Finally3. Destruir FileStream
    End;
  Except
    —Punto 6. Atrapar excepciones esperadas de la creación del FileStream y convertirlas en una excepción de tu clase.
  End;
End;
¿Mucha anidación?...¿Recuerdas lo de tener un límite de líneas? Divide un método largo en varios cortos y vencerás toda complejidad.

Última edición por Al González fecha: 01-06-2015 a las 19:09:56.
Responder Con Cita
  #24  
Antiguo 01-06-2015
Avatar de nlsgarcia
[nlsgarcia] nlsgarcia is offline
Miembro Premium
 
Registrado: feb 2007
Ubicación: Caracas, Venezuela
Posts: 2.206
Poder: 21
nlsgarcia Tiene un aura espectacularnlsgarcia Tiene un aura espectacular
Alberto,

Cita:
Empezado por Al González
...Msg #22 y Msg #23...
Excelente manejo de las excepciones

Nelson.
Responder Con Cita
  #25  
Antiguo 01-06-2015
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
Hola Al.
Te agradezco tu aporte.

De lo que veo en tu propuesta, aplicas un triple try anidado y separas la excepción de la creación del FileStream de las excepciones que puede arrojar un Read o Write, y dejas a un try-finally intermedio cuando se dan situaciones "segura" y por tanto proceder a finalizar el Free.

No se diferencia mucho de la 2da propuesta que logré diseñar. Basicamente la diferencia radica en donde capturar y lanzar las excepciones propias.

Ayer estuve haciendo más pruebas y pude apreciar que no necesito relanzar la excepción como me estaba preguntando ¡Lo hace! Mi miedo era que el raise de EInvalidFileArrayFormat y/o el de EInconsistArray fuera capturado por el except y no se mostrara dicha excepción y tuviera que añadirla en la lista y volver a aplicar un rise. La excepción "pasa de largo" y efectivamente se termina recibiendo desde el "lado cliente".

Aparentemente todo funciona bien. La aplicación de prueba me ha permitido evaluar las alternativas, y en ciertos casos forzando algunas situaciones como un fallo de lectura/escritura. Se detectan las excepciones y se lanzan las adecuadas.

Tendría que probar tu alternativa, pero tengo que continuar con el trabajo. Por el momento tengo en suspenso tu propuesta. Y será el camino hacia una nueva versión si lo amerita, o bien en cuanto pueda disponer de tiempo y se justifique algo más seguro.

CheckMatrix no ha sido diseñada para lanzar excepciones. Pertenece a una unidad (que junto a otras forman un gran módulo) que contiene cientos de procedimientos y funciones dedicadas a álgebra lineal y otras cosas más. Su diseño, a la vieja escuela (paradigma estructurado), no ameritaba algo OO por lo que CheckMatrix, por ejemplo, se limita a ofrecer variables de control como ser el código de error generado y adicionalmente la dimensión de la matriz.
Es una unidad que ya ha alcanzado un grado de madurez bastante elevado y tiene casi 3000 líneas de código. No se malgasta en clases, excepciones, va a lo directo. Su diseño a sido dual: ofrece procedimientos bajo situaciones ideales, y además ofrece funciones y otros métodos de evaluación y control para aquellos casos en los que se necesita ciertas evaluaciones previas.

Las clases/módulos clientes de esta gran biblioteca si quieren pueden seguir el diseño estructurado o bien, aprovechar el poder OO para situaciones más complejas.

Los mensajes de algunas excepciones, si te fijas en mi 2da propuesta, aplican a un Format() a un string. Entre los parámetros paso el mensaje de la excepción original. De este modo el texto de la excepción que arrojo lleva consigo no sólo el texto para el contexto esperado (el Converter) sino además información adicional que provee sobre el TFileStream (aunque el texto de éstas más bien es básico según lo que vi en su código).

Lo de escribir en un único idioma, si es que te lo preguntas el porque uso comentarios en español y código en inglés, es porque ya me acostumbré asi. La idea es que los comentarios me ayuden a entender lo que tengo y para ello recurro al español. Después de todo es trabajo personal.

Lo que evitar algoritmos de más de 20 líneas lo tengo presente. Pero en ocasiones debemos extendernos más. Tengo por ejemplo en otra unidad un procedimiento que tiene 130 líneas de código. Se podría particionarlo, pero ya de por sí las operaciones se hacen de manera óptima y goza de buena velocidad. De particionarlo, algunas partes se estarían llamando cientos de veces. Preferí centrar todo y se ejecute en un único procedimiento antes que estar lidiando con las vueltas de código repartido en varios.

Te agradezco tu ayuda porque siempre se aprende algo nuevo. Seguro que esta lección del triple-try la pongo en práctica para otro caso, que tiene cierta semejanza con el TArrayConverter. Es otra especie de conversor pero para otras clases (quizá más manejables que el TFileStream... espero) y finalidades.

Seguramente nos mantendremos en contacto.

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #26  
Antiguo 01-06-2015
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
¡Mucha suerte, Marcelo!

Por cierto, fu forma de escribir y tus comentarios de código me parecen bien. Lo del idioma fue un llamado a la comunidad en general para ser un poco más formales con las explicaciones técnicas, evitando el spanglish en algo tan valioso como la divulgación técnica.

Al González.

P.D. Nelson, gracias por ese mensaje.
Responder Con Cita
  #27  
Antiguo 01-06-2015
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
Cita:
Empezado por Al González Ver Mensaje
¡Mucha suerte, Marcelo!

Por cierto, fu forma de escribir y tus comentarios de código me parecen bien. Lo del idioma fue un llamado a la comunidad en general para ser un poco más formales con las explicaciones técnicas, evitando el spanglish en algo tan valioso como la divulgación técnica.

Al González.

P.D. Nelson, gracias por ese mensaje.
Muchas gracias Al.
Ojalá la suerte fuera contagiosa y se transmitiera por cables de red. Necesito ¡ y mucha!

Me alagas demasiado por mi escritura de código. Aún tengo mucho por pulir, sobre todo habiendo perdido mucha práctica por haber tenido que dejar por tanto tiempo la programación. Y si de pulir se trata ahora que veo de nuevo mi código creo que puedo reducir 2 cálculos en uno sólo. Cuando calculo los índices i y j aplico DIV y MOD según sea el caso. Esto se puede hacer de manera efectiva y rápida con DivMod.

En lo de ser lo más técnico posible te apoyo. Hay que hacer lo posible por emplear las palabras formales, pero entiendo que en ocasiones por las prisas, cansancio, el no poder encontrar las expresiones en el momento (que pasa... y seguido) y hasta algo de desconocimiento, nos juegan en contra y nos mandamos cada una.

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
Respuesta



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

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Capturando excepciones en un archivo de texto noob Varios 5 20-02-2009 09:47:46
Duda sobre posibles excepciones en una desconexión de un socket noob Varios 0 13-02-2009 19:33:14
TMaskedit, con posibles excepciones en el formato grotero76 OOP 6 31-01-2008 13:49:23
Cómo utilizar consultas con DISTINCT de forma correcta dec MySQL 9 19-09-2006 17:50:47
lista de todas las posibles excepciones maruenda Varios 1 06-12-2004 22:31:02


La franja horaria es GMT +2. Ahora son las 22:12:36.


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