Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Ayuda con refactorización (https://www.clubdelphi.com/foros/showthread.php?t=95306)

Dexter182 28-07-2021 05:09:20

Ayuda con refactorización
 
Hola a todos!


Gracias a los sabios consejos que me dieron en este post: https://www.clubdelphi.com/foros/showthread.php?t=94720 comencé con mucho éxito la migración y refactorización de mi humilde sistema.
He avanzado mucho y el código está quedando mucho más legible y ordenado que antes.
Sin embargo, en algunas ocasiones me está costando bastante separar las consultas SQL de los forms.
Por ejemplo, un código como este:



Código Delphi [-]
Modulo.ADOCommand.CommandText := 'DELETE FROM Productos WHERE Cod_Producto = :pCodigo';
Modulo.ADOCommand.Parameters.ParamByName('pCodigo').Value := Edit_Codigo.Text;
Modulo.ADOCommand.Execute


Fue sencillo de separar con un simple procedimiento:

Código Delphi [-]
Modulo.EliminarArticulo(Edit_Codigo.Text);


Ahora bien, cuando necesito volcar los datos recibidos de la consulta en el form no se muy bien como hacerlo.
Por ejemplo, un código como este ¿cómo lo refactorizarían?
Código Delphi [-]
Modulo.Consulta.Active := FALSE;
Modulo.Consulta.SQL.Clear;
Modulo.Consulta.SQL.Add('SELECT Productos.*, Proveedores.Denominacion, Secciones.Desc_Seccion, '+
                               'Categorias.Desc_Categoria, IVA.Valor AS Valor_IVA '+
                        'FROM Productos, Proveedores, Categorias, Secciones, IVA '+
                        'WHERE (Cod_Producto = :pCodigo) AND '+
                              '(Productos.Cod_Proveedor = Proveedores.Cod_Proveedor) AND '+
                              '(Productos.Cod_Categoria = Categorias.Cod_Categoria) AND '+
                              '(Categorias.Cod_Seccion = Secciones.Cod_Seccion) AND '+
                              '(Productos.Porcentaje_IVA = IVA.Codigo)');
Modulo.Consulta.Parameters.ParamByName('pCodigo').Value := Edit_Codigo.Text;
Modulo.Consulta.Active := TRUE;

//Carga los campos con los datos de la tabla
With Modulo.Consulta do
  begin
    Edit_Descripcion.Text      := FieldByName('Desc_Producto').AsString;
    Edit_PreUnitario.Text      := FieldByName('Precio').AsString;
    ComboBox_IVA.Text          := FieldByName('Valor_IVA').AsString;
    Edit_Ganancia.Text         := FieldByName('Porcentaje_Ganancia').AsString;
    SpinEdit_Stock.Text        := FieldByName('Cant_Existente').AsString;
    SpinEdit_StockMinimo.Text  := FieldByName('Cant_Minima').AsString;
    SpinEdit_CantRep.Text      := FieldByName('Cant_Reposicion').AsString;
    ComboBox_Seccion.Text      := FieldByName('Desc_Seccion').AsString;
    ComboBox_Categoria.Text    := FieldByName('Desc_Categoria').AsString;
    ComboBox_Proveedor.Text    := FieldByName('Denominacion').AsString;
    Edit_CodProveedor.Text     := FieldByName('Cod_Producto_Proveedor').AsString;
    SpinEdit_UniProveedor.Text := FieldByName('Unidad_Proveedor').AsString;
    Edit_CodBarras.Text        := FieldByName('Cod_Barras').AsString;
  end;


Saludos! ^\||/^\||/^\||/

mamcx 28-07-2021 06:00:02

Una manera simple es crear un Record basico para pasar los datos:

Código Delphi [-]
type
  TProduct = Record
    CodBarras : string;
...
  end;

  TCustomer = Record
    CodCustomer : string;
...
  end;

  TInvoice = Record
...
  end;

Eso queda muy bonito si en un solo archivo tienes todos tus "datos" declarados. De alli, puedes hacer una clase/interface para pasar/leer los datos:

http://www.delphibasics.co.uk/Articl...Name=Interface
Código Delphi [-]
type
   IDb = Interface(IInterface)
     function to_sql(con:TCon..., of:T) : TClientDataSet;
     function from_sql(con:TCon..., sql:String) : T;
   end;

Neftali [Germán.Estévez] 28-07-2021 10:36:57

Otra opción es "separar" la parte visual de la parte de "los datos".
Igual que de entrada, has eliminado el Edit_Codigo.Text de donde tenías la consulta y lo has convertido en un parámetro, puedes hacer lo mismo con el Dataset.

Código Delphi [-]
Modulo.EliminarArticulo(Edit_Codigo.Text);

De forma que esta llamada quedaría así:

Código Delphi [-]
Modulo.EliminarArticulo(Edit_Codigo.Text, ADataset);

Y luego podrías tener u procedimiento (en la parte voisual) que cogiera los valores del Dataset y los asignara a los campos visuales:

Código Delphi [-]
Modulo.EliminarArticulo(Edit_Codigo.Text, ADataset); 
AsignarVvaloresRetorna(ADataset);

Y el procedimiento quedaría así (en la parte visual):
Código Delphi [-]
procedure AsignarValoresRetorna(ADataset:TDataset);
begin
  //Carga los campos con los datos de la tabla
  With ADataset do
  begin
    Edit_Descripcion.Text      := FieldByName('Desc_Producto').AsString;
    Edit_PreUnitario.Text      := FieldByName('Precio').AsString;
    ComboBox_IVA.Text          := FieldByName('Valor_IVA').AsString;
    Edit_Ganancia.Text         := FieldByName('Porcentaje_Ganancia').AsString;
    SpinEdit_Stock.Text        := FieldByName('Cant_Existente').AsString;
    SpinEdit_StockMinimo.Text  := FieldByName('Cant_Minima').AsString;
    SpinEdit_CantRep.Text      := FieldByName('Cant_Reposicion').AsString;
    ComboBox_Seccion.Text      := FieldByName('Desc_Seccion').AsString;
    ComboBox_Categoria.Text    := FieldByName('Desc_Categoria').AsString;
    ComboBox_Proveedor.Text    := FieldByName('Denominacion').AsString;
    Edit_CodProveedor.Text     := FieldByName('Cod_Producto_Proveedor').AsString;
    SpinEdit_UniProveedor.Text := FieldByName('Unidad_Proveedor').AsString;
    Edit_CodBarras.Text        := FieldByName('Cod_Barras').AsString;
  end;  
end;

Dexter182 28-07-2021 14:36:49

¡Muchas gracias a ambos! v:-)v


Había pensado en un record, pero pasándolo como parámetro.
Mis conocimientos son un poco más rudimentarios, jaja.


Me gustan ambas opciones.
La de Germán es la más fácil de implementar con mis conocimientos actuales, pero lo de la interface me despertó curiosidad.
Voy a leer un poco y veo por cual me decido.

¡Muchas gracias de nuevo a ambos por la ayuda! ||-||

Dexter182 28-07-2021 20:14:44

No se si es correcto, pero lo implementé de la siguiente manera:


Código Delphi [-]
procedure TForm_Articulo.AsignarValores;

var
  Consulta: TDataSet;
begin
  Consulta := Modulo.DatosArticulo(eCodigo.Text);

  //Carga los campos con los datos de la tabla
  With Consulta do
    begin
      eDescripcion.Text  := FieldByName('Desc_Producto').AsString;
      ePreUnitario.Text  := FieldByName('Precio').AsString;
      cbIVA.Text         := FieldByName('Valor_IVA').AsString;
      eGanancia.Text     := FieldByName('Porcentaje_Ganancia').AsString;
      eStock.Text        := FieldByName('Cant_Existente').AsString;
      eStockMinimo.Text  := FieldByName('Cant_Minima').AsString;
      eCantRep.Text      := FieldByName('Cant_Reposicion').AsString;
      cbSeccion.Text     := FieldByName('Desc_Seccion').AsString;
      cbCategoria.Text   := FieldByName('Desc_Categoria').AsString;
      cbProveedor.Text   := FieldByName('Denominacion').AsString;
      eCodProveedor.Text := FieldByName('Cod_Producto_Proveedor').AsString;
      eUniProveedor.Text := FieldByName('Unidad_Proveedor').AsString;
      eCodBarras.Text    := FieldByName('Cod_Barras').AsString;
    end;
end;


Leí sobre las interfaces y está muy bueno, pero necesito leer más para entender bien como usarlas.
Saludos! ||-||

Neftali [Germán.Estévez] 29-07-2021 12:09:17

Mejor si el Dataset lo pasas como parámetro.
De esa forma el procedimiento de asignar valores no tiene que hacer referencia al módulo (queda independiente) y se podría llamar con otro dataset que estiviera en "Modulo2" (por decir algo).
Aunque ahora no lo vayas a utilizar ayuda a crear piezas (procedimientos) independientes (cajas negras) y te acostumbras a trabajar así.

Te evitas esta línea:

Código Delphi [-]
Consulta := Modulo.DatosArticulo(eCodigo.Text);

Los Interfaces son potentes y también ayudan a crear piezas "estancas". Para que te hagas una idea una Interfaz es como un contrato. Creas un contrato y todos aquellos elementos que lo usen deben cumplir ese contrato (esas normas).
Pero si es cierto que no es algo "inicial".

Dexter182 29-07-2021 14:27:27

¡Gracias Germán, como siempre! v:-)v

Cita:

Empezado por Neftali [Germán.Estévez] (Mensaje 542141)
Aunque ahora no lo vayas a utilizar ayuda a crear piezas (procedimientos) independientes (cajas negras) y te acostumbras a trabajar así.

Más claro imposible.
La idea es mejorar mi manera de programar, así que gracias por la explicación. ^\||/^\||/^\||/
Saludos!!!! ||-||


La franja horaria es GMT +2. Ahora son las 19:48:45.

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