![]() |
![]() |
| Paypal | FTP | CCD | Buscar | Trucos | Trabajo | Foros |
|
|||||||
| Registrarse | FAQ | Miembros | Calendario | Guía de estilo | Buscar | Temas de Hoy | Marcar Foros Como Leídos |
![]() |
|
|
Herramientas | Buscar en Tema | Desplegado |
|
|
|
#1
|
||||
|
||||
|
Hola Marcelo.
Cuatro cosas: 1. Gracias por regresar al foro. Da gusto ver cómo durante el último año han estado integrándose y reintegrándose muchos colegas en el Club. Muy de la mano, es evidente que el rescate de Delphi se va consolidando (y por añadidura el repunte de otros lenguajes Object Pascal). ![]() 2. En México tienes abiertas la puertas de mi humilde hogar, si te agrada la idea y te es posible viajar, no tienes más que avisar. Y si es necesario buscamos la forma de facilitarte el traslado. Entre nosotros hay mucho código y conocimiento que podríamos compartir presencialmente. En fin, es una invitación a que te desconectes aunque sea unos meses de aquel ambiente. 3. Sostengo los comentarios técnicos que escribí hace varios años en el hilo que refieres, incluso ahora estoy más convencido de ellos. 4. Si este fin de semana no me distraen mucho acá, revisaré con detenimiento tu caso y responderé aquí con lo que pueda ayudar. Saludos. Al.
__________________
Tras casi seis años de trabajar para una empresa alemana como desarrollador Delphi, se vieron forzados a dejarme ir (temas presupuestales). Así que ahora estoy abierto a escuchar nuevas ofertas. |
|
#2
|
||||
|
||||
|
Cita:
De lo que estoy entendiendo de tu propuesta, es hacer de TArrayConverter una especie de Adapter del TFileStream y que en caso de poder crear una instancia de TArrayConverter proceda a utilizarla. De ser así en realidad no soluciona el mayor problema: que no se pueda crear el TArrayConverter es lo mismo que no se pueda crear el TFileStream. Tal diseño directamente pone en evidencia que no tiene sentido la clase y directamente se haga uso de TFileStream ¿no crees? Entonces las clases que eran clientes de TArrayConverter, que directamente, hagan uso de TFileStream. Si yo estoy entendiendo mal el concepto por favor hazmelo saber. ![]() La intención de contar con TArrayConverter es que ésta pueda centrar el trabajo común de leer y guardar de archivos. Otros módulos/clases tienen ya sus propios juegos de matrices y vectores. Entre ellas se comparten algunas estructuras comunes, y otras son propias. Cada módulo/clase aplica sus instrucciones sobre estas estructuras y varias son de gran importancia e interés poder materializarlas en un archivo para usos posteriores. Debido a ello es que vi natural el que exista una instancia de TArrayConverter a modo singleton que reciba las estructuras de cualquiera de estos módulos/clases y haga lo que mejor sabe hacer. No consideré prudente que un LoadMatrix() regrese el tipo de dato TMatriz como sugieres debido a que esto condiciona a que el conflicto de intereses entre quien es el dueño de la matriz y no incluirle lógica que ya es más propia de otras clases. Por cuestiones de operatoria y diseño es raro que se necesite un intento de leer y/o guardar archivos de forma concurrente o simultáneo. Generalmente se da cierto orden secuencial. Pero por seguridad, y para esos casos en que tales archivos sean grandes (según pruebas algunos archivos si que serán grandes... entre los 4MB a 10MB en promedio pero puede darse situaciones de mayor tamaño), es que vi sano el añadir la propiedad InUse o alguna tipo flag que indique que el objeto está ocupado trabajando en ese momento. De ese modo pretendía dos cosas: 1. Que TArrayConverter cree el TFileStream y lo libere cuando se necesite trabajar con algún archivo (recién me percato que posiblemente sea un error disponer de un atributo privado) 2. Que al disponer de esta propiedad InUse permita cierto "relajo" a la aplicación y permita darle respiros ante la cantidad de operaciones que se realizan entre cada lectura/guardado de archivos. Cita:
Si bien tengo más presencia en los últimos tiempos en DA, no quiere decir que no estime a algunos compañeros. Como te dije: la comunidad Delphi es una. Te agradezco la invitación, y admito que tengo ganas de buscar otros aires. Ganas no me faltan de ir a México y visitar a toda la pandilla, pero por ahora no podrá ser. Ya en los próximos días debo volver a casa, acá tengo a conocidos que me están dando apoyo pero también me ponen en ultimatum para que concrete para éste Lunes 1 (fecha en que posiblemente viaje). Ni modo, no es fácil explicar a quien no está en el tema que un sistema no puede estar a medias. No es que se puede dejar como esté y que ande. Deberé regresar y ver el modo de terminarlo allí. No pensé que esto me tomara tanto tiempo. Necesito mínimo otra semana más si no hay más imprevisto y todo sale a la perfección. Te agradezco cualquier recomendación. Les comento a ambos que en lo que estoy pensando es aplicar una lógica que siga este diseño:
Lo que estoy divagando es ver como adaptar el algoritmo que puse en mi primer post a este esquema lo más limpio posible. ¿Que piensan? De este modo alguna clase que llame a ésta haga algo como:
Y la versión análoga para una lectura. ¿Como lo ven? Saludos, |
|
#3
|
||||
|
||||
|
Actualizo el hilo para comentarles que he hecho algunos cambios y redefinido un poco el diseño de la clase. He intentado hacer que el código siguiera la estructura de dos try anidados. El try-finally interior asume las condiciones ideales, y el exterior es un try-except para capturar las posibles excepciones que podrían darse.
la 2da versión, y quizá un poco más pulida, es:
La duda que me surge, es si el try-except externo captura las excepciones arrojadas por el interno, y de ser así debiera de relanzarlas. El compilador no protesta, pero no he probado el código por falta de tiempo y ya me gana el cansancio. En la versión anterior, al evaluar el estado de la matriz con CheckMatrix() primero verificaba el resultado de dicha operación y a posterior comprobaba las variables de control que éste regresa (RM, CM) con la información leída del Header para determinar si efectivamente la matriz y el archivo tengan la misma dimensión y por tanto ni sobre ni falten datos. Ahora directamente no hago esta distinción y asumo que ambos escenarios son del mismo tipo de error. Delego en la clase cliente la tarea de verificar tanto que la matriz efectivamente esté disponible (y por tanto al invocarse a CheckMatriz se lea su tamaño correcto) como la de que controle lo mejor posible que sus archivos estén en orden. Por diseño de CheckMatriz cuando la evaluación falla regresa un "código" de error distinto a OPERATION_DONE las variables de control se establecen en -1. Rediseñé las excepciones, y propuse una nueva forma de nombrarlas. Saludos, |
|
#4
|
||||
|
||||
|
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:
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, |
|
#5
|
||||
|
||||
|
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: El uso canónico de un bloque Try-Except es: 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: Espero que esta participación sea de alguna ayuda. ![]()
__________________
Tras casi seis años de trabajar para una empresa alemana como desarrollador Delphi, se vieron forzados a dejarme ir (temas presupuestales). Así que ahora estoy abierto a escuchar nuevas ofertas. |
|
#6
|
||||
|
||||
|
Ah, pero resulta que el punto 1, es para ti punto 5 también. Entonces apliquemos la misma lógica:
¿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. ![]()
__________________
Tras casi seis años de trabajar para una empresa alemana como desarrollador Delphi, se vieron forzados a dejarme ir (temas presupuestales). Así que ahora estoy abierto a escuchar nuevas ofertas. Última edición por Al González fecha: 01-06-2015 a las 19:09:56. |
|
#7
|
||||
|
||||
|
Alberto,
Cita:
Nelson. |
![]() |
| Herramientas | Buscar en Tema |
| Desplegado | |
|
|
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 |
|