Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

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

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 03-09-2014
Jose Roman Jose Roman is offline
Miembro
 
Registrado: jul 2006
Ubicación: Colombia
Posts: 361
Poder: 18
Jose Roman Va por buen camino
TStrings como variable global

Hola a todos,

Resulta que he declarado mi variable TStrings globalmente asi:
Código Delphi [-]
implementation

uses uDataModule, uMain;

{ TAlumno }

var
  AlumnoSql : TStrings;

Cuando creo el TObject con el que estoy trabajando hago esto:
Código Delphi [-]
constructor TAlumno.Create;
begin
  inherited Create;
  AlumnoSql := TStringList.Create;
  AlumnoSql := wDataModule.tbAlumnos.SelectSQL;
  ShowMessage(AlumnoSql.Text);
end;

El cuadro de dialogo me muestra pecfectamente los valores de AlumnoSql, hasta ahi va bien, pero cuando voy a otro procedimiento:
Código Delphi [-]
procedure TAlumno.BuscarAlumno(Sender: TObject);
begin
   wDataModule.tbAlumnos.Close;
   wDataModule.tbAlumnos.SelectSQL.Clear;
   ShowMessage('AlumnoSql.Text);
end;
La variable AlumnoSql esta vacia. Que estoy haciendo mal?

Última edición por Jose Roman fecha: 03-09-2014 a las 00:43:39.
Responder Con Cita
  #2  
Antiguo 03-09-2014
Avatar de mamcx
mamcx mamcx is offline
Moderador
 
Registrado: sep 2004
Ubicación: Medellín - Colombia
Posts: 3.911
Poder: 25
mamcx Tiene un aura espectacularmamcx Tiene un aura espectacularmamcx Tiene un aura espectacular
En primer lugar, estas usando una variable global. Debes limitar al maximo eso. A duras penas, para objetos tipo "Singleton", y eso que ojala ni eso.

Segundo, estas dependiendo de manejo de estado mutable, osea, AlumnoSql puede cambiar en cualquier momento por medio de quien sabe quien, asi que se requiere disciplina para saber exactamente donde y como y en que orden se opera sobre un tipo mutable en un programa. Asi que lo que te tocaria hacer es buscar en todo el codigo fuente donde y quien esta modificando esos datos, y controlar manualmente el orden de acceso.

La forma mas correcta es:

- No usar variables globales
- Usar funciones "puras", que ante la misma entrada de datos de forma deterministica siempre sale el mismo dato, y no hay forma de interceptar a medio camino y alterar sus datos (que es lo que pasa con AlumnoSql). Ademas, que estas no dependan del estado de otras funciones y/o objetos.
- Centralizar todo lo que maneje estado (osea: Acceso a base de datos, archivos, etc).
- Si manipulas una estructura mutable (que en Delphi es casi todo ) encapsular en una clase para que sepas exactamente como y quien y cuando se hacen las cosas.

O dicho muy sencillo:

El manejo de estado debería ser LOCAL a la clase/objeto (no hay como accederlo por fuera, no hay forma de hacer MiObjeto.MiDato ni parecido). Cuando un objeto se comunica con otro, en vez de pasar punteros/referencias/datos mutables se debería pasar una COPIA de los datos. Osea, se debe poder asegurar que si Pepito le pasa a Juanito una billetera con 10000 dólares, Juanito VERDADERAMENTE tiene los 10000 dólares, no que Pepito puede cambiar 10000 por 0 y luego Juanito se pregunte: Porque desapareció mi plata magicamente?

Que en tu caso en concreto: AlumnoSql no debe ser ni una propiedad, ni variable ni externa ni interna, siempre que se requiere asignar un sql al dataset una funcion lo regenera siempre:


Código Delphi [-]
procedure TAlumno.BuscarAlumno(Params....);
begin
  //PREFERIBLEMENTE NO usara un datamodule global..
   self.tbAlumnos.Close;
   self.tbAlumnos.SelectSQL.Clear;
   self.tbAlumnos.Sql := AQUI SE HACE EL SQL

end;

Y mucho mejor:

Código Delphi [-]
function TAlumno.BuscarAlumno(Params....):TDataSet;
begin
 //Crear el DataSet y retornarlo desde 0
end;

Lo que lo convertiria en una funcion testeable.
__________________
El malabarista.
Responder Con Cita
  #3  
Antiguo 03-09-2014
Jose Roman Jose Roman is offline
Miembro
 
Registrado: jul 2006
Ubicación: Colombia
Posts: 361
Poder: 18
Jose Roman Va por buen camino
Gracias mamcx, a corregir lo que estoy haciendo, de nuevo gracias por mostrarme el camino.
Responder Con Cita
  #4  
Antiguo 03-09-2014
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
Vamos a examinar paso a paso lo que sucede.

Código Delphi [-]
constructor TAlumno.Create;
begin
  inherited Create;
  AlumnoSql := TStringList.Create;
  AlumnoSql := wDataModule.tbAlumnos.SelectSQL;
  ShowMessage(AlumnoSql.Text);
end;
  1. En la línea en negritas creas una instancia de TStringList y la asignas a la variable global AlumnoSql.
  2. En la siguiente línea "asesinas" la asignación anterior y le asignas a AlumnoSql otro objeto de tipo TStringList. O sea, el objeto creado en la línea anterior se pierde irremediablemente.
  3. En esta segunda asignación, lo que asignas a la variable AlumnoSql es una referencia al objeto wDataModule.tbAlumnos.SelectSQL, no una copia de él.
  4. Esto quiere decir que cualquier cosa que le pase a wDataModule.tbAlumnos.SelectSQL también le pasará a AlumnoSql.
  5. En particular, cuando en el otro procedimiento haces

    Código Delphi [-]
    wDataModule.tbAlumnos.SelectSQL.Clear;

    también borras lo que tenga AlumnoSql, pues en realidad se trata del mismo objeto.

Quizá lo que pensabas era algo más de este estilo:

Código Delphi [-]
constructor TAlumno.Create;
begin
  inherited Create;
  AlumnoSql := TStringList.Create;
  AlumnoSql.Assign(wDataModule.tbAlumnos.SelectSQL);
  ShowMessage(AlumnoSql.Text);
end;

En este caso, sí tendrías una copia del objeto.

De todas formas, como dice mamcx, es mala idea tener una variable global así. Aunque no estoy muy seguro de concordar con él en eso de construir la sentencia SQL cada vez.

// Saludos
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
Como asignar un valor a una variable global desde un componente paquechu Varios 6 15-01-2014 22:10:18
variable tStrings Carliviris Varios 4 03-01-2007 20:01:05
Variable global jluisx OOP 3 27-10-2005 23:31:22
Variable global (De novatisimo) RyAr Varios 5 08-07-2004 16:48:44
variable global existe en php ? sarga PHP 1 27-06-2004 18:47:07


La franja horaria es GMT +2. Ahora son las 08:07:06.


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