Tarea A: Libros y registro de entrada y salida

De Egeasy
Saltar a: navegación, buscar

<?php echo "Hola mundo"; ?> En esta sección, vamos a implementar el registro de entrada y salida que acabamos de definir. Para comenzar a trabajar, te recomendamos que descargues este proyecto básico que te servirá como punto de partida.
En el directorio #Source, crea un fichero y llámalo Main.ndf. Ábrelo con tu editor favorito (te recomendamos EditPlus) y vamos a comenzar a trabajar. Empezaremos definiendo el concepto Entrada:

unidad [Main]
tipo [Entrada] es contenedor
   [Datos generales] es formulario
      [Número] es texto
      [Fecha] es texto
      [Remitente] es texto
      [Destinatario] es texto
   fin
fin


¿Qué hemos hecho?
En primer lugar, hemos declarado el nombre de la unidad [Main] en la que estamos trabajando. Podemos definir nuestro sistema en cuantos ficheros queramos, pero para que el compilador los analice, debemos darle un nombre de unidad a cada uno y, además, incluirlo en el fichero del proyecto, como veremos más adelante. A continuación, hemos declarado el tipo Entrada diciendo que es un contenedor. Contenedor es un tipo nativo de la plataforma y una de las piezas fundamentales de ODL. Los contenedores nos permitirán definir, entre otros, formularios y colecciones de datos con gran facilidad. Dentro del contenedor hemos definimos una componente formulario, indicando que vamos a declarar un formulario de datos. Seguidamente, decimos que este formulario tiene cuatro campos (de momento dejaremos fuera la documentación adjunta), todos de tipo texto. Por último, cerramos la declaración de formulario y la declaración del contenedor Entrada. Ya está. Ya podemos crear entradas en nuestro sistema. ¿Dónde? En el Libro de entrada:

[Libro de entrada] es contenedor
   [Contenido] es coleccion
      -nombre_tabla = "TC$ENTRADAS";
   
      contiene [Entrada]
      
      columna [Número]
         -columna_bd.nombre = "NUMERO";
         -origen = [Datos generales].[Número];
      columna [Fecha]
         -columna_bd.nombre = "FECHA";;
         -origen = [Datos generales].[Fecha];
   fin
fin

En este fragmento de código, definimos el Libro de entrada también como contenedor. Pero, ¿no ponemos tipo antes de [Libro de entrada]? Antes de continuar es necesario aclarar un concepto. En ODL se pueden hacer dos clases de declaraciones:

  • Declaraciones de tipo
  • Declaraciones de sistema

Si se hace una declaración de tipo, estamos definiendo un objeto reutilizable y del que pueden existir varias instancias. Al hacer una declaración de sistema, estamos indicando que sólo existe una instancia. Por hacer un símil con la Programación Orientada a Objetos, las declaraciones de tipo serían las clases de las cuáles se crean instancias durante la vida de la aplicación y las declaraciones de sistema serían clases singleton.
El Libro de entrada es una definición de sistema; es decir, sólo existirá una instancia del libro en la aplicación. Por otro lado, podremos crear múltiples instancias de Entrada.
Dentro del Libro definimos una componente de tipo coleccion a la cuál denominamos Contenido, indicando que este objeto tiene una colección de objetos. El tipo de objetos que puede contener se especifica mediante la sentencia contiene. En este caso, indicamos que la colección Contenido contiene objetos de tipo Entrada.
En la aplicación final, una colección se verá como una lista de objetos. Para generar dicha lista, el sistema crea una tabla en la base de datos con las columnas que se mostrarán en la vista. El nombre de esta tabla lo especificamos en el atributo nombre_tabla. En el ejemplo, indicamos que para esta colección se cree la tabla TC$ENTRADAS.
Para añadir columnas a la vista utilizamos las declaraciones de columna. En nuestro libro, indicamos que queremos dos columnas: [Número] y [Fecha]. Para cada columna, deben indicarse al menos dos atributos:

  • Cómo se llamará la columna en la base de datos (columna_bd.nombre)
  • Qué dato se mostrará en la vista (origen)

Por ejemplo, para la columna [Número] decimos que en la base de datos se llamará NUMERO y que debe mostrar el campo [Datos generales].[Número] (es decir, el campo Número que está en el formulario [Datos generales] del objeto Entrada).Aunque en nuestro ejemplo una columna muestra el valor de un solo campo, no tenemos por qué limitarnos a este uso. Al atributo origen se le puede asignar una expresión más compleja, como por ejemplo una concatenación de campos.
Lo único que falta para que nuestro libro sea operativo es hacerlo accesible para los usuarios. Para ello, debemos definir una habitación y ubicar en ella el Libro de entrada:

[Registro de entrada y salida] es habitacion
   ubicado [Libro de entradas]
       -lugar = "Libros";
fin

Conceptualmente, una habitacion representa una oficina o un departamento de la organización. Dentro de una habitacion indicamos qué recursos de sistema van a estar disponibles para los usuarios de esa oficina. Esto nos ayuda a construir el sistema siguiendo la estructura organizativa de la corporación, pero, simultáneamente, a lograr que todos los recursos transversales sean accesibles allí donde sean necesarios. ¿Cómo? Realizando declaraciones de ubicado, indicando qué recursos de sistema van a estar disponibles para los usuarios de dicha habitacion.
Cada vez que ubiquemos un recurso, debemos indicar en el atributo lugar en qué grupo va a estar colocado. En nuestro ejemplo, decimos que queremos poner el Libro de entrada en el grupo Libros. No existe un conjunto de valores predefinidos para el atributo lugar. Se le puede asignar cualquier valor.
Ahora, sólo queda generar el modelo, instalar e iniciar el centro.
Cuando lo hayamos hecho, arrancamos la aplicación egExplorer y lo que nos aparecerá será una lista con todas las habitaciones disponibles en el sistema, donde la única que aperecerá será Registro de entrada y salida.

Figura 2 - Habitaciones disponibles

Si entramos en nuestra habitación, veremos a la izquierda el grupo Libros con el Libro de entrada ubicado y haciendo clic lo abriremos:

Figura 3 - Libro de entrada

Haciendo clic en Nuevo crearemos una nueva entrada en el Libro. ¿Y qué aparece? El formulario que hemos definido:

Figura 4 - Formulario Datos generales del objeto Entrada

Si creamos una entrada, la guardamos y volvemos al libro aparecerá el listado con un elemento mostrando el número y la fecha que hemos puesto:

Figura 5 - Libro de entradas con una Entrada creada

¿Y si además queremos incluir el Remitente? Pues no tenemos más que volver a nuestro código y añadir la columna en la coleccion:

[Libro de entrada] es contenedor
   [Contenido] es coleccion
       -nombre_tabla = "TC$ENTRADAS";
       contiene [Entrada]
       contiene [Número]
           -columna_bd.nombre = "NUMERO";
           -origen = [Datos generales].[Número];
       columna [Fecha]
           -columna_bd.nombre = "FECHA";
           -origen = [Datos generales].[Fecha];
       columna [Remitente]
           -columna_bd.nombre = "REMITENTE";
           -origen = [Datos generales].[Remitente];
   fin
fin

Compilamos y actualizamos el modelo. Al hacerlo, en la tabla TC$ENTRADAS se añadirá la columna REMITENTE. Si volvemos al egExplorer y abrimos el Libro de entrada veremos la columna Remitente incorporada.

Figura 6 - Entrada con la columna remitente

Y el campo Destinatario, ¿no lo ponemos como columna? Entonces, ¿dónde se almacena?

Es el momento de explicar cómo se almacenan los objetos en la plataforma egEasy.
egEasy utiliza una base de datos orientada a objetos, en vez de un esquema clásico de base de datos relacional. Con esta arquitectura no tenemos una tabla para cada objeto nuevo que se crea en la base de datos. En su lugar, hay una sola tabla (eg$resources) en la que se almacenan todos los recursos del sistema. La administración de esta tabla es completamente transparente para el desarrollador y dentro de ella todos los campos y atributos de cada objeto se guardan serializados en un campo binario.
Entonces, ¿para qué nos sirve una colección? Con la definición de una colección logramos dos objetivos. En primer lugar, definimos el ámbito en el que se pueden crear los objetos (el objeto Entrada se puede crear en la componente Contenido del Libro de entrada). Por otro lado, proporcionamos un método rápido y eficiente para mostrar una lista de objetos; si no utilizásemos las colecciones, en el momento de mostrar una lista habría que deserializar uno por uno los objetos, una operación que podría resultar muy lenta.


La definición del libro de salida es prácticamente igual al de entradas:

tipo [Salida] es contenedor
   [Datos generales] es formulario
       [Número] es texto
       [Fecha] es texto
       [Remitente] es texto
       [Destinatario] es texto
   fin
fin
[Libro de salida] es contenedor [Contenido] es coleccion -nombre_tabla = "TC$SALIDAS"; contiene [Entrada] columna [Número] -columna_bd.nombre = "NUMERO"; -origen = [Datos generales].[Número]; columna [Fecha] -columna_bd.nombre = "FECHA"; -origen = [Datos generales].[Fecha]; columna [Remitente] -columna_bd.nombre = "REMITENTE"; -origen = [Datos generales].[Remitente]; fin fin
[Registro de entrada y salida] es habitacion ubicado [Libro de entrada] -lugar = "Libros"; fin

Para hacerlo visible para los usuarios, debemos ubicarlo en la oficina:

[Registro de entrada y salida] es habitacion
   ubicado [Libro de entrada]
       -lugar = "Libros";
   ubicado [Libro de salida]
       -lugar = "Libros";
fin

¿Qué hemos aprendido?

  • En ODL existen dos clases de declaraciones: de tipo (podemos crear instancias de ellas) y de sistema (sólo existe una intancia).
  • El contenedor es uno de los tipos fundamentales de ODL y nos permite definir en su contexto componentes tales formularios y colecciones de datos.
  • Las colecciones se muestran en la aplicación final como listas de objetos en las que podemos crear contenedores.
  • Podemos añadir columnas a una colección haciendo uso de la sentencia columna.
  • La declaraciones de habitación nos permiten ubicar los recursos para hacerlos visibles a los usuarios.