Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > OOP
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 02-08-2007
Avatar de AzidRain
[AzidRain] AzidRain is offline
Miembro Premium
 
Registrado: sep 2005
Ubicación: Córdoba, Veracruz, México
Posts: 2.914
Poder: 21
AzidRain Va camino a la fama
Duda sobre OOP y capas

A ver, se aceptan sugerencias:

Estoy haciendo un proyecto y quiero seguir al pie de la letra OOP y capas por lo que me olvidé por el momento de controles data-aware y demás. Uso como motor MySQL.

Ya hice un pequeño control de datos de empresas. De manera que definí las siguientes clases:

TCatalogoEmpresas y TEmpresa. Hasta aqui se ve obvio como se trabaja. TCatalogoEmpresas se encarga de gestionar las n TEmpresas que pueda haber. Digamos que estas dos clases pertenecen a la capa de negocio. La capa de Datos la manejo por medio de un datamodule y sus correspondientes querys y demás.

TCatalogoEmpresas tiene los siguentes metodos:

Function GetListaEmpresas:TZQuery;
Devuelve una tabla que muestra las empresas que hay en la BD. Solo para efectos de visualización ya que no permite su edición. Este query se lo pide a la capa de datos.

Function GetEmpresa(aIDEmpresa:String):TEmpresa;
Devuelve la TEmpresa cuyo ID sea el indicado, genera una excepción si el ID no se encuentra.

Function NewEmpresa:TEmpresa;
Construye una nueva empresa para trabajarla.

Procedure InsertEmpresa(aEmpresa:TEmpresa)
Inserta aEmpresa como nueva empresa.

Hasta aqui todo funciona excelente pero hay cosas que no me gusta como se ven, por ejemplo para editar una empresa hago esto:

Código Delphi [-]
      FViewEmpresa := TFViewEmpresa.Create(nil);
   try
      try
        EmpresaAnterior := CatalogoEmpresas.GetEmpresa(  GridViewEmpresasRFC.EditValue);
        EmpresaEditada  := CatalogoEmpresas.GetEmpresa(  GridViewEmpresasRFC.EditValue);
        If FViewEmpresa.EditaEmpresa( EmpresaEditada ) Then
           CatalogoEmpresas.UpDateEmpresa( EmpresaAnterior, EmpresaEditada );
           GridViewEmpresas.DataController.DataSource.DataSet.Refresh;
      Finally
         EmpresaEditada.Free;
         EmpresaAnterior.Free;
      end;
   finally
     FViewEmpresa.Free;
   end;
Lo que no me gusta es eso de UpdateEmpresa, bastaría con pasarle una TEmpresa y que esta se actualzara pero resulta que en la capa de datos las cosas son diferntes a los objetos ya que cad TEmpresa es en realidad un registro de una tabla y se actaulizan por medio de un UPDATE TABLE de SQL hay que indicarle a ese query cual es la clave del registro a modificar: "update table empresas set.... where clave=laclave"
Hasta aqui no pasaria nada pues con los datos de tempresa de puede hacer el query sin problemas pero...que pasa si en TEMpresa se le editó el campo clave?? Entonces ya no podriamos editarlo en la tabla porque aunque tenemos los nuevos valores no tenemos forma de localizar el registro anterior.

Alguna sugerencia para y que el codigo quede mas simple?

Ahora otra mas.
Tenemos nuestra TEmpresa que contienen los datos de la empresa y algunas cosas mas. Tenemos una Forma TFViewEmpresa que muestra los datos de la empresa. Como les decia, no uso componentes dataaware para poder seguir el esquema completo de capas, pero por ejemplo para llenar los campos de la forma con los datos de la clase tengo que hacer una serie de asignaciones y para guardar es lo mismo...hay alguna otra forma'?
__________________
AKA "El animalito" ||Cordobés a mucha honra||
Responder Con Cita
  #2  
Antiguo 03-08-2007
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
No entiendo tu problema con la clave. Estamos hablando de la llave primaria ¿no? Entonces no debería editarse ¿o sí?

Bueno, como alguna vez he intentado hacer estas cosas es, primero que nada, usando una llave primaria artificial (un entero autoincremental, por ejemplo) para no caer en el caso de tener que editarla.

Cada objeto del negocio desciende de una clase común:

Código:
TObjetoNegocio = class
public
  property Id;
  procedure Load(Id: Integer); virtual; abstract;
  procedure Save; virtual; abstract;
  procedure Delete; virtual; abstract;
end;
Cada clase redefine los métodos para construir las sentencias SQL adecuadas y mandarlas al DataModule. El método Save es dual, sirve para insertar y modificar. Si el ID es 0, quiere decir que el objeto es nuevo y se requiere un INSERT. En caso contrario, quiere decir que ya existe en la base y se requiere un UPDATE.

Siguiendo tu ejemplo, se procedería así:

Código:
Empresa := TEmpres.Create();

try
  Empresa.Load(EmpresaId);
  if TViewEmpresa.Editar(Empresa) then
    Empresa.Save;
finally
  Empresa.Free;
end;
TViewEmpresa.Editar sería un método de clase que es el que se encarga de construir el visor y pasarle el objeto Empresa. Esto para evitar tener que construir explícitamente el visor en cada edición que se requiera.

---------

El paso de datos entre el objeto y los controles yo creo que es mucho más difícil. Una aproximación podría ser usar RTTI para inspeccionar las propiedades publicadas del objeto y llenar con ellas los controles con el mismo nombre.

// Saludos
Responder Con Cita
  #3  
Antiguo 03-08-2007
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.286
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Cita:
Empezado por AzidRain Ver Mensaje
Lo que no me gusta es eso de UpdateEmpresa, bastaría con pasarle una TEmpresa
Creo que lo más adecuado eas que el método Actualizar/Update estuviera en el propio objeto Empresa, tal como ya han comentado.
Lo más sencillo es que todos tus objetos de negocio deriven de uno Base (no se si lo tienes así), por ejemplo de TObjetoBase.
En este objeto base es donde debes programar el máximo de operraciones posibles; entre ellas los Load, Insert, Updates, búsquedas,... si realmente quieres que el "invento" sea potente.


Cita:
Empezado por AzidRain Ver Mensaje
Ahora otra mas.
Tenemos nuestra TEmpresa que contienen los datos de la empresa y algunas cosas mas. Tenemos una Forma TFViewEmpresa que muestra los datos de la empresa. Como les decia, no uso componentes dataaware para poder seguir el esquema completo de capas, pero por ejemplo para llenar los campos de la forma con los datos de la clase tengo que hacer una serie de asignaciones y para guardar es lo mismo...hay alguna otra forma'?
Si sigues una nomenclatura de nombres se puede automatizar por RTTI como dice Román; La otra opción que se me ocurre es utilzar algun tipo de componente (diseñado por tí) que te almacene la correspondencia entre el Obtejo (de la clase de negocio) y los componentes visuales; Vendría a ser como el "enganche" entra ambas capas.
La última opción, pero más compleja, y que puedes intentar más adelante es crear un componente que te haga las veces de TDataSource, pero que en lugar de unir Controles DB y Base de Datos, te una Controles DB y Objetos de Negocio.
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #4  
Antiguo 03-08-2007
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
Otro enfoque al segundo punto, que en algunos casos podría ser práctico, es el que expone Wayne Niddery en su artículo Can Good Object-Oriented Design include Data-Aware Controls?, que básicamente consiste en insertar un clientdataset entre el objeto de negocios y los controles data aware:


DataSet final <--> Objeto Negocios <--> ClientDataSet <--> Controles data aware

El objeto de negocios contendría el ClientDataSet y se encargaría de transportar la información entre éste y el DataSet final, validando todas las reglas del negocio. Este paso de información sigue siendo manual, pero se hace sólo en este punto y todos los formularios se conectarían de la manera tradicional via un DataSource.

// Saludos
Responder Con Cita
  #5  
Antiguo 04-08-2007
Avatar de AzidRain
[AzidRain] AzidRain is offline
Miembro Premium
 
Registrado: sep 2005
Ubicación: Córdoba, Veracruz, México
Posts: 2.914
Poder: 21
AzidRain Va camino a la fama
Gracias Roman, ese artículo ya lo había leído.

Finalmente y por el momento lo deje como lo tenía solo agregue una función al visor que lee o escribe los datos del Objeto a los controles y viceversa. Si hay algún cambio solo tengo que modificar esos métodos.

Por otro lado y a manera de contribución al tema, me encontré este artículo bastante interesante que me aclaró algunos puntos y aunque los ejemplos son de C# se entiende perfectamente.

http://jmhogua.blogspot.com/2007/02/...-negocios.html

Me pareció interesante porque no se limita a teorizar sino que da un ejemplo real de como se aplica la separación de capas.

Por otro lado resolvi una duda que tenia respecto a como ubicar las capas mediante estas sencillas reglitas que a lo mejor son tontas pero bien que sirven:

* La capa de presentación (un TFOrm) no tiene acceso a la capa de datos (ni la conoce)
* La capa de negocio es la unica que puede acceder a la capa de datos
* La capa de presentacion solo puede ver a la de negocio
* La capa de negocio es la que tiene que validad todo antes de pasar a la de datos.

Comento tambien que me quedó muy entendible mi modelo ya que a pesar de que me dio mas trabajo de teclear que lo normal, para estarle cambiando algo es muy sencillo y siempre determino precisamente en que parte debo corregir, cosa que cuando lo hago en no OOP es mucho más relajo.

Por otra parte también terminé de comprender bien lo de las excepciones ya que las utilizo cuando hago las validaciones y hay algun problema

miren quedo algo como esto:
Este codigo se ejecuta al hacer click en el boton aceptar de la forma
Código:
 WriteEmpresa(laEmpresa); // Escribimos los datos del form al objeto laEmpresa
   Try
     laEmpresa.ValidarDatos; //Le pedimos a la empresa que se valide
     modalResult :=mrOk;     // Si todo salió bien la ventana se puede cerrar
   except
     on E: ERFCNovalido Do  // La validación puede generar estas excepciones
     Begin
       eRFC.SetFocus;         // como ya se donde esta el error 
       eRFC.SelectAll;         //  puedo seleccionar el control correspondiente
       raise;                     // vuelvo a elevar la excepción para mostrar el 
     end;                        // mensaje de error.
    on E: ENivelesNoValidos Do   // ....y asi para cualquier otro error de validación
     Begin
       TabCatalogo.SetFocus;
       eNivel1.SetFocus;
       raise;
     end;
   end;
Ahora bien a la clase TEmpresa le puse su validador:
Código:
procedure TEmpresa.ValidarDatos;
begin
   If Trim(RFC)='' Then raise ERFCNovalido.Create('El RFC no puede estar en blanco');
   If ( (Personalidad= E_PERSONAFISICA) and (Length(RFC)<>13)) OR  ((Personalidad= E_PERSONAMORAL) and (Length(RFC)<>12)) Then raise ERFCNovalido.CreateFmt('El RFC %s no es válido',[RFC]);
   If Not NivelesValidos Then raise ENivelesNoValidos.Create('La suma de digitos de los niveles no puede ser mayor que 21');
end;
En otra unidad definí las excepciones ERFCNoValido y ENivelesNoValidos.


Que bonito se ve el código y dejen lo bonito que facil es de depurar y lo mejor, corrió a la primera.
__________________
AKA "El animalito" ||Cordobés a mucha honra||
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
sobre aplicacion de 3 capas yoyo Providers 4 03-08-2007 18:08:12
Duda sobre DFS enrique_84 Varios 2 08-06-2006 11:53:40
Una duda sobre los Uses jorch_yr Varios 1 30-05-2004 04:39:40
Una duda sobre ADO PTW Conexión con bases de datos 1 13-04-2004 23:33:14
Duda sobre ADO Omar Alejandro Conexión con bases de datos 7 31-05-2003 19:52:58


La franja horaria es GMT +2. Ahora son las 22:42:01.


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