Club Delphi  
    Paypal   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 Buscar Temas de Hoy Marcar Foros Como Leídos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 28-05-2015
Avatar de Casimiro Noteví
Casimiro Noteví Casimiro Noteví is offline
Merodeador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.682
Poder: 10
Casimiro Noteví Tiene un aura espectacularCasimiro Noteví Tiene un aura espectacular
Como indica mamcx, creo que estás cayendo en algo que todos hemos caído muchas veces (debe ser algo implícito en personas como nosotros) y es que siempre estamos buscando la perfección. Hace tiempo que me di cuenta que no es necesario ser perfecto, basta con controlar lo "imprescindible" y si falla algo, ahora sí, emitir un mensaje o guardar un log, para saber dónde ha fallado y solucionarlo.
Pero intentar ser perfecto hasta el infinito y más allá no vale la pena
Responder Con Cita
  #2  
Antiguo 28-05-2015
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 28
Delphius Va camino a la fama
Cita:
Empezado por Casimiro Notevi Ver Mensaje
Como indica mamcx, creo que estás cayendo en algo que todos hemos caído muchas veces (debe ser algo implícito en personas como nosotros) y es que siempre estamos buscando la perfección. Hace tiempo que me di cuenta que no es necesario ser perfecto, basta con controlar lo "imprescindible" y si falla algo, ahora sí, emitir un mensaje o guardar un log, para saber dónde ha fallado y solucionarlo.
Pero intentar ser perfecto hasta el infinito y más allá no vale la pena
No es que busque hacerlo perfecto, sólo espero controlar la separación cohesiva.
Para mi diseño es muy necesario poder controlar esta parte puesto que responde a una necesidad importante. No es un detalle menor el guardar y leer de archivos y que si algo falla vaya y pase. Me son vitales para que justamente en caso de problemas, y por sobre todo para poder continuar con el trabajo en otra oportunidad, tener un medio en donde almacenar los datos.
Justamente la clases clientes esperan delegar el trabajo de poder leer y guardar en archivos en esta clase TArrayConverter para mantenerse lo más cohesivos posibles. En vista a que en varios puntos del programa me es necesario estar guardando y leyendo de archivos la clase TArrayConverter es más que justificada.
No vale la pena el uso de bases de datos, de hecho inicialmente lo estuve considerando pero tener una representación matricial en una DB es algo más trabajoso.

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #3  
Antiguo 28-05-2015
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
Asi que la pregunta es:

Que se supone que debe pasar si falla (por cualquier motivo) una llamada a TArrayConverter?
__________________
El malabarista.
Responder Con Cita
  #4  
Antiguo 28-05-2015
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 28
Delphius Va camino a la fama
Cita:
Empezado por mamcx Ver Mensaje
Asi que la pregunta es:

Que se supone que debe pasar si falla (por cualquier motivo) una llamada a TArrayConverter?
Mi principal objetivo es que TArryConverter reporte a las clases clientes de que hubo problema de "conversión" (aunque quizá el término más adecuado sería materialización). Pero no si antes de evaluar si es posible detectar el tipo de problema que ha tenido y de intentar solucionarlo por otra vía. Pero si no es viable esto, al menos ofrecer una excepción acorde a lo que la clase deba reportar.

Una excepción si es posible evitar propagarla lo más "arriba" posible y solucionarlo antes mejor.

El constructor del TFileStream puede fallar debido a "permisos". El constructor recibe como parámetro el modo de apertura del archivo, y se cierra cuando el TFileStream es liberado. La 1ra versión del código, la que expuse, no tiene la lógica para reintentar una apertura con diferentes modos. Pero debiera de considerarlo.

El código que expuse fue mi 1er intento, y ni bien lo vi me he dado cuenta de que no es del todo seguro y sano. Esto me hace cuestionar la forma en como debiera de poder encarar su diseño y ofrecer medidas de seguridad que garanticen lo más posible de que se haga el trabajo.
Por ello es que vengo aquí. A ver alternativas.

Hasta el momento había previsto excepciones en el contexto de la clase TArrayConverter para los siguientes casos:
1. Que la matriz (o vector; debe ser posible de trabajar con ambas estructuras. No vi necesario hacer una clase específica para cada una) no esté en un estado inconsistente debido a que no estuviera reservada o no fuera uniforme. Esto se da cuando no pasa el examen de CheckMatrix.
2. Que el formato de archivo no sea válido. Esta excepción puede darse si efectivamente se ha accedido a la apertura del archivo.
3. Que la dimensión de la matriz y la cantidad de datos registrados en el archivo no sean coincidentes.

Para cada una hay una posible solución desde el lado cliente:
Para 1 y 3 (re)Dimensionar la matriz.
Para 2. Simplemente se descarta el archivo y se da aviso de que el archivo no es el indicado y se solicita otro para efectuar las operaciones previstas.

Para estas excepciones las clases clientes pueden y tienen la información necesaria para revertir el problema. Ya tienen su carga de trabajo.
No sería bueno que además tuviera que estar al tanto de errores relacionados con más operatoria interna, si es posible que TArrayConverter haga parte de ese trabajo.

Asi lo estoy entendiendo yo.

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #5  
Antiguo 29-05-2015
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
Asi como lo expresas, entonces me parece que es bueno seguir tal como es FileStream. Crear TArrayConverter si el archivo no se puede leer carece de sentido, mientras que operar sobre TArrayConverter puede no siempre tener problemas, asi que en cada metodo se evalua que hacer.

Mejor dicho:

Código Delphi [-]
 TArrayConverter = class
    private
      FFile: TFileStream;
      ..
      ..
    public
      //Aqui se hace lo de LoadFile. si esto falla, el objeto
      //no tiene razon de existir
      constructor Create(FileName: string);
      destructor Destroy; override;
      procedure LoadMatrix(AMatrix: TAMatrix);
      procedure LoadVector(AVector: TAVector);
      procedure SaveMatrix(AMatrix: TAMatrix; OnDir: TArrayOrientation);
      procedure SaveVector(AVector: TAVector);
  end;

Asi que quien llama a TArrayConverter con el archivo X solo tiene 2 opciones: Se puede o no operar sobre el archivo, si no se puede, ya haces como has dicho.

Si el objeto TArrayConverter existe, los errores son solo probables y el objeto reacciona de acuerdo.

Asi se captura de forma muy explicita lo que estas diciendo, sin complicar la logica interna del objeto. Ademas, mientras exista TArrayConverter se asume que el archivo esta en uso, lo que anula la variable de InUse que existe ahora porque TArrayConverter esta en un estado potencialmente dual: Tiene o no acceso?


Si entiendo bien lo de punto 1 & 3, entonces no veo porque pasas la matriz, en vez de retornarla tal como indique el archivo, o sea:

Código Delphi [-]
function LoadMatrix():TAMatrix;

Ademas, si estas invocando de multiples sitios ese metodo, tendras problemas de concurrencia y tendrias que aplicar bloqueos u otra opcion para asegurar el acceso concurrente.

Es mas simple cuando los objetos son inmutables, y la informacion no se comparte (crea un cuello de botella). Mientras no se muchisimos datos, es muy rapido recrear una matriz y que cada parte del programa tenga su propia copia sabiendo con certeza que nadie la va a alterar.
__________________
El malabarista.
Responder Con Cita
  #6  
Antiguo 29-05-2015
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.610
Poder: 32
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.

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.
Responder Con Cita
  #7  
Antiguo 29-05-2015
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 28
Delphius Va camino a la fama
Cita:
Empezado por mamcx Ver Mensaje
Asi como lo expresas, entonces me parece que es bueno seguir tal como es FileStream. Crear TArrayConverter si el archivo no se puede leer carece de sentido, mientras que operar sobre TArrayConverter puede no siempre tener problemas, asi que en cada metodo se evalua que hacer.

Mejor dicho:

Código Delphi [-] TArrayConverter = class private FFile: TFileStream; .. .. public //Aqui se hace lo de LoadFile. si esto falla, el objeto //no tiene razon de existir constructor Create(FileName: string); destructor Destroy; override; procedure LoadMatrix(AMatrix: TAMatrix); procedure LoadVector(AVector: TAVector); procedure SaveMatrix(AMatrix: TAMatrix; OnDir: TArrayOrientation); procedure SaveVector(AVector: TAVector); end;


Asi que quien llama a TArrayConverter con el archivo X solo tiene 2 opciones: Se puede o no operar sobre el archivo, si no se puede, ya haces como has dicho.

Si el objeto TArrayConverter existe, los errores son solo probables y el objeto reacciona de acuerdo.

Asi se captura de forma muy explicita lo que estas diciendo, sin complicar la logica interna del objeto. Ademas, mientras exista TArrayConverter se asume que el archivo esta en uso, lo que anula la variable de InUse que existe ahora porque TArrayConverter esta en un estado potencialmente dual: Tiene o no acceso?


Si entiendo bien lo de punto 1 & 3, entonces no veo porque pasas la matriz, en vez de retornarla tal como indique el archivo, o sea:

Código Delphi [-]function LoadMatrix():TAMatrix;


Ademas, si estas invocando de multiples sitios ese metodo, tendras problemas de concurrencia y tendrias que aplicar bloqueos u otra opcion para asegurar el acceso concurrente.

Es mas simple cuando los objetos son inmutables, y la informacion no se comparte (crea un cuello de botella). Mientras no se muchisimos datos, es muy rapido recrear una matriz y que cada parte del programa tenga su propia copia sabiendo con certeza que nadie la va a alterar.
Muchas gracias mamx (no recuerdo bien si tu nombre era Mario, y a mi me gusta en lo posible dirigirme más en forma personal) por tu valioso aporte y ayudarme.

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:
Empezado por Al González Ver Mensaje
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.
Hola Al, gracias por venir en mi ayuda. Pido disculpas por haberte molestado en forma privada pero es que ya mi cabeza no trabaja tan bien después de haberme mandado cerca de 5000 líneas de código en otros módulos previos a éste. Y sumándose a que por cosas de la vida ya he perdido mucha práctica al estar bastante alejado de la programación.

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:

Código Delphi [-]
procedure TArrayConverter.LoadMatrix(...)
var File: TFileStream;
begin
  try
    File := TFileStream.Create(...);
    try
      // Hacer todo el trabajo
    finally
      File.Free;
    end;
  except
    // capturar excepciones dadas por TFileStrem y/o propagar las propias de TArrayConverter
  end;
end;

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:

Código Delphi [-]
procedure TOtraClase.HacerAlgo;
begin
   HagoAlgoConEstaMatriz(LaMatrix);
   // y otras cosas más...
   try
      Conversor.SaveMatrix(LaMatrix, NombreDelArchivo, Orientacion); // Conversor es singleton!
   except
      E: EFileOperation do
      ....
end;

Y la versión análoga para una lectura.

¿Como lo ven?

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #8  
Antiguo 30-05-2015
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 28
Delphius Va camino a la fama
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:

Código Delphi [-]
procedure TArrayConverter.LoadMatrix(AMatrix: TAMatrix; FileName: string);
var idx, i, j, RowsM, ColsM, ErrM: integer;
    AFile: TFileStream;
    Can: Boolean;
    Fmt: TFileFormat;
    Header: TMatrixHeader;
begin
  Can := CheckMatrix(AMatrix, RowsM, ColsM, ErrM);
  try
    AFile := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
    Try
      FIsBusy := true;
      // Leemos formato y Header
      Fmt.SizeFile := AFile.Seek(0, soEnd);
      AFile.ReadBuffer(Fmt.IDIni, SizeOf(Fmt.IDIni)); // ID.Ini
      AFile.ReadBuffer(Header, SizeOf(Header)); // Header
      AFile.Seek(INI_ID_END, soFromEnd);
      AFile.ReadBuffer(Fmt.IDEnd, SizeOf(Fmt.IDEnd)); // ID.End

      // Posibles excepciones de formato y Header
      if NOT IsValidFormat(Fmt, Header)
         then raise EInvalidFileArrayFormat.Create(Format(sInvalidFormat,['matrix']));
      if (Header.Cols <> ColsM) OR (Header.Rows <> RowsM)
         then raise EInconsistArray.Create(sInconsistArray);

      // Operamos
      if Header.Orientation = aoCol
         then for Idx := 1 to (Header.Rows * Header.Cols) do
              begin
                i := (Idx - 1) mod Header.Rows;
                j := (Idx - 1) div Header.Rows;
                AFile.ReadBuffer(AMatrix[i, j], SizeOf(TYPEDATA));
              end
         else for Idx := 1 to (Header.Rows * Header.Cols) do
              begin
                i := (Idx - 1) div Header.Cols;
                j := (Idx - 1) mod Header.Cols;
                AFile.ReadBuffer(AMatrix[i, j], SizeOf(TYPEDATA));
              end;
    finally
      Afile.Free;
      fIsBusy := false;
    end; // end-try-finally
  except
    on E: EFOpenError do
    begin
      raise EFileAccessDenied.Create(Format(sAccessDenied, [FileName, E.Message]));
    end;
    on E: EReadError do
    begin
      raise EConvertFailed.Create(Format(sConvertFailed, ['read', FileName, E.Message]));
    end;
    // ¿Este except captura las excepciones lanzadas en el try interno y debiera relanzarlas?
  end; // end-try-except
end;

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,
__________________
Delphius
[Guia de estilo][Buscar]
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

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 05:59:04.


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