Su IP: 18.97.9.170
Usar el ScriptControl para crear aplicaciones extensibles
Este artículo fue publicado originalmente en octubre del 2000 como introducción a las técnicas de extensibilidad para desarrolladores en Visual Basic (e incluía una cantidad de detalles técnicos de implementación que han sido eliminados para esta versión) sin embargo, puede ser útil para los integradores de ClearLight como ilustración de los conceptos de extensibilidad que orientan el uso de scripts
Una aplicación "extensible" es aquella a la cual los usuarios pueden agregarle funcionalidad adicional a la prevista por sus diseñadores y constructores. Los productos que integran la suite Office de Microsoft, por ejemplo, son extensibles mediante el uso de Visual Basic para Aplicaciones. Los plugins, los scripts y el uso de XML hacen "extensibles" a los navegadores web.
Nuestra misión es producir aplicaciones empresariales, que además de cumplir con los requisitos básicos de robustez y completitud, puedan mercadearse a un precio razonable y que esa "economía de adquisición" sea seguida del más bajo "costo de explotación" posible. Para poder cumplir este objetivo, es necesario alcanzar un gran volumen de ventas. Y para lograr un gran volumen de ventas, en un mercado tan competido como lo es el de los sistemas empresariales, hay que ofrecer algo más que precios bajos. Por esto enfocamos nuestro trabajo de investigación y desarrollo hacia la búsqueda y construcción de sistemas que puedan adaptarse a los requerimientos más específicos de cualquier usuario potencial. Y el resultado fue una solución sencillísima basada en el uso de la tecnología de scripting, y de las posibilidades de interoperabilidad que ofrecen las tecnologías de orientación a objetos.
El concepto fundamental de nuestro modelo es el de "Punto de Extensión". Un punto de extensión es cualquier operación implementada en el sistema en la cual un usuario podría introducir un cambio. Por supuesto que en casi ninguno de nuestros sistemas "grandes" están identificados todos los puntos de extensión (al final, cada acción realizada por el sistema es potencialmente un punto de extensión, desde la validación de una caja de texto hasta la agregación de un detalle a una factura). Pero el concepto de punto de extensión nos permite agregar rápidamente la funcionalidad requerida (o mejor dicho, suministrar una interfaz para que el usuario del sistema agregue la funcionalidad).
Veamos un primer ejemplo, tomado de uno de nuestros sistemas. Se trata de una transferencia interna de mercancías entre almacenes. Esta operación se inicia desde una forma en la cual el operador introduce los datos básicos de la transferencia: la fecha en la que se realizó, el motivo de la misma, el almacén de origen, el almacén de destino y los detalles (que en esencia se reducen al código y cantidad de los diferentes artículos movidos). No siendo una operación con efecto contable, que se incorporó al sistema sólo como soporte operativo, ignoramos inicialmente el costo unitario de los productos. Pero ocurre que un cliente necesitó conocer este costo, imprimirlo en el documento de transferencia y consultarlo en algunos reportes.
Para satisfacer este requerimiento con los enfoques tradicionales, habría resultado necesario modificar el código fuente del programa, agregando una referencia a una columna adicional de la tabla de detalles de transferencia (el Costo Unitario). Y este cambio en la fuente habría implicado la necesidad de actualizar la estructura de la tabla de detalles de transferencia en todos los otros usuarios que actualizaran el programa despues de este cambio. Además de que habría sido necesario compilar nuevamente el sistema completo, y tal vez reinstalarlo en los equipos del cliente en caso de que alguno de los componentes empleados en el entorno de desarrollo se hubiese actualizado desde la instalación original.
Pensando en cómo satisfacer los requerimientos de este cliente (que de todas maneras tuvo que actualizar su sistema), se nos ocurrió insertar en el controlador de la operación, el siguiente código:
If isOk Then
' isOk indica que el registro se realizó
correctamente If instTransferencia.Load(instTransferencia.Numero) Then ExecuteScript "postTransferencia.vbs", instTransferencia End If End If |
En esencia, lo que hace este código es llamar a la función ExecuteScript, para que esta a su vez determine si existe el archivo postTransferencia.vbs y, de ser así, cargue su código en un control de scripting de Microsoft (Microsoft Script Control), le pase la referencia a instTransferencia (la transferencia que acaba de ser procesada) y ejecute la Sub Main definida en dicho archivo.
Veamos ahora el codigo contenido en portTransferencia.vbs:
Sub
Main() Dim dbHandle ' DAO.Database Dim pItemInv ' Articulo de Inventario Dim pDetalle ' Detalle de la Transferencia Dim sQuery ' Para Armar la Sentencia SQL
Set
dbHandle = Factoria.CrearObjeto("DATABASE") |
Por supuesto que este código no tiene nada de especial, salvo por el hecho de que pudo haber sido escrito por cualquier usuario bien informado del sistema sin que nosotros nos hubiésemos siquiera enterado. En esencia, lo que hace es, para cada renglón de la transferencia, agrega a la fila correspondiente de la tabla (identificada por el número de la transferencia y el número del renglón) el costo unitario del artículo (obtenido de la fila correspondiente de la tabla itemsInventario).
Aunque bien visto, el código si tiene algunas cosas especiales: las referencias a los objetos OwnerObject y Factoria.
La Factoria es una fábrica de objetos del espacio de aplicación, que pueden ser utilizados desde el script.
Adicionalmente, brinda funciones de soporte general al script (por ejemplo, vemos Factoria.NumeroDB(OwnerObject.Numero). NumeroDB es una función que traduce un argumento numérico a un formato aceptable por el gestro de BD. Idealmente debería estar en una DLL, pero está en un módulo .bas de la aplicación.
Pero lo realmente importante de la Factoria es la posibilidad de proveer al script de referencias a muchos objetos de la aplicación. La clase CFactoria exporta la función CrearObjeto(sTipoObjeto) As Object (sTipoObjeto debe ser una cadena, pero como VBScript no soporta ningún tipo de datos con excepción del Variant, tenemos por norma no especificar tipos en ninguna función construída para ser llamada desde un script). La estructura de esta función es un Select Case donde, dependiendo del valor de sTipoObjeto se instancian nuevos objetos (o se copian referencias a los objetos existentes, como la referencia a la BD o a los "almacenes": proveedores de servicio de acceso especializados en un tipo específico de objeto) y se pasan al cliente. A través de la factoría los scripts pueden crear y manipular la mayoría de los objetos que definen los niveles de dominio y aplicación del sistema anfitrión. Haciendo clic aquí, puede acceder a la documentación en línea sobre la factoria de ClearLight.
Hay más sobre la extensibilidad: el uso de atributos para agregar datos a la definición básica de las entidades originales del sistema, el uso del registro o de la BD para pasar valores entre dos scripts que se ejecutan secuencialmente, o de DLLs de extensión de las formas.