16 noviembre 2007

Creando aplicaciones multicapa (II)

Después de tener una visión global de cómo funcionan las aplicaciones multicapa vamos a ver cada una de sus partes.

LA ESTRUCTURA DE LA APLICACION CLIENTE


El usuario que va a utilizar la aplicación cliente no notará la diferencia entre una aplicación cliete/servidor y una aplicación multicapa, ya que el acceso a la información se realiza a través de los componentes estándar TClientDataSet.

El componente ClientDataSet se comunica con el proveedor de datos a través de la interfaz IAppServer. Se pueden seleccionar diferentes protocolos de comunicación según el componente de conexión que se utilice, donde tenemos los siguientes componentes:

Componente Protocolo
--------------------------------------------------
TDCOMConnection DCOM
TSocketConnection Windows sockets (TCP/IP)
TWebConnection HTTP
TSOAPConnection SOAP (HTTP y XML)

LA ESTRUCTURA DE LA APLICACION SERVIDOR

Una vez instalado el servidor de aplicaciones, cuando se ejecuta por primera vez no establece una conexión con los clientes. Más bien son los clientes los que inician y mantienen la conexión con el servidor de aplicaciones. Todo esto sucede automáticamente sin que tengamos que manejar solicitudes o administrar interfaces.

La base de un servidor de aplicaciones es el módulo de datos remoto, el cual esta especializado en soportar la interfaz IAppServer (para los servidores de aplicaciones que tienen servicios web, el módulo de datos remoto soporta la interfaz IAppServerSOAP, y usa como preferencia IAppServer).

Las aplicaciones cliente usan las interfaces de módulos de bases de datos remotos para comunicarse con los componentes Provider del servidor de aplicaciones. Cuando el módulo de datos remoto usa IAppServerSOAP, el componente de conexión se adapta a este para la interfaz IAppServer que el que usa el componente ClientDataSet.

Hay tres tipos de módulos de datos remotos:

TRemoteDataModule: Se usa este tipo si los clientes van a utilizan protocolos DCOM, HTTP, sockets o una conexión OLE hacia el servidor de aplicaciones, a menos que queramos instalar el servidor de aplicaciones con COM+.

TMTSDataModule: Se utiliza este tipo si vamos a crear un servidor de aplicaciones como librería DLL que esté instalada con COM+ (or MTS). Se puede utilizar este módulo de datos remoto MTS con protocolos DCOM, HTTP, sockets u OLE.

TSoapDataModule: Este es un módulo de datos que implementa una interfaz IAppServerSOAP en una aplicación de servicios web. Utilizaremos este tipo de módulo de datos para proveer datos a los clientes con acceso a servicios web.

Si el servidor de aplicaciones es distribuido mediante COM+ (o MTS), el módulo de datos incluye eventos para cuando el servidor de aplicaciones sea activado o desactivado. Esto permite conectar automáticamente con los motores de bases de datos cuando se active y desconectarlas cuando se desactive.

EL CONTENIDO DEL MODULO DE BASES DE DATOS REMOTO

Como cualquier otro módulo de datos, se puede incluir cualquier componente no visual en el módulo de datos remoto. Pero hay que tener en cuenta ciertos aspectos:

- Para cada dataset que tiene el módulo de datos remoto en los clientes, debemos incluir un DataSetProvider. Un DataSetProvider parte la información en paquetes que son enviados a los ClientDataSet y aplican las actualizaciones de las bases de datos contra el servidor de aplicaciones.

- Para cada documento XML que el módulo de datos remoto envía al cliente, debemos incluir un proveedor XML. Un proveedor XML actua como un DataSetProvider, exceptuando que la actualización de los datos se efectua a través de documentos XML en vez de ir al motor de bases de datos.

No hay que confundir los componentes de conexión a bases de datos con los componentes de conexión a servidores de aplicaciones, ya que estos últimos utilizan los componentes de las pestañas DataSnap y WebServices.

MODULOS DE DATOS REMOTOS TRANSACCIONALES

Si vamos a crear un servidor de aplicaciones que va a utilizar los protocolos COM+ o MTS entonces podemos sacar ventaja de esto creando módulos de datos transaccionales (Transactional Data Module) en lugar de un módulo de datos remoto ordinario (Remote Data Module). Esto sólo se puede hacer en sistemas opetarivos Windows 2000 en adelante.

Al utilizar un módulo de datos transaccional tenemos las siguientes ventajas:

- Seguridad: COM+ (o MTS) proporciona unas reglas de seguridad en nuestro servidor de aplicaciones. A los clientes se les asignan reglas, las cuales determinan como pueden acceder a la interfaz MTS del módulo de datos.

- Los módulos de datos transaccionales permiten mantener la conexión de los clientes abierta cuando se conectan y desconectan muchas veces hacia el servidor de aplicaciones. De este modo, mediante unas pocas conexiones podemos controlar a muchos clientes que se conectan y se desconectan continuamente (como si fuera un servidor web).

- Los módulos de datos transaccionales pueden participar en transacciones que abarquen múltiples bases de datos o incluir funciones que no están implementadas en las bases de datos.

- Pudemos crear nuestro servidor de aplicaciones como un módulo de datos remoto cuya instancia es activada y desactivada según se necesite. Cuando se usa la activación en tiempo real, nuestros módulos de datos remotos son instanciados solamente si los necesitan los clientes. Esto evita de gastar recursos que no se vayan a utilizar.

Pero no todo son ventajas. Con una simple instancia de un módulo de datos el servidor de aplicaciones se puede manejar todas las llamadas a bases de datos a través de una simple conexión de bases de datos. Pero si se abusa de esto se puede crear un cuello de botella y puede impactar en la ejecución cuando hay muchos clientes, con lo tenemos que mantener un equilibrio entre el número de clientes que van a acceder al servidor de aplicaciones y el número de módulos de datos remotos que se van instanciar.

También puede ocurrir el efecto contrario: si se utilizan múltiples instancias de un módulo de bases de datos remotas, cada instancia puede mantener una conexión a bases de datos independiente. De modo que si hay muchas instancias del módulos de datos remotos se abrirían demasiadas conexiones con la base de datos, disminuyendo el rendimiento del motor de bases de datos como si fuera la típica aplicación cliente/servidor con muchos usuarios.

AGRUPAMIENDO DE MODULOS DE DATOS REMOTOS

El agrupamiento de objetos (pooling) nos permite crear una caché de módulos de datos remotos que estarán disponibles en memoria para las llamadas de las aplicaciones cliente. De esta manera se conservarán recursos en el servidor y evitará el tener que instanciar y destruir de memoria los módulos de datos remotos cuando se utilicen o se dejen de utilizar.

Cada vez que no estamos usando el módulo de datos transaccional obtenemos todas las ventajas que proporciona el tener una cache de objetos agrupados tanto si la conexión se efectua a través de DCOM como si es mediante el componente TWebConnection. Además podemos limitar el número conexiones a bases de datos.

Cuando el servidor de aplicaciones web recibe una petición del cliente, este las pasa a su primer módulo de datos remoto disponible en la caché de módulos de datos remotos. Si no hay disponible ninguna instancia de módulo de datos remoto, el servidor crea una nueva (no sobrepasando el máximo de módulos especificado por nosotros). Esto proporciona una gran flexibilidad permitiendo manejar varios clientes a través de un simple instancia de módulo de datos remoto (el cual puede actuar como un cuello de botella) e irá creando nuevas instancias según se vaya necesitando.

Cuando una instancia de un módulo de datos remoto que está en la caché no recibe ninguna petición de clientes durante un tiempo prolongado, es automáticamente liberado. Esto evita que el servidor de aplicaciones se sature con muchas instancias abiertas.

En la siguiente parte de este artículo abarcaremos los tipos de conexión que se pueden realizar entre las aplicaciones clientes y el servidor de aplicaciones.

Pruebas realizadas en Delphi 7.

14 noviembre 2007

Creando aplicaciones multicapa (I)

En este artículo que estará separado en varias partes vamos a ver como crear aplicaciones de bases de datos multicapa cliente/servidor. Este tipo de aplicaciones esta dividido en unidades lógicas, llamadas capas, las cuales se ejecutan en distintas máquinas. Las aplicaciones multicapa distribuyen los datos y se comunican en una red de área local o bien sobre Internet. Esto proporciona muchas ventajas tales como centralizar la lógica de negocio en un sólo servidor y donde varios clientes van tirando de él. Además podemos crear aplicaciones que comuniquen varios centros de trabajo se estén separados geográficamente a través de Internet.

Una aplicación multicapa queda particionada de la siguiente manera:

- Aplicación Cliente: se encarga de mostrar la interfaz de usuario.

- Servidor de aplicaciones: reside en la red local central y es accesible por todos los clientes donde reciben datos directamente de este servidor.

- Servidor de bases de datos: en este servidor es donde está instalado el motor de bases de datos (Interbase, Firebird, Oracle, etc.), aunque el servidor de aplicaciones y el servidor de bases de datos pueden ser la misma máquina.

En este modelo a tres capas los clientes sólo pueden comunicarse con el servidor de aplicaciones y en ningún caso directamente con el motor de bases de datos, como ocurre en las aplicaciones cliente/servidor habituales.

Este tipo de aplicaciones multicapa no tiene porque estar compuesto sólo de tres capas, podría constar de varios servidores de bases de datos y servidores de aplicaciones.

VENTAJAS DE CREAR UN MODELO MULTICAPA

En este modelo de bases de datos la aplicación cliente sólo se dedica a mostrar los datos al usuario, no sabe nada sobre como los datos son actualizados y mantenidos.

El servidor de aplicaciones (capa media) coordina y procesa las peticiones y actualizaciones de múltiples clientes. El servidor maneja todos los detalles, define el conjunto de datos e interactua con el servidor de bases de datos.

Las ventajas de este modelo multicapa son las siguientes:

- Encapsulación de lógica de negocio. Diferentes clientes de la aplicacion pueden acceder al mismo servidor intermedio. Esto permite evitar la redundancia (y coste de mantenimiento) de duplicar las reglas de negocio para cada aplicación cliente separada.

- Aplicaciones clientes pequeñas. Al delegar las tareas más pesadas en la capa media las aplicaciones clientes ocupan menos y consumen menos procesador y memoria, permitiendo instalarse en máquinas de bajo rendimiento. Esto trae la ventaja de que por muchos clientes que accedan a la aplicación, el motor de bases de datos sólo tiene una conexión, que va directamente al servidor de aplicaciones, evitando así problemas de concurrencia o latencia de datos entre distintas aplicaciones cliente. Estas aplicaciones clientes también pueden funcionar a través de Internet ya que su consumo de ancho de banda es mínimo, al contrario de conectar directamente con el motor de bases de datos.

- Procesar datos distribuidos. Distribuir el trabajo de una aplicación entre varias máquinas puede mejorar la ejecución, ya que el balanceo de carga permite reducir la carga de las máquinas que funcionan como servidor de aplicaciones. Por ejemplo, si vemos que una aplicación de gestión se relentiza podemos distribuir en una máquina las compras, en otra las ventas y la gestión de recibos en otra.

- Incrementar la seguridad. Podemos aislar la funcionalidad en las capas dando restricciones de seguridad. Esto proporciona unos niveles de seguridad configurables y flexibles. Las capas intermedias pueden limitar los puntos de entrada a material protegido, permitiendo controlar el control de acceso más fácilmente. Si usamos HTTP o COM+, podemos utilizar los modelos de seguridad que soportan.

COMPOSICION DE LAS APLICACIONES DE BASES DE DATOS MULTICAPA

Las aplicaciones multicapa usan los componentes de la pestaña DataSnap, los de la pestaña Data Access y a veces los de la pestaña WebServices, más un módulo de datos remoto que es creado por el asistente de la pestaña Multitier o WebServices del cuadro de diálogo New Items. Estos componentes proporcionan las funcionalidades para empaquetar información transportable sólo con los datos que se hayan modificado.

Los componentes que necesitamos para aplicaciones multicapa son los siguientes:

Módulo de bases de datos remoto: Los módulos de datos pueden actual como un servidor COM o implementar un servicio web para dar a las aplicaciones clientes acceso a los datos. Este componente es utilizado en el servidor de aplicaciones en la capa intermedia (el servidor de aplicaciones).

Provider: Es el que proporciona los datos creando paquetes de datos y resolviendo las actualizaciones de los clientes. Este componente es utilizado en el servidor de aplicaciones en la capa intermedia (servidor de aplicaciones).

ClientDataSet: es un dataset especializado que usa la librería midas.dll o midaslib.dcu para manejar los datos almacenados en los paquetes que se envían y reciben. Este componente es utilizado por la aplicación cliente. Tiene una caché local y sólo envía al servidor los datos que han cambiado.

Connection: Es una familia de componentes que estan localizados en el servidor y que utilizan la interfaz IAppServer para leer las peticiones de las aplicaciones clientes. Cada componente de conexión está especializado en protocolo particular de comunicaciones.

Los componentes proveedores y clientes requiren las librerías midas.dll o midaslib.dcu cuando se va a distribuir la aplicación en otros equipos.

FUNCIONAMIENTO DE UNA APLICACION A TRES CAPAS

Los siguientes pasos ilustran la secuencia normal de eventos para una aplicación a tres capas:

1. El usuario cliente arranca la aplicación. El cliente conecta con el servidor de aplicaciones (el cual puede ser elegido en tiempo de ejecución). Si el servidor de aplicaciones no estuviera arrancado, lo arranca automáticamente. Los clientes reciben una interfaz IAppServer para comunicarse con el servidor de aplicaciones.

2. El cliente solicita los datos al servidor de aplicaciones, donde puede requerir todos los datos de una vez o pedir una parte de ellos poco a poco.

3. El servidor de aplicaciones lee la información solicitada por el cliente del motor de bases de dtaos (estableciendo una conexión con si fuera necesario), empaqueta la información y devuelve la información al cliente. La información adicional (por ejemplo, las características de los campos) pueden ser incluida en los metadatos del paquete de datos. Este proceso de empaquetamiento de datos es llamado providing.

4. El cliente decodifica el paquete recibido y muestra los datos al usuario.

5. Cuando el usuario de la aplicación cliente realiza modificaciones sobre los datos (añadir, borrar o modificar registros) estas modificaciones son almacenadas en un log temporal.

6. Finalmente los clientes envian las actualizaciones al servidor de aplicaciones, el cual responde normalmente a cada acción del usuario. Para aplicar los cambios, los paquetes de los clientes leerán y cambiarán el log antes de enviar sus paquetes de datos al servidor.

7. El servidor de aplicaciones decodifica el paquete y efectua los cambios (en el contexto de una transacción cuando sea apropiada). Si un registro no puede ser actualizado (por ejemplo, porque otra aplicación cambie el registro antes de que el cliente lo solicite y después de que el cliente haya aplicado los cambios), el servidor de aplicaciones intenta reconciliar los cambios de los clientes con los datos actuales, y guarda los registros que podrían no ser actualizados. Este proceso de guardar y resolver problemas con los registros es llamado resolving.

8. Cuando el servidor de aplicaciones finaliza el proceso de actualización de registros, devuelve los registros no actualizados al cliente para que pueda resolverlos por el mismo.

9. El cliente resuelve los registros que el servidor no ha podido actualizar. Hay muchas maneras de que un cliente pueda resolver estos registros. Generalmente el cliente intenta corregir la situación asegurándose de que los registros estén validados antes de enviarlos. Si la situación puede ser rectificada, entonces vuelve a enviar los datos al servidor.

10. El cliente desempaqueta los datos que vienen del servidor y refresca su caché local.

En la siguiente parte de este artículo veremos la estructura de una aplicación cliente.

Pruebas realizadas en Delphi 7.

12 noviembre 2007

Creando tablas de memoria con ClientDataSet

Una de las cosas que más se necesitan en un programa de gestión es la posibilidad crear tablas de memoria para procesar datos temporalmente, sobre todo cuando los datos origen vienen de tablas distintas.

Es muy común utilizar componentes de tablas de memoria tales como los que llevan los componentes RX (TRxMemoryData) o el componente kbmMemTable. Pues veamos como hacer tablas de memoria utilizando el componente de la clase TClientDataSet sin tener que utilizar ningún componente externo a Delphi.

DEFINIENDO LA TABLA

Lo primero es añadir a nuestro proyecto un componente ClientDataSet ya sea en un formulario o en un módulo de datos. Como vamos a crear una tabla de recibos lo vamos a llamar TRecibos.

Ahora vamos a definir los campos de los que se compone la tabla. Para ello pulsamos el botón [...] en la propiedad FieldDefs. En la ventana que se abre pulsamos el botón Add New y vamos creando los campos:

Name DataTpe Size
-----------------------------------
NUMERO ftInteger 0
CLIENTE ftString 80
IMPORTE ftFloat 0
PAGADO ftFloat 0
PENDIENTE ftFloat 0

Para crear la tabla de memoria pulsamos el componente TClientDataSet con el botón derecho del ratón y seleccionamos Create DataSet. Una vez creado sólo nos falta hacer que los campos sean persistentes. Eso se consigue haciendo doble clic sobre el componente y pulsando la combinación de teclas CTRL + A.

Con estos sencillos pasos ya hemos creado una tabla de memoria y ya podemos abrirla para introducir datos. No es necesario abrir la tabla ya que estas tablas de memoria hay que dejarlas activas por defecto.

DANDO FORMATO A LOS CAMPOS

Como tenemos tres campos de tipo real vamos a dar formato a los mismos del siguiente modo:

1. Hacemos doble clic sobre el componente ClientDataSet.

2. Seleccionamos los campos IMPORTE, PAGADO y PENDIENTE.

3. Activamos en el inspector de objetos su propiedad Currency.

Con esto ya tenemos los campos en formato moneda y con decimales.

REALIZANDO CALCULOS AUTOMATICAMENTE

A nuestra tabla de recibos le vamos a hacer que calcule automáticamente el importe pendiente. Esto lo vamos a hacer antes de que se ejecute el Post, en el evento BeforePost:

procedure TFormulario.TRecibosBeforePost( DataSet: TDataSet );
begin
TRecibosPENDIENTE.AsFloat := TRecibosIMPORTE.AsFloat - TRecibosPAGADO.AsFloat;
end;

De este modo, tanto si insertamos un nuevo registro como si lo modificamos realizará el cálculo del importe pendiente antes de guardar el registro.

AÑADIENDO, EDITANDO Y ELIMINANDO REGISTROS DE LA TABLA

Insertamos tres registros:

begin
TRecibos.Append;
TRecibosNUMERO.AsInteger := 1;
TRecibosCLIENTE.AsString := 'TRANSPORTES PALAZON, S.L.';
TRecibosIMPORTE.AsFloat := 1500;
TRecibosPAGADO.AsFloat := 500;
TRecibos.Post;

TRecibos.Append;
TRecibosNUMERO.AsInteger := 2;
TRecibosCLIENTE.AsString := 'TALLERES CHAPINET, S.L.';
TRecibosIMPORTE.AsFloat := 200;
TRecibosPAGADO.AsFloat := 200;
TRecibos.Post;

TRecibos.Append;
TRecibosNUMERO.AsInteger := 3;
TRecibosCLIENTE.AsString := 'GRUAS MARTINEZ, S.L.';
TRecibosIMPORTE.AsFloat := 625;
TRecibosPAGADO.AsFloat := 350;
TRecibos.Post;
end;

Si queremos modificar el primer registro:

begin
TRecibos.First;
TRecibos.Edit;
TRecibosCLIENTE.AsString := 'ANTONIO PEREZ BERNAL';
TRecibosIMPORTE.AsFloat := 100;
TRecibosPAGADO.AsFloat := 55;
TRecibos.Post;
end;

Y para eliminarlo:

begin
TRecibos.First;
TRecibos.Delete;
end;

MODIFICANDO LOS CAMPOS DE LA TABLA

Si intentamos añadir un nuevo campo a la tabla en FieldDefs y luego pulsamos CTRL + A para hacer el campo persistente veremos que desaparece de la definición de campos. Para hacerlo correctamente hay que hacer lo siguiente:

1. Pulsamos el componente ClientDataSet con el botón derecho del ratón.

2. Seleccionamos Clear Data.

3. Añadimos el nuevo campo en FieldDefs.

4. Volvemos a pulsar el el botón derecho del ratón el componente y seleccionamos Create DataSet.

5. Pulsamos CTRL + A para hacer persistente el nuevo campo.

Estos son los pasos que hay que seguir si se crean, modifican o eliminan campos en la tabla.

CREANDO CAMPOS VIRTUALES PARA SUMAR COLUMNAS

Vamos a crear tres campos virtuales que sumen automáticamente el valor de las columnas IMPORTE, PAGADO y PENDIENTE para totalizarlos. Comencemos con el cálculo del importe total:

1. Pulsamos el componente ClientDataSet con el botón derecho del ratón.

2. Seleccionamos Clear Data.

3. Hacemos doble clic en el componente ClientDataSet.

4. Pulsamos la combinación de teclas CTRL + N para añadir un nuevo campo:

Name: TOTALIMPORTE
FieldType: Agregate

5. Pulsamos Ok. Seleccionamos el campo creado escribimos en su propiedad Expression:

SUM(IMPORTE)

y activamos su propiedad Active. También activamos su propiedad Currency.

6. Creamos en el formulario un campo de tipo DBText y asociamos en nuevo campo creado:

DataSource: TRecibos
DataField: TOTALIMPORTE

7. Volvemos a pulsar el el botón derecho del ratón el componente y seleccionamos Create DataSet.

8. Activamos en el componente TClientDataSet la propiedad AggregatesActive.

Igualmente habría que crear dos campos más para sumar las columnas del importe pagado y el importe pendiente.

Utilizar ClientDataSet para crear tablas de memoria es ideal para procesar listados en tablas temporales sin tener que volcar el resultado en ninguna base de datos. Además podemos importar y exportar datos a XML usando el menú contextual de este componente.

Pruebas realizadas en Delphi 7.

Publicidad