Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Departamento de Computación
Miembros suplentes:
Fecha de lectura:
Calificación:
RESUMEN
Las aplicaciones de anotación de trabajo han ganado una relevancia notable en los últi-
mos años debido a la actual tendencia a trasladar todas las mecánicas habituales de los
entornos empresariales al ámbito ofimático. Esta filosofı́a es la perseguida por la aplicación
PhpReport, un programa web de software libre creado por la empresa Igalia. La primera
versión de dicha herramienta fue creada en el año 2003 y en año 2009 se decidió reimple-
mentarla por completo.
Este proyecto clásico de ingenierı́a consiste en la ampliación de la nueva versión de dicha
aplicación web de software libre para anotación de trabajo, añadiéndole nuevas funcionali-
dades y actualizando sus interfaces. Los objetivos concretos de esta ampliación de su nueva
versión son dotar a PhpReport de planificación a corto y largo plazo, añadirle capacidades
avanzadas de extracción de datos y un nuevo conjunto de interfaces web dinámicas.
Al dotarla de capacidades para anotar la planificación se pretende integrar dicho aparta-
do con la anotación de tareas, permitiendo un seguimiento más sencillo de la evolución de
los proyectos. Dicho seguimiento se podrá realizar a dos niveles: una planificación a largo
plazo (planificación completa del proyecto) y una planificación a corto plazo (planificaciones
periódicas del trabajo diario).
La extracción de datos avanzada persigue una obtención sencilla de informes, tanto
generales como de elementos individuales, de múltiples tipos. Para ello se persigue crear
un motor de extracción de información de un ámbito general y configurable en base a
parámetros, de manera que no sea necesario un método distinto para cada tipo de informe
requerido.
Un nuevo conjunto de interfaces dinámicas permitirán abandonar las actuales interfaces
web de PhpReport, todas de enfoque estático y por lo tanto susceptibles de necesitar un
gran número de recargas con cambios de información en el lado del servidor. El empleo
de ((widgets)) dinámicos permitirá dotar a la aplicación de una apariencia más moderna y
proporcionar una mejor experiencia al usuario, al cual se le evitará la recarga de la página
cuando requiere o guarda un conjunto de datos.
Una vez logrados estos tres objetivos se obtendrá una aplicación de anotación de trabajo
totalmente libre y funcional para el entorno empresarial, a la cual se planea realizar una
serie de mejoras y añadidos en el futuro con el objetivo tanto de mejorar su apariencia de
cara al usuario final como de aumentar la potencia de sus nuevas capacidades y mejorar su
rendimiento.
PALABRAS CLAVE
PhpReport Data-mining
Igalia PHP
Time-tracking PostgreSQL
Me gustarı́a agradecer a todos los miembros de Igalia la excelente acogida que me han
brindado durante todo el tiempo que he tenido la suerte de trabajar con ellos, gracias a los
cuales he tenido una de las mejores experiencias de toda mi vida, tanto en lo profesional
como en lo personal. Muy especialmente me gustarı́a agradecer a Jota, Jacobo y Chema
su apoyo, confianza y ayuda durante la elaboración de este trabajo, y por brindarme la
oportunidad de dar mis primeros pasos en el mundo laboral.
Índice general
Índice general I
Índice de tablas IV
Índice de figuras V
1. Prólogo 1
1.1. Marco del proyecto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2. Objetivos globales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.3. Contribuciones logradas . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.4. Estructura de la memoria . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2. Introducción 4
2.1. Igalia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.2. PhpReport . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.3. Herramientas y entorno de trabajo . . . . . . . . . . . . . . . . . . . . . . 5
2.3.1. Entorno informático básico de trabajo . . . . . . . . . . . . . . . . 5
2.3.2. Lenguajes, bibliotecas, modelos y enfoques empleados . . . . . . . . 5
2.3.3. Herramientas software empleadas . . . . . . . . . . . . . . . . . . . 20
2.3.4. Herramientas software testeadas . . . . . . . . . . . . . . . . . . . 22
2.4. Metodologı́a de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.4.1. Descripción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.4.2. Caracterı́sticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.4.3. Aplicación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
i
ÍNDICE GENERAL ii
4. Planificación de trabajo 33
4.1. Objetivos y descripción . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.1.1. Objetivos concretos . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.1.2. Descripción general . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.2. Análisis y diseño . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
4.2.1. Planificación a corto plazo . . . . . . . . . . . . . . . . . . . . . . 35
4.2.2. Planificación a largo plazo . . . . . . . . . . . . . . . . . . . . . . 36
4.2.3. Estructura final de la BD . . . . . . . . . . . . . . . . . . . . . . . 38
4.3. Implementación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
4.3.1. Creación de la base de datos . . . . . . . . . . . . . . . . . . . . . 41
4.3.2. Creación de los Value Object (VO) . . . . . . . . . . . . . . . . . . 41
4.3.3. Creación de los Data Access Object (DAO) . . . . . . . . . . . . . 42
4.3.4. Creación de las acciones . . . . . . . . . . . . . . . . . . . . . . . 43
4.3.5. Creación de las fachadas . . . . . . . . . . . . . . . . . . . . . . . 46
4.4. Pruebas y resultados obtenidos . . . . . . . . . . . . . . . . . . . . . . . . 46
4.4.1. Pruebas de VOs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
4.4.2. Pruebas de DAOs . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
4.4.3. Pruebas de acciones . . . . . . . . . . . . . . . . . . . . . . . . . . 48
B. Código 113
B.1. Planificación de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
B.2. Extracción de datos avanzada . . . . . . . . . . . . . . . . . . . . . . . . . 116
Referencias 122
Índice de tablas
iv
Índice de figuras
v
ÍNDICE DE FIGURAS vi
vii
Capı́tulo 1
Prólogo
1
1.2. Objetivos globales 2
Cada uno de los capı́tulos centrales del documento (el capı́tulo 4 en la página 33,
el 5 en la página 49 y el 6 en la página 61) recoge con mayor detalle las caracterı́sticas
de cada uno de estos objetivos globales.
Todos estas mejoras se han realizado respetando su estructura por capas, lo que hace
que el código sea limpio, modular y fácilmente ampliable y ((debugueable)), además de estar
totalmente documentado e incorporar pruebas formales en todos los fragmentos de código
no triviales a todos los niveles.
Se incluyen también una serie de apéndices que buscan complementar todo el contenido
anterior:
Introducción
Debido a que el proyecto se realizó en un contexto empresarial este capı́tulo está dedi-
cado a describir dicho entorno de trabajo, tanto desde el punto de vista social (descripción
de la empresa, su filosofı́a y perfil de los integrantes) como el organizativo (la metodologı́a
de trabajo empleada) o el técnico (las herramientas, bien software o hardware, relacionadas
con el trabajo realizado).
2.1. Igalia
Igalia [1] es una empresa de desarrollo software creada en el año 2001. Aunque ini-
cialmente se encontraba únicamente en la ciudad de A Coruña (oficina a la cual acudió el
alumno en numerosas ocasiones), actualmente ha adoptado una filosofı́a de trabajo distri-
buido, poseyendo otra oficina en Pontevedra y diversos empleados que trabajan de manera
remota en otras localizaciones geográficas.
Tal y como reza en la descripción que podemos leer en su web, la empresa Igalia tiene
como sus pilares fundamentales:
• El trabajo cooperativo entre todos sus miembros y una filosofı́a de cooperación asam-
blearia.
• Compartición de responsabilidades entre sus integrantes.
• Igualdad de condiciones entre los trabajadores.
• Prioridad máxima al desarrollo en software libre.
• Innovación en todos los campos, aunque siempre centrándose en el mundo del software
libre.
2.2. PhpReport
La aplicación alrededor de la cual gira este proyecto era en su versión anterior una
aplicación web implementada totalmente en PHP. Fue creada por Enrique Ocaña en el
año 2003, y desde entonces ha sido empleada en todo momento por los trabajadores de
la empresa para registrar el trabajo realizado. Además, en el año 2005 fue publicada bajo
licencia General Public License (GPL), y ha experimentado en estos años diversas mejoras
y bug-fixing por parte de miembros de la plantilla de Igalia.
4
2.3. Herramientas y entorno de trabajo 5
Con los años ha atravesado diversas versiones que tuvieron como resultado una am-
pliación constante de sus funcionalidades, además de la solución de los bugs que han ido
surgiendo. Por ello la aplicación que inicialmente tenı́a como único objetivo la anotación del
trabajo en base a un modelo muy sencillo fue adoptando entidades y capacidades nuevas.
El cálculo de horas extra, la clasificación de los clientes según su sector, el cálculo de las
horas de vacaciones o el cálculo de desviación de costes en los proyectos son algunas de los
múltiples añadidos que se han realizado a PhpReport desde su creación.
A pesar de la utilidad y potencial que ha demostrado en todos estos años, la aplicación
comienzar a presentar serios inconvenientes. En primer lugar, de cara al usuario presenta
unas interfaces web meramente funcionales, basadas totalmente en formularios estáticos.
A dı́a de hoy su interfaz ha quedado claramente desfasada al lado de otras aplicaciones
web con comportamientos dinámicos. Por otra parte, para los desarrolladores comienza a
convertirse en código insostenible debido a una barrera muy difusa entre la capa modelo
y la capa web, además de por los seis años de parches a intervalos regulares. Este código
con una capacidad de modularidad muy escasa supone un claro impedimento tanto para el
añadido de nuevas funcionalidades como para labores de bug-fixing.
Mejorar tanto la experiencia de los usuarios finales como el trabajo sobre el código de
futuros programadores, sean de Igalia o no, es el motivo para la confección de una nueva
versión de PhpReport, y por lo tanto de su ampliación abordada en este proyecto.
• El estado está compuesto de datos, será uno o varios atributos a los que se
habrán asignado unos valores concretos (datos).
• El comportamiento está definido por los procedimientos o métodos con que
puede operar dicho objeto, es decir, qué operaciones se pueden realizar con él.
• La identidad es una propiedad de un objeto que lo diferencia del resto, dicho
con otras palabras, es su identificador (concepto análogo al de identificador de
una variable o una constante).
PHP
Descripción [6, 7]
2.3. Herramientas y entorno de trabajo 8
Justificación
PHP fue percibido como el lenguaje idóneo para la realización del núcleo de la apli-
cación por presentar las siguientes caracterı́sticas:
• Soporte para una gran cantidad de bases de datos (MySQL, PostgreSQL, Ora-
cle...).
• Capacidades completas para POO desde su versión 5.
• Integración con multitud bibliotecas externas, dotándole de numerosas funcio-
nalidades, desde generar documentos en PDF hasta analizar código Extensible
Markup Language (XML).
• Sistema muy simple de creación de páginas web dinámicas mediante la ejecución
del código en el lado del servidor.
• Código notablemente más sencillo de mantener y extender gracias a su intuitiva
sintaxis y flexibilidad en el tipado.
• Siendo código abierto en su totalidad, PHP goza de la ayuda de un gran grupo
de programadores, permitiendo que los fallos de funcionamiento se encuentren
y reparen rápidamente.
• Diversas opciones para un control sencillo de la comunicación con el usuario en
el lado del servidor (manejo de sesiones, gestión de cookies, etc).
• Python[8, 9]
Python es un lenguaje de programación interpretado creado por Guido van Ros-
sum en el año 1991.
Se compara habitualmente con Tcl, Perl, Scheme, Java y Ruby. En la actualidad
Python se desarrolla como un proyecto de código abierto, administrado por la
Python Software Foundation. La última versión estable del lenguaje es la 3.1.1
Python permite dividir el programa en módulos reutilizables desde otros progra-
mas Python. Viene con una gran colección de módulos estándar que se pueden
utilizar como base de los programas (o como ejemplos para empezar a apren-
der Python). También hay módulos incluidos que proporcionan E/S de ficheros,
llamadas al sistema, sockets y hasta interfaces a GUI (interfaz gráfica con el
usuario) como Tk, GTK, Qt entre otros.
Python se utiliza como lenguaje de programación interpretado, lo que ahorra un
tiempo considerable en el desarrollo del programa, pues no es necesario compilar
ni enlazar. El intérprete se puede utilizar de modo interactivo, lo que facilita
experimentar con caracterı́sticas del lenguaje, escribir programas desechables o
probar funciones durante el desarrollo del programa.
El nombre del lenguaje proviene de la afición de su creador original, Guido van
Rossum, por los humoristas británicos Monty Python. El principal objetivo que
persigue este lenguaje es la facilidad, tanto de lectura como de diseño.
Entre sus otras caracterı́sticas podemos destacar:
◦ Soporte para los tres principales paradigmas de programación: orientada a
objetos, estructurada y funcional.
◦ Tipado dinámico.
◦ Resolución dinámica de nombres.
◦ Sintaxis más clara debido a su identación obligatoria.
◦ Soporte multiplataforma (consecuencia de ser un lenguaje interpretado).
◦ Facilidad de extensión mediante módulos en C o C++.
No hubo aspectos concretos de Python que motivaran su descarte, sino que
PHP se percibió como una opción más adecuada para nuestro propósito al estar
centrado en el desarrollo de aplicaciones web, con un gran número de librerı́as
y funciones sencillas para ello, especialmente en lo referente a páginas web
dinámicas.
PHPUnit
Descripción [10]
Framework de pruebas unitarias para PHP. Creado por Sebastian Bergmann, forma
parte de la familia de frameworks de pruebas xUnit. Actualmente es el framework
más empleado para la creación de pruebas en PHP, siendo algunas de sus principales
caracterı́sticas:
2.3. Herramientas y entorno de trabajo 10
Justificación
Las pruebas unitarias de PHP fueron realizadas completamente con PHPUnit debido
a que es el framework de pruebas más completo y empleado en ese lenguaje.
JavaScript
Descripción [11, 12]
Lenguaje de scripting basado en objetos, utilizado para acceder a objetos en apli-
caciones. Principalmente, se utiliza integrado en un navegador web permitiendo el
desarrollo de interfaces de usuario mejoradas y páginas web dinámicas. JavaScript es
un dialecto de ECMAScript y se caracteriza por ser un lenguaje basado en prototi-
pos, con entrada dinámica y con funciones de primera clase. JavaScript ha tenido
influencia de múltiples lenguajes y se diseñó con una sintaxis similar al lenguaje de
programación Java, aunque más fácil de utilizar para personas que no programan.
Todos los navegadores modernos interpretan el código JavaScript integrado dentro de
las páginas web. Para interactuar con una página web se provee al lenguaje JavaScript
de una implementación del Document Object Model (DOM).
El lenguaje fue inventado por Brendan Eich en la empresa Netscape Communications,
la que desarrolló los primeros navegadores web comerciales. Apareció por primera vez
en el producto de Netscape llamado Netscape Navigator 2.0.
Tradicionalmente, se venı́a utilizando en páginas web HyperText Markup Langua-
ge (HTML), para realizar operaciones y en el marco de la aplicación cliente, sin
acceso a funciones del servidor. JavaScript se ejecuta en el agente de usuario, al
mismo tiempo que las sentencias van descargándose junto con el código HTML.
Justificación
La elección del framework ExtJS (apartado 2.3.2 en la página 12), el cual está cons-
truido mediante JavaScript, implicó el uso de este lenguaje para la realización de las
interfaces web.
AJAX
Descripción [13]
2.3. Herramientas y entorno de trabajo 11
Asynchronous JavaScript And XML (AJAX) es una técnica de desarrollo web para
crear aplicaciones dinámicas. Estas aplicaciones se ejecutan en el cliente, es decir,
en el navegador de los usuarios mientras se mantiene la comunicación ası́ncrona
con el servidor en segundo plano. De esta forma es posible realizar cambios sobre
las páginas sin necesidad de recargarlas, lo que significa aumentar la interactividad,
velocidad y usabilidad en las aplicaciones. Habitualmente se considera a AJAX como
el soporte para el tipo más sencillo de aplicaciones Rich Internet Applications (RIA),
aunque no debemos confundirlo con las verdaderas aplicaciones RIA, de mucha mayor
complejidad.
AJAX es una tecnologı́a ası́ncrona, en el sentido de que los datos adicionales se
requieren al servidor y se cargan en segundo plano sin interferir con la visualización
ni el comportamiento de la página. JavaScript es el lenguaje interpretado (scripting
language) en el que normalmente se efectúan las funciones de llamada de AJAX
mientras que el acceso a los datos se realiza mediante XMLHttpRequest, objeto
disponible en los navegadores actuales. En cualquier caso, no es necesario que el
contenido ası́ncrono esté formateado en XML.
AJAX es una técnica válida para múltiples plataformas y utilizable en muchos sis-
temas operativos y navegadores dado que está basado en estándares abiertos como
JavaScript y DOM.
Justificación
Las interfaces dinámicas creadas por el alumno siguen el enfoque AJAX en su inmensa
mayorı́a ya que es el enfoque de diseño web que nos permite delegar código en el
navegador del cliente y obtener interfaces dinámicas con su comunicación ası́ncrona
con el servidor (uno de los objetivos globales del proyecto).
• RIA[14]
Las aplicaciones plenamente Rich Internet Applications (RIA) son aplicaciones
web que tienen la mayorı́a de las caracterı́sticas de las aplicaciones tradicionales.
Estas aplicaciones utilizan un navegador web especı́fico para ejecutarse, y por
medio de un plugin, o independientemente mediante una máquina virtual o un
sandbox, se agregan las caracterı́sticas adicionales.
Esta surge como una combinación de las ventajas que ofrecen las aplicaciones
Web y las aplicaciones tradicionales. Buscan mejorar la experiencia del usuario
Normalmente en las aplicaciones web hay una recarga continua de páginas cada
vez que el usuario pulsa sobre un enlace. De esta forma se produce un tráfico
muy alto entre el cliente y el servidor, llegando muchas veces a recargar la misma
página con un mı́nimo cambio.
En los entornos RIA, en cambio, no se producen recargas de página, ya que
desde el principio se carga toda la aplicación, y sólo se produce comunicación
con el servidor cuando se necesitan datos externos como datos de una BD o de
otros ficheros externos.
2.3. Herramientas y entorno de trabajo 12
ExtJS
Descripción [15, 16]
Biblioteca de JavaScript para el desarrollo de aplicaciones web interactivas usando
tecnologı́as como AJAX, Dynamic HTML (DHTML) y DOM. Como casi todas las
interfaces, se basa en la programación dirigida por eventos.
Originalmente construida como una extensión de la biblioteca YUI, en la actualidad
puede usarse como extensión para las biblioteca jQuery y Prototype. Desde la versión
1.1 puede ejecutarse como una aplicación independiente.
Incluye un gran número de ((widgets)) y caracterı́sticas, como:
Justificación
Se eligió la biblioteca ExtJS frente a otras por presentar un gran abanico de po-
sibilidades de personalización en un nivel superior, disponiendo además de un gran
número de ((widgets)) ya predefinidos y fácilmente configurables de diversos modos,
incluyendo tanto contenedores como elementos individuales o de comunicación (e.g.
proxy para XML), lo que facilitaba al programador la obtención de una interfaz de
alto nivel.
• jQuery[17, 18]
2.3. Herramientas y entorno de trabajo 13
PostgreSQL
Descripción [21, 22]
Sistema de gestión de base de datos relacional orientada a objetos de software libre,
publicado bajo la licencia Berkeley Software Distribution (BSD). Se trata de uno de
los sistemas de gestión de bases de datos más avanzados en la actualidad, entre cuyas
caracterı́sticas podemos destacar:
Justificación
PostgreSQL fue el sistema de gestión de bases de datos para el proyecto debido a que
presenta las siguientes ventajas frente a sus competidores:
• MySQL[8, 9]
MySQL es un sistema de gestión de base de datos relacional, multihilo y mul-
tiusuario con más de seis millones de instalaciones. MySQL AB (desde enero de
2008 una subsidiaria de Sun Microsystems y ésta a su vez de Oracle Corporation
desde abril de 2009) desarrolla MySQL como software libre en un esquema de
licenciamiento dual.
Por un lado se ofrece bajo la GPL para cualquier uso compatible con esta licencia,
pero para aquellas empresas que quieran incorporarlo en productos privativos
deben comprar a la empresa una licencia especı́fica que les permita este uso.
Está desarrollado en su mayor parte en ANSI C.
Entre sus caracterı́sticas actuales (versión 5.1.46) encontramos:
2.3. Herramientas y entorno de trabajo 15
◦ Procedimientos almacenados.
◦ Cursores.
◦ Vistas actualizables.
◦ Modo Strict.
◦ Motores de almacenamiento independientes.
◦ Caché de queries.
◦ Selects anidados.
◦ Soporte para Secure Socket Layer (SSL).
No presentó motivos propios para descartarla, sino que se prefirió PostgreSQL
debido a sus optimizaciones para manejo de grandes volúmenes de datos (ciertos
cálculos requieren la extracción de un gran número de tareas) y a su mayor
abanico de tipos de datos (lo cual permite el empleo de un gran número de
funciones especı́ficas que permiten obtener datos calculados en las queries).
Apache
Descripción [23, 24]
Servidor web HyperText Transfer Protocol (HTTP) de código abierto para platafor-
mas Unix (BSD, GNU/Linux, etc.), Windows, Macintosh y otras, que implementa el
protocolo HTTP/1.1 y la noción de sitio virtual. Cuando comenzó su desarrollo en
1995 se basó inicialmente en código del popular NCSA HTTPd 1.3, pero más tarde
fue reescrito por completo. Su nombre se debe a que Behelendorf eligió ese nombre
porque querı́a que tuviese la connotación de algo que es firme y enérgico pero no
agresivo, y la tribu Apache fue la última en rendirse al que pronto se convertirı́a en
gobierno de EEUU, y en esos momentos la preocupación de su grupo era que llegasen
las empresas y ((civilizasen)) el paisaje que habı́an creado los primeros ingenieros de
internet. Además Apache consistı́a solamente en un conjunto de parches a aplicar al
servidor de NCSA. Era, en inglés, a patchy server (un servidor ((parcheado))).
Apache presenta entre otras caracterı́sticas altamente configurables, bases de datos
de autenticación y negociado de contenido, pero fue criticado por la falta de una
interfaz gráfica que ayude en su configuración.
Es usado primariamente para enviar páginas web estáticas y dinámicas en la World
Wide Web. Muchas aplicaciones web están diseñadas asumiendo como ambiente de
implantación a Apache, o que utilizarán caracterı́sticas propias de este servidor web.
Apache es el componente de servidor web en la popular plataforma de aplicaciones
LAMP, junto a MySQL y los lenguajes de programación PHP/Perl/Python (y ahora
también Ruby).
La licencia de software bajo la cual el software de la fundación Apache es distribuido
es una parte distintiva de la historia de Apache HTTP Server y de la comunidad de
código abierto. La Licencia Apache permite la distribución de derivados de código
abierto y cerrado a partir de su código fuente original.
2.3. Herramientas y entorno de trabajo 16
Justificación
Apache es el servidor web libre más popular en la actualidad, con una calidad probada
a lo largo de los años y una gran cantidad de módulos para aumentar o mejorar su
funcionamiento, lo cual hizo que fuera directamente el elegido para probar todas las
páginas web.
XML
Descripción [25, 26]
Siglas en inglés de Extensible Markup Language (lenguaje de marcas extensible), es
un metalenguaje extensible de etiquetas desarrollado por el World Wide Web Con-
sortium (W3C). Es una simplificación y adaptación del Standard Generalized Mark-
up Language (SGML) y permite definir la gramática de lenguajes especı́ficos (de
la misma manera que HTML es a su vez un lenguaje definido por SGML). Por lo
tanto XML no es realmente un lenguaje en particular, sino una manera de definir
lenguajes para diferentes necesidades. Algunos de estos lenguajes que usan XML para
su definición son Extensible HyperText Markup Language (XHTML), Scalable Vector
Graphics (SVG), Mathematical Markup Language (MathML).
El formato XML no nació sólo para su aplicación en Internet, sino que se propone
como un estándar para el intercambio de información estructurada entre diferentes
plataformas. Se puede usar en bases de datos, editores de texto, hojas de cálculo y
casi cualquier cosa imaginable.
Su amplia extensión se debe en gran parte a que es una tecnologı́a sencilla que tiene
a su alrededor otras que la complementan y la hacen mucho más grande y con unas
posibilidades mucho mayores. Tiene un papel muy importante en la actualidad ya
que permite la compatibilidad entre sistemas para compartir la información de una
manera segura, fiable y fácil.
Justificación
XML fue empleado en el proyecto como principal lenguaje para intercambio de infor-
mación entre sistemas por el simple motivo de ser el más extendido en la actualidad,
prácticamente considerado un estándar de facto (con soporte del W3C), y por tanto
el idóneo para lograr la comunicación de la aplicación con otras externas.
En los comienzos de la era internet XML logró su aceptación gracias, entre otras
caracterı́sticas, a que su similitud con HTML facilitó la reutilización de tecnologı́a ya
existente para este último.
2.3. Herramientas y entorno de trabajo 17
JSON
Descripción [27, 28]
JavaScript Object Notation (JSON) es un formato ligero para el intercambio de datos,
subconjunto de la notación literal de objetos de JavaScript que no requiere el uso de
XML.
La simplicidad de JSON ha dado lugar a la generalización de su uso, especialmente
como alternativa a XML en AJAX. Una de las ventajas de JSON sobre XML como
formato de intercambio de datos en este contexto es que es mucho más sencillo
escribir un analizador semántico de JSON. En JavaScript, JSON puede ser analizado
trivialmente usando el procedimiento eval(), lo cual ha sido fundamental para la
aceptación de JSON por parte de la comunidad de desarrolladores AJAX, debido a la
ubicuidad de JavaScript en casi cualquier navegador web.
JSON se emplea habitualmente en entornos donde el tamaño del flujo de datos entre
cliente y servidor es de vital importancia (de aquı́ su uso por Yahoo, Google, etc, que
atienden a millones de usuarios) cuando la fuente de datos es explı́citamente de fiar
y donde no es importante el no disponer de procesamiento XSLT para manipular los
datos en el cliente.
Justificación
ExtJS incluye métodos de parseo y captura de datos de JSON más potentes que los de
XML para los ((widgets)) AJAX más complejos, y por ello se empleó como lenguaje de
intercambio de información en casos concretos, a fin de aprovechar dichas ventajas.
HTML
Descripción [29, 30]
HyperText Markup Language (HTML) es el lenguaje de marcado predominante para
la construcción de páginas web. Es usado para describir la estructura y el contenido
en forma de texto, ası́ como para complementar el texto con objetos tales como
imágenes. HTML se escribe en forma de ((etiquetas)), rodeadas por corchetes angulares
(<, >). HTML también puede describir, hasta un cierto punto, la apariencia de un
documento, y puede incluir un script (por ejemplo Javascript), el cual puede afectar
el comportamiento de navegadores web y otros procesadores de HTML.
HTML también es usado para referirse al contenido del tipo de MIME text/html
o todavı́a más ampliamente como un término genérico para el HTML, ya sea en
forma descendida del XML (como XHTML 1.0 y posteriores) o en forma descendida
directamente de SGML (como HTML 4.01 y anteriores).
Justificación
2.3. Herramientas y entorno de trabajo 18
En las páginas web de cualquier tipo se empleó HTML para su realización (directa
o indirectamente), por el simple hecho de ser el lenguaje de marcado estándar en
tecnologı́as web.
Selenium
Descripción [31, 32]
Selenium es un framework para testeo de aplicaciones web. Proporciona una herra-
mienta de registro y reproducción de acciones que permite crear tests sin necesidad
de emplear explı́citamente un lenguaje de scripting. Selenium proporiona un Domain
Specific Language (DSL) para la escritura de tests formales (pero no unitarios) en di-
versos de los más populares lenguajes de programación (Java, Ruby, Python, PHP...).
La reproducción de los tests es posible en la mayorı́a de los navegadores web moder-
nos. Selenium funciona en plataformas Windows, Linux y Macintosh.
Selenium incluye un Integrated Development Environment (IDE) implementado como
extensión de Firefox que permite grabar, editar y reproducir tests (con capacidades
de debugging). Incluye las siguientes caracterı́sticas:
Justificación
Selenium fue el framework escogido para realizar las pruebas sobre las interfaces web
debido a su facilidad de uso, tanto a la hora de escribir las pruebas como de ejecutarlas,
a la gran variedad de comandos que permite ejecutar (incluyendo algunos de cierta
complejidad, como ((drag & drop))), sus opciones de debugging y a su capacidad de
registrar las acciones realizadas por el usuario, lo que permite una escritura rápida de
los tests.
UML
Descripción [33, 34]
2.3. Herramientas y entorno de trabajo 19
Lenguaje Unificado de Modelado (UML, por sus siglas en inglés, Unified Modeling
Language) es el lenguaje de modelado de sistemas de software más conocido y utili-
zado en la actualidad; está respaldado por el OMG (Object Management Group). Es
un lenguaje gráfico para visualizar, especificar, construir y documentar un sistema.
UML ofrece un estándar para describir un ((plano)) del sistema (modelo), incluyendo
aspectos conceptuales tales como procesos de negocio y funciones del sistema, y as-
pectos concretos como expresiones de lenguajes de programación, esquemas de bases
de datos y componentes reutilizables.
Es importante resaltar que UML es un ((lenguaje de modelado)) para especificar o
para describir métodos o procesos. Se utiliza para definir un sistema, para detallar
los artefactos en el sistema y para documentar y construir. En otras palabras, es el
lenguaje en el que está descrito el modelo.
Se puede aplicar en el desarrollo de software entregando gran variedad de formas
para dar soporte a una metodologı́a de desarrollo de software (tal como el Proceso
Unificado Racional o RUP), pero no especifica en sı́ mismo qué metodologı́a o proceso
usar.
Justificación
Tanto los diagramas incluidos en esta memoria propios de la fase de diseño como
los de la BD empleados como entrada del programa tedia2sql (comentado en el
apartado 2.3.3 en la página siguiente) durante la implementación se realizaron como
diagramas UML por ser éste el lenguaje de modelado más conocido, extendido y
trabajado hoy en dı́a, existiendo además múltiples herramientas software para su
manejo.
E-R
Descripción [35, 36]
Un diagrama o modelo entidad-relación (a veces denominado por su siglas E-R,
((Entity relationship)), o DER, ((Diagrama de Entidad Relación))) es una herramienta
para el modelado de datos de un sistema de información. Estos modelos expresan en-
tidades relevantes para un sistema de información, sus inter-relaciones y propiedades.
El modelo Entidad-Relación es un concepto de modelado para bases de datos, pro-
puesto por Peter Chen en 1976, mediante el cual se pretende ‘visualizar’ los objetos
que pertenecen a la BD como entidades (se corresponde al concepto de objeto de
la Programación Orientada a Objetos) las cuales tienen unos atributos y se vinculan
mediante relaciones.
Es una representación conceptual de la información. Mediante una serie de procedi-
mientos se puede pasar del modelo E-R a otros, como por ejemplo el modelo relacional.
Justificación
El modelo Entidad Relación es el modelo por excelencia para la creación de bases
de datos, con probada eficacia durante más de tres décadas durante las cuales se ha
2.3. Herramientas y entorno de trabajo 20
mejorado de diversos modos, haciéndolo la mejor opción para crear los diagramas de
diseño de la base de datos.
Modelo relacional
Descripción [37]
El modelo relacional para la gestión de una BD es un modelo de datos basado en
la lógica de predicados y en la teorı́a de conjuntos. Es el modelo más utilizado en la
actualidad para modelar problemas reales y administrar datos dinámicamente. Tras
ser postuladas sus bases en 1970 por Edgar Frank Codd, de los laboratorios IBM
en San José (California), no tardó en consolidarse como un nuevo paradigma en los
modelos de base de datos.
Su idea fundamental es el uso de ((relaciones)). Estas relaciones podrı́an considerarse
en forma lógica como conjuntos de datos llamados ((tuplas)). Pese a que ésta es la
teorı́a de las bases de datos relacionales creadas por Edgar Frank Codd, la mayorı́a
de las veces se conceptualiza de una manera más fácil de imaginar, esto es, pensando
en cada relación como si fuese una tabla que está compuesta por registros (cada fila
de la tabla serı́a un registro o tupla), y columnas (también llamadas campos).
Justificación
Aunque no se crearon manualmente las tablas de base de datos (se empleó la herra-
mienta tedia2sql, apartado 2.3.3), éstas se basan en el modelo relacional, el cual
permite mapear los diagramas Entidad Relación a la estructura de tablas de una BD,
por lo que su uso era necesario para pasar del modelo a la ‘implementación’.
2.4.2. Caracterı́sticas
Las caracterı́sticas fundamentales de la metodologı́a son:
Corrección de todos los errores antes de añadir nueva funcionalidad. Hacer entregas
frecuentes.
Refactorización del código, es decir, reescribir ciertas partes del código para au-
mentar su legibilidad y mantenibilidad pero sin modificar su comportamiento. Las
pruebas han de garantizar que en la refactorización no se ha introducido ningún fallo.
todo el personal pueda corregir y extender cualquier parte del proyecto. Las frecuentes
pruebas de regresión garantizan que los posibles errores serán detectados.
Simplicidad en el código: es la mejor manera de que las cosas funcionen. Cuando
todo funcione se podrá añadir funcionalidad si es necesario. La programación extrema
apuesta que es más sencillo hacer algo simple y tener un poco de trabajo extra para
cambiarlo si se requiere, que realizar algo complicado y quizás nunca utilizarlo.
La causa de su enfoque centrado en simplicidad y comunicación es que ambas son
extraordinariamente complementarias. Con más comunicación resulta más fácil identificar
qué se debe y qué no se debe hacer. Cuanto más simple es el sistema, menos tendrá que
comunicar sobre éste, lo que lleva a una comunicación más completa, especialmente si se
puede reducir el equipo de programadores.
2.4.3. Aplicación
La programación extrema se aplicó durante la realización del proyecto mediante los
siguientes elementos:
Planificaciones semanales: cada semana se preparaba el trabajo de la semana si-
guiente (cada tarea a realizar tenı́a asociado un número de horas previstas).
Reuniones semanales: el alumno presentaba a su director como mı́nimo una vez a
la semana el trabajo realizado para discutir ambos el rumbo a tomar a continuación,
qué aspectos mejorar o corregir, las decisiones de diseño o implementación, etc. En
algunas ocasiones se pidió la opinión o consejo a otros miembros de la empresa, bien
como usuarios de la aplicación o como desarrolladores con experiencia en la realización
de aplicaciones web.
Anotación de horas trabajadas: se anotaban cada dı́a las horas trabajadas en las
distintas tareas planificadas, empleando para ello la versión existente de la aplicación
PhpReport. Cada entrada con las horas trabajadas incluı́a la hora de inicio, la de fin,
el tipo de tarea realizada (implementación, diseño, documentación...) y una breve
descripción. De este modo se disponı́a de una referencia con información inmediata
sobre el trabajo realizado, permitiendo la consulta por parte de cualquier implicado
en el proyecto y el seguimiento de la planificación semanal.
Seguimiento de la evolución del proyecto: realizado mediante la utilidad tWiki
[54] con la extensión XPTracker [55], para realizar el seguimiento del proyecto con las
caracterı́sticas del ciclo XP. En esta utilidad se anotaron las horas trabajadas (desde un
punto de vista general y no estrictatemente diario), las decisiones tomadas en cuanto
a diseño o implementación, aspectos complejos y/o interesantes de la aplicación para
otros programadores (e.g. explicación del funcionamiento de fragmentos de código
poco intuitivos) y los principales problemas encontrados (aquéllos que supusieron un
retraso respecto a lo inicialmente previsto). Todos estos datos sobre su planificación,
diseño e implementación lo convierten en una fuente de información esencial sobre el
proyecto, tanto para el propio alumno y el director como para otros programadores
que decidan emplear, modificar o estudiar el código realizado.
Capı́tulo 3
Desde que el ordenador comenzó a irrumpir en los entornos de trabajo como una plata-
forma de propósito múltiple, dejando atrás sus años de herramienta para tareas especı́ficas,
los usuarios han intentado sacarle todo el provecho. De esta manera se han ido delegando en
él aspectos laborales de los que antes se ocupaban otros utensilios o personas. Si hoy parece
que la telefonı́a sobre IP acabará desterrando en más de una empresa a la telefonı́a tradi-
cional [56], la agenda con las horas trabajadas y la máquina de fichar ya fueron derrotadas
hace bastantes años por las aplicaciones de seguimiento y monitorización de actividades.
A principios de los 90 la popularización de los entornos de ventanas propició que las
empresas comenzaran a emplear de manera más generalizada los ordenadores como herra-
mienta central [57]. En aquella época se pudieron ver los primeros intentos de anotación
del trabajo realizado, que consistı́an en una simple agenda con un campo de texto por dı́a,
un simple émulo de la agenda tradicional [58]. Poco a poco se le comenzaron a añadir
campos adicionales que hacı́an más sencillo extraer información de ella, los cuales ahora ya
nos parecen totalmente esenciales en cualquier herramienta de este tipo, como el proyecto
al que pertenece la tarea o las horas de inicio y fin [59]. Prácticamente la totalidad de
estas herramientas eran de software privativo (GNU is Not Unix (GNU)/Linux aún no habı́a
alcanzado su etapa de popularidad [60]), y además funcionaban únicamente en local, por
lo que su función era únicamente para anotación personal del trabajo realizado, y si se
requerı́a sincronizarlo con otra fuente se debı́a hacer manualmente [58].
En los años 96 y 97 el comienzo de la era de internet significó un empuje crucial para
estas herramientas [61] [62]. Este mismo hecho supuso también el arranque definitivo del
software libre en casi todas las áreas [63], incluido el seguimiento de tareas, por lo que
a partir de este momento sı́ podemos hacer una distinción lógica entre las aplicaciones
privativas y las libres.
25
3.1. Evolución de las aplicaciones privativas 26
Exportación/importación de datos
Las aplicaciones seguı́an funcionando a nivel local, de manera que cada usuario las
seguı́a empleando del mismo modo que antes. La diferencia es que las aplicaciones incluı́an
una nueva funcionalidad: importación y exportación de datos. Esto les permitı́a guardar
la información en un formato especı́fico (normalmente con una sintaxis propia) para que
posteriormente pudiera ser parseado por la misma herramienta y recuperar los datos. Los
formatos más empleados hasta dı́a de hoy con este propósito han sido los lenguajes de
marcado, como XML, HTML y JSON, y las hojas de cálculo, principalmente Excel [64]
[59].
Gracias a esta opción existı́a la posibilidad de transferir datos locales de una máquina
a otra para mantener una central con todos ellos. La dinámica habitual era realizar regu-
larmente (una vez al dı́a la mayorı́a de las veces) una exportación de datos desde cada
máquina local, enviar los datos a la máquina central e importarlos en esta última. Una posi-
ble variante serı́a mantener todas las copias actualizadas con todos los datos, pero rara vez
se ha empleado este modelo. En cualquier caso, este proceso acababa siendo automatizado
mediante un script debido a lo mecánico que resulta, para que de ese modo fuera todavı́a
más transparente para los usuarios finales.
El principal problema de este enfoque es que los datos se encuentran desactualizados
la mayor parte del tiempo, hasta que se exportan los nuevos a la máquina central. Tam-
bién puede haber problemas con la modificación de datos anteriores si se ha optado por
exportaciones incrementales.
Almacenamiento centralizado
El enfoque de sincronización mediante exportación de datos presentaba el problema de
contener datos desactualizados la mayor parte del tiempo, y además el propio proceso de
exportar e importar resultaba molesto al suponer una carga de trabajo adicional. Esto llevó a
que de manera natural se pasara directamente a almacenar los datos de manera remota en
esa máquina central que los contenı́a todos, para de ese modo eliminar los dos problemas
mencionados [65].
Este enfoque produjo otros cambios relacionados con la gestión de intranets en em-
presas al basarse claramente en este enfoque. En primer lugar era evidente que además de
la instalación en local se necesitaba tener configurada correctamente la máquina remota
destinada a almacenar la información, ası́ como una conexión estable hasta ella desde to-
dos los hosts en los que los usuarios almacenarı́an información, y posteriormente se debı́a
3.1. Evolución de las aplicaciones privativas 27
nes para generar sus informes, también son incluidas en muchos casos para su uso directo
por parte del usuario, permitiéndole extraer la información de una manera más directa. Su
funcionamiento y sintaxis (en base simplemente a campos o no) se suele asemejar mucho
al de una interfaz gráfica simplificada para bases de datos, mostrando posteriormente las
filas extraı́das en una o varias tablas.
Este apartado ha aumentado mucho de importancia en los últimos años debido a la
mayor necesidad de informes que permitan seguir las lógicas de negocio cada vez más
complejas de las empresas. Esto provoca que la minerı́a de datos pueda ser determinante a
la hora de decantarse por una herramienta u otra en entornos empresariales mı́nimamente
grandes.
3.1.4. Temporizador
Un problema que presentaban las aplicaciones de anotación de trabajo es que en muchas
ocasiones ni el propio usuario recordaba cuánto tiempo llevaba trabajando. Con el objetivo
de eliminar este problema muchas aplicaciones incluyeron un ((widget)) muy sencillo consis-
tente en un cronómetro que al pulsar un botón comenzará a contar el tiempo transcurrido,
permitiéndonos llevar cuenta de la duración de la actividad [59] [69]. Normalmente permi-
ten la introducción al comienzo de un nombre para la tarea, y muchas veces incluyen otros
campos (e.g. descripción o proyecto), e incluso el envı́o automático de su información al
almacenamiento central al detener el contador. Con el tiempo han incorporado pequeñas
mejoras, como la detección de los tiempos de inactividad, que las han hecho muy populares,
llegando incluso a ser una única interfaz minimalista en algunas aplicaciones [70].
3.1. Evolución de las aplicaciones privativas 29
de popularizarse, realizar marketing y captar nuevos clientes mediante la cata del producto.
Las limitaciones de la versión de prueba suelen variar según el tipo de programa que sea. Si
se trata de uno local, habitualmente la versión de prueba tiene un lı́mite de tiempo tras el
cual el usuario debe registrar su copia y pagar por una licencia a la empresa desarrolladora.
En las aplicaciones centralizadas es más común que limiten el número de entidades a
manejar (usuarios, proyectos, etc.), las capacidades de extracción de información o los
campos activos en los formularios, y de nuevo el usuario deberá pagar por una licencia
si requiere mayores capacidades. En las aplicaciones más completas suele haber diversas
’suites’con diferentes precios según el máximo de entidades a manejar y de funcionalidades
requeridas [80] [81] [82].
Planificación de trabajo
33
4.2. Análisis y diseño 34
No sólo se pretende añadir una dimensión nueva a la aplicación, sino conectarla con la
que ya existı́a previamente. Es decir, se permitirá vincular la anotación de actividades con la
planificación mediante una relación entre las tareas anotadas y las actividades planificadas.
Ası́ el usuario eligirá la actividad del proyecto ya planificada a la que pertenece la tarea
a anotar, y se almacenará como parte de ese proyecto. Este mecanismo permitirá que la
evolución del proyecto sea registrada conjuntamente y de manera natural junto con la
anotación del trabajo, requiriendo un esfuerzo adicional mı́nimo por parte del usuario.
Cada tarea dispone de una página con campos de texto por defecto (razones del
retraso, aspectos importantes de la implementación, caracterı́sticas pendientes, etc)
en la que sus usuarios escribirán la información que estimen conveniente.
A fin de facilitar la transición a la nueva aplicación por parte de los usuarios, además
de por la eficacia que ha tenido en la empresa hasta el momento, se decidió mantener el
modelo empleado en tWiki en la mayor medida posible. Pero, además de la planificación
a corto plazo, en ciertos proyectos de la empresa se empleaba también un segundo tWiki
para llevar un control a largo plazo de modo más general y clásico, demostrando ser un
complemento importante en proyectos de entidad importante, especialmente en aquéllos a
fecha de fin.
Este segundo tWiki empleaba el mismo plugin que el de corto plazo, por lo cual se
decidió que el nivel correspondiente a las iteraciones se mapearı́a al apartado global del pro-
yecto (e.g. análisis, diseño, implementación) y las tareas y subtareas ahora serı́an secciones
más pequeñas de cada apartado. En el texto de la tarea se anotaban únicamente decisiones
tomadas y aspectos clave en lugar del desarrollo del trabajo diario realizado por el usuario.
Por este motivo se decidió añadir la planificación a los dos niveles: planificación semanal
(la habitual en XP) y planificación clásica a largo plazo.
Iteration
Agrupa trabajo de un proyecto concreto en un perı́odo determinado. Almacena la si-
guiente información:
Story
Recoge información sobre un apartado a llevar a cabo en una iteración especı́fica. Con-
tiene los siguientes datos:
Aceptación: flag que rellenará el supervisor para indicar que la story ha cumplido los
requisitos previstos.
TaskStory
Describe un trabajo concreto dentro de una story. Se componen de los siguientes cam-
pos.
Fecha de fin estimado: momento en el que se prevé que termine el trabajo del perı́odo.
Pueden estar relacionadas con tareas introducidas por el usuario (de esta manera las
horas trabajadas se recogen automáticamente de la anotación del trabajo).
Module
Contiene una etapa de trabajo global en un proyecto (e.g. diseño, implementación),
almacenando los siguientes datos:
Fecha de inicio: el momento en el que empieza el trabajo del perı́odo.
Fecha de fin: el momento en el que termina el trabajo del perı́odo.
Nombre: nombre descriptivo para su identificación.
Resumen: texto como resumen del trabajo contenido.
Y se relaciona con otras entidades del siguiente modo:
Uno o más modules pertenecen a un proyecto.
Section
Recoge información sobre un apartado a llevar a cabo en un module especı́fico. Contiene
los siguientes datos:
Nombre: nombre descriptivo para su identificación.
Resumen: texto como resumen del trabajo contenido.
Posee las siguientes relaciones:
Una o más sections pertenecen a un module.
Pueden tener a un usuario como supervisor.
TaskSection
Describe una tarea más concreta dentro de una section. Se componen de los siguientes
campos.
Nombre: nombre descriptivo para su identificación.
Riesgo: dificultad o peligro potencial que entraña el trabajo del perı́odo.
Horas estimadas: duración estimada del trabajo del perı́odo.
Presenta estas relaciones:
Una o más taskSections pertenecen a una section.
Pueden tener a un usuario como trabajador asignado.
Pueden estar relacionadas con una o más taskStories (para vincular la planificación
a corto y largo plazo2 ; ver 4.2.1 en la página anterior).
2
un ejemplo sencillo serı́a una taskSection que recoge parte de la planificación global de implemen-
tación de una aplicación con la cual se relaciona una taskStory con la implementación de un fragmento
de código concreto por parte de una persona, o con cualquier otra tarea que surge durante el proceso
de codificación.
4.2. Análisis y diseño 38
3
el diagrama ha sido simplificado para una mejor lectura, pero si se desea la versión completa, se
puede consultar en el anexo A.1 en la página 105
4.3. Implementación 39
4.3. Implementación
Tal y como ya se comentó y justificó en el apartado 2.3.2 en la página 7, la capa modelo
fue realizada completamente en PHP, con la excepción, claro está, de las nuevas tablas de
la base de datos. La capa se construyó en base al extendido modelo VO-DAO-Fachadas.
Aunque posteriormente se detallará cada apartado en PhpReport, podemos describir el
funcionamiento general del modelo del siguiente modo:
1. Los Value Object (VO) son objetos encargados de almacenar los datos provenientes
de base de datos. Habitualmente se construye uno por tabla (entidad), aunque en
ocasiones se pueden necesitar objetos para guardar datos adicionales a las entidades
o calculados. En dicho caso se les denomina Custom Object (CO). Suelen contener
únicamente métodos get y set para sus atributos, que mapean a los de la entidad
de base de datos. Cuando dichos atributos son claves foráneas se presentan diversos
enfoques: almacenar las claves, almacenar los VO correspondientes o no recuperarlo
con el propio objeto (se recuperarán más adelante si son necesarios).
2. Las operaciones individuales contra la base de datos son realizadas por los Data Ac-
cess Object (DAO). Lo más habitual es que cada DAO se encargue únicamente de
una tabla, con la excepción de las relaciones. En este último caso se suele preparar
para que a partir de un extremo de la relación se puedan obtener los elementos
asociados en el otro mediante un método, tanto en relaciones 1-1 como 1-N o N-N.
En todos los demás casos realizará operaciones sobre su propia tabla empleando el VO
correspondiente como almacén de datos (al trabajar con relaciones puede emplear los
VO correspondientes a las otras entidades o simplemente trabajar con su identificador
y delegar su posterior obtención).
3. Por último tenemos las fachadas, que se encargan de añadir una capa adicional para
reunir en un método todas las operaciones de DAO que requiere un caso de uso.
Pueden realizar varias llamadas sobre los DAO, llamadas condicionales, rellenar obje-
tos CO con atributos derivados u obtenidos de otras tablas, etc. Constituyen la parte
superior de la capa modelo que permite la comunicación con la capa web.
Siendo ésa la estructura habitual del modelo, PhpReport ha incluido en su nueva ver-
sión un nivel más de abstracción: las acciones. Dichos objetos, que veremos con más detalle
en su propio apartado (el 4.3.4 en la página 43), se encuentran entre las fachadas y los
DAO, encargándose ahora de la comunicación con estos últimos. Existe una acción por
cada método de las fachadas, y contienen el código que habitualmente tendrı́a dicho méto-
do, de manera que la fachada delega en él por completo. El objetivo de este enfoque es
proporcionar soporte para plugins individuales en cada función, de manera que la acción
buscará los plugins que le corresponden y los ejecutará cuando sea preciso (pueden existir
plugins pre-acción o post-acción). En la figura 4.2 en la página siguiente podemos observar
el comportamiento habitual de una acción junto con plugins.
Antes de entrar con más detalle en la implementación destacaremos que todo el código
en PHP correspondiente a esta etapa fue documentado con phpDocumentor (véase apar-
tado 2.3.3 en la página 20), el cual requerı́a introducir unos comentarios con una sintaxis
especı́fica antes de cada elemento que querı́amos documentar (archivo, objeto, función,
4.3. Implementación 40
Figura 4.2: diagrama UML de secuencia del funcionamiento normal de una acción y sus plugins
4.3. Implementación 41
atributo, etc.). No entraremos en detalle en la sintaxis, bastante sencilla [87], pero sı́ se
mantendrán los comentarios en todos los fragmentos de código incluidos, sirviendo como
ejemplos ilustrativos de su empleo.
Ahora se verán a fondo las diferentes etapas de la implementación.
los objetos relacionados con él (delegando en el DAO del otro extremo), además de las
operaciones especı́ficas requeridas por cada uno.
Para cada DAO se creó una clase padre abstracta a fin de separar la implementación
para PostgreSQL de la capa superior, de manera que en caso de que fuera necesario se
pudieran crear DAOs para otros tipos de BD sin ningún problema. Para poder obtener la
implementación concreta de los DAO se dispone del objeto DAOFactory, el cual, siguiendo
el patrón ((factory)), nos devuelve la instancia correcta del tipo de DAO pedido (un método
por cada uno), tomando para ello el parámetro de configuración de PhpReport que nos
indica el tipo de BD empleada.
El diagrama6 4.4 en la página siguiente nos muestra todos los objetos creados relativos
al nivel DAO.
Al igual que en el apartado anterior, la relación entre Task y TaskStory implicó pequeños
cambios en el DAO correspondiente a Task. Concretamente se preparó para que recuperara y
rellenara el atributo nuevo de TaskVO, y también se añadieron los métodos correspondientes
a la relación, para recuperar el objeto relacionado.
Por último destacaremos el uso de los errores especı́ficos ya definidos previamente en
PhpReport para los siguientes casos:
Figura 4.5: diagrama UML de los métodos nuevos en las fachadas para la planificación
4.4. Pruebas y resultados obtenidos 46
Figura 4.6: diagrama UML de secuencia del proceso completo de creación de una Task Story
4.4. Pruebas y resultados obtenidos 48
Se añadieron los nuevos tests a la suite ya existente en PhpReport que aglutina todos
los relativos a los VOs.
Creación de los métodos de extracción de datos (lo más genéricos y potentes posibles).
49
5.2. Análisis y diseño 50
almacena PhpReport, como por ejemplo saber las horas de vacaciones pendientes de los
empleados, calculadas a partir de la duración de su jornada y las horas trabajadas ese año.
Todo el proceso de extracción y cruce de datos se basará en las relaciones existentes
entre las entidades de la base de datos. Dichas capacidades de extracción de información
serán lo más genéricas posibles, con el objetivo de que realizar nuevos cruces de datos
requiera simplemente llamar a los mismos métodos con otros parámetros o realizar un
número diferente de llamadas, pero siempre evitando en la medida de lo posible la creación
de nuevas funciones a nivel de DAO.
Ya que los informes requeridos son siempre sobre las tareas, todos giran en torno a
la entidad Task, por lo que será su DAO el que realice el grueso del trabajo.
De manera genérica existen dos tipos de informes: aquéllos que recuperan datos
relacionados con un elemento (e.g. las horas trabajadas por cada uno de los usuarios
en un proyecto concreto, es decir, los datos de un proyecto agrupados en base a los
usuarios) y los que trabajan con todos los datos almacenados (e.g. horas trabajadas
por cada uno de los usuarios para cada cliente, es decir, todos los datos agrupados
en base a combinaciones de usuario y cliente).
También se creó una función en el DAO de Task que nos permite obtener las horas
de vacaciones empleadas por los usuarios entre dos fechas, un dato que nos permi-
tirá obtener posteriormente el número de horas de vacaciones que les restan.
Existen dos datos especialmente importantes para los usuarios y con una lógica más
compleja que implica varias entidades:
• Horas extra trabajadas (tanto hasta el momento actual como a una fecha con-
creta).
5.3. Implementación 51
Una vez obtenidas estas conclusiones se decidió que se dotarı́a al DAO de Task de
capacidades de extracción de datos, tanto relacionados con un elemento concreto (pro-
yecto, cliente, usuarios, etc.) como de manera general, agrupándolos en diversos niveles y
permitiendo el filtrado por fechas de inicio y/o fin.
En cuanto al cálculo de horas extra, se optó por integrar su lógica a nivel de una acción
independiente, por ser especialmente compleja, propensa a modificaciones en el futuro e
implicar un importante número de entidades (User, Task, Journey History, City History,
City...). En el caso del cálculo de vacaciones pendientes, se creó un método en el DAO de
Task que nos permitiera recuperar las horas de las tareas asociadas al proyecto simbólico
para las vacaciones1 , delegando el resto de la lógica en otra acción independiente. En ambos
casos se permitirı́a tanto la obtención de los datos para un único usuario como un informe
general para todos, además del filtrado por fechas de inicio y/o fin. La extracción de los
datos bien para un único usuario o para todos como informe general fue otra caracterı́stica
que se optó por añadir. Las acciones obtendrı́an los datos base mediante operaciones de los
diferentes DAOs, incluyendo en el caso del de Task la operación de extracción avanzada de
datos añadida en el paso anterior.
Ya antes de comenzar a implementar se decidió que la etapa de pruebas de este apartado
serı́a especialmente importante debido a los problemas habituales que se habı́an presentado
en el cálculo de las horas extra y de las vacaciones pendientes en ocasiones anteriores. Para
ello se contrastarı́an los datos con los obtenidos mediante el código de la versión anterior
de PhpReport.
5.3. Implementación
Como se comentó la sección anterior, la base del código destinado a las labores generales
de data-mining se encontrarı́a en el DAO de Task, mientras que aquellos informes que
requiriesen lógica más compleja tendrı́an dicho código añadido en una acción especı́fica.
Además se creó un método para obtener las horas de vacaciones utilizadas por cada usuario.
Debido a la especial importancia de estos métodos, hablaremos de su implementación con
más detalle a continuación.
sin filtrados especı́ficos. También se creó un método más sencillo para obtener las horas de
vacaciones utilizadas por cada usuario.
La fecha de inicio del intervalo requerido (en caso de no pasarse o ser nula, no se
establece lı́mite inferior alguno para la fecha de la tarea).
La fecha de fin del intervalo requerido (en caso de no pasarse o ser nula, se toman
los datos hasta la fecha actual).
Atributo opcional para el primer nivel de agrupamiento (actualmente acepta los strings
USER, PROJECT, CUSTOMER, TTYPE y STORY, definidos en un enumerado en la clase
abstracta padre del DAO).
Mediante estos cinco atributos, cuyos valores válidos son fácilmente expandibles, se pue-
den extraer múltiples conjuntos de datos para la generación, tanto directa como indirecta,
de casi cualquier informe potencial sobre un elemento concreto requerido en la empresa.
El siguiente ejemplo ayudará a entender mejor el funcionamiento y utilidad del método:
se quiere saber cuántas horas ha trabajado cada empleado en cada uno de los proyectos del
cliente ((Wealthy Client)) durante el año 2009. Para ello se invocará el método pasándole
como parámetros el objeto CustomerVO de ((Wealthy Client)), las fechas de inicio y fin de
2009, y los strings PROJECT y USER. Con estos parámetros el método ejecutará internamen-
te la siguiente sentencia SQL:
la cual nos devolverá las horas trabajadas por cada usuario en cada proyecto (campos
add hours, userid y projectid respectivamente).
Informes generales
En el caso de querer informes generales sin filtrar por ningún elemento se usa la función
GetGlobalTaskReport del DAO de Task, la cual acepta los siguientes parámetros:
5.3. Implementación 53
La fecha de inicio del intervalo requerido (en caso de no pasarse o ser nula, no se
establece lı́mite inferior alguno para la fecha de la tarea).
La fecha de fin del intervalo requerido (en caso de no pasarse o ser nula, se toman
los datos hasta la fecha actual).
Atributo para el primer nivel de agrupamiento (actualmente acepta los strings USER,
PROJECT, CUSTOMER, TTYPE y STORY, definidos en un enumerado en la clase abstracta
padre del DAO).
Las diferentes combinaciones posibles de los cinco atributos, de nuevo fácilmente ex-
pandibles, nos permiten extraer un gran número de informes generales de gran utilidad para
la empresa, tanto directa como indirectamente.
Ahora presentaremos otro ejemplo para ilustrar el uso del método: se quiere saber
cuántas horas ha trabajado cada usuario para cada proyecto en cada tipo de tarea durante
el año 2009. Para ello se invocará el método pasándole como parámetros las fechas de
inicio y fin de 2009, y los strings USER, PROJECT y TTYPE. Con estos parámetros el método
ejecutará internamente la siguiente sentencia SQL:
la cual nos devolverá las horas trabajadas por cada usuario en cada proyecto por cada tipo
de tarea (campos add hours, usrid, projectid y ttype respectivamente).
En la figura 5.1 en la página siguiente incluimos un diagrama de secuencia con todo los
pasos por los que atraviesa la obtención de un informe de trabajo User-Story, para poder
ver en funcionamiento toda la capa descrita hasta ahora, y la figura 5.2 en la página 55
nos muestra un ejemplo del posible resultado obtenido con dicho informe.
El usuario del cual queremos saber las vacaciones utilizadas (objeto UserVO).
La fecha de inicio del intervalo requerido (en caso de no pasarse o ser nula, no se
establece lı́mite inferior alguno para la fecha de la tarea).
5.3. Implementación 54
Figura 5.1: diagrama UML de secuencia del proceso completo de obtención de un informe
User-Story
5.3. Implementación 55
La fecha de fin del intervalo requerido (en caso de no pasarse o ser nula, se toman
los datos hasta la fecha actual).
Antes de mostrar el seudocódigo de este cálculo2 haremos una breve descripción del
modo de obtener las horas extra en base a otras categorı́as de horas calculadas:
Horas extra: se obtienen de restar a las horas trabajadas las horas trabajables del
mismo intervalo.
Horas trabajadas: como su propio nombre indica, las horas anotadas por un trabajador
en tareas que no fuesen del proyecto vacaciones.
Horas trabajables: son las horas que le corresponden a un trabajador en un intervalo.
Se calculan a partir de su histórico de jornada, teniendo en cuenta los diferentes
festivos existentes (que a su vez dependen del histórico de ciudad).
El cálculo de las horas trabajables representa la parte más compleja de toda la acción, ya
que implica el cruce de diversos históricos (de ciudad y de jornada) y su posterior aplicación
al calendario laboral de las diferentes ciudades. En cambio la obtención de las horas traba-
jadas fue prácticamente directa de la BD mediante el DAO de Task. Podemos comprobarlo
en el seudocódigo incluido en la sección de código 5.1 en la página siguiente.
2
el apartado B.2 en la página 116 contiene el código correspondiente a la lógica de negocio de la
acción por si se quiere consultar.
5.3. Implementación 57
Los datos se devuelven de nuevo en un array relacional que incluye para cada usuario,
referenciado por su login, los tres tipos de horas mencionadas anteriormente, relativas al
intervalo pasado a la acción, y además el número total de horas extra acumuladas por el
usuario hasta el dı́a actual. También se incluirá un conjunto adicional con los datos totales
de todos los usuarios en caso de tratarse del informe general.
En la figura 5.3 en la página siguiente podemos observar un posible resultado del infor-
me de horas extra y vacaciones pendientes a modo de ejemplo.
El usuario del cual queremos saber las vacaciones pendientes (objeto UserVO), o
un valor nulo si nos interesa el informe con las vacaciones pendientes de todos los
3
aunque se permite el cálculo con intervalos concretos, y en ciertas ocasiones puede ser útil, para
conocer el número real de horas de vacaciones pendientes se debe seleccionar el comienzo del año actual
como inicio del intervalo, ya que es el momento en que habitualmente se reiniciará el número de festivos
disponibles.
5.3. Implementación 58
Figura 5.3: ejemplo del informe de horas extra y vacaciones pendientes de los usuarios
5.4. Pruebas y resultados obtenidos 59
usuarios almacenados.
Pruebas de DAOs
Los nuevos métodos del DAO de Task cuentan con sus propios tests de unidad dentro
de la clase PostgreSQLTaskDAOBasicTests. El método getTaskReport cuenta con un
conjunto de pruebas de unidad que testean varias combinaciones diferentes de parámetros
(la clase de objeto sobre la que se generan pruebas y la inclusión o no de fechas y agru-
pamiento), mientras que getVacations y getGlobalTaskReport tienen cada uno una
prueba que las testea. En todas las pruebas se procedió a crear en BD los mı́nimos obje-
tos necesarios para la extracción del informe, y posteriormente se realizó dentro del propio
test de unidad el cálculo de las horas acumuladas, números que después son comparados
con los devueltos por el método del DAO. Los resultados obtenidos fueron simplemente la
confirmación de que los métodos funcionaban siempre del modo previsto.
Pruebas de acciones
El cálculo de las horas extra fue en la versión anterior de PhpReport fuente de varios
errores de programación, en ocasiones exclusivos de la codificación y en otros de casos
especiales no detectados en la propia lógica de negocio. Por ello se optó por crear tests
unitarios para la comprobación de la acción correspondiente. Para lograrlo se necesitaba
un código adicional que calculara las horas extra a fin de comparar ambos resultados, y se
optó por coger el empleado en la versión anterior de PhpReport y guardarlo por separado
en un archivo nuevo.
Dicho código necesitaba una base de datos con la estructura antigua, ası́ que se creó otra
base de datos de pruebas con dicho esquema, rellenándola con un dump de la BD real. A
fin de contener los mismos datos, la base de datos de prueba de la versión actual tendrı́a
el mismo contenido migrado al esquema nuevo.
4
en el anexo B.3 en la página 119 se puede ver el código correspondiente a la lógica de negocio de
la acción.
5.4. Pruebas y resultados obtenidos 60
5
las compensaciones de horas extra eran entidades abstractas empleadas para compensar a un usua-
rio las horas extra realizadas hasta una fecha concreta, de un modo similar a pagarle lo realizado y
poner a cero su número.
Capı́tulo 6
Creación de las interfaces dinámicas para PhpReport (aunque no todas las páginas,
por su propia naturaleza, dispongan de elementos realmente dinámicos).
61
6.2. Análisis y diseño 62
• Task. • Project.
• User.
• Sector.
• User Group.
• Area. • Customer.
• Entradas de los históricos (coste por hora, ciudad, jornada y área) de los usuarios.
• Todos los componentes de ambos tipos de planificación (vistos en el aparta-
do 4.2 en la página 34).
• Horas extra.
• Vacaciones pendientes.
• Horas trabajadas de un usuario por proyecto y cliente.
• Horas trabajadas por usuario y Story.
Una vez que se tuvieran estas funcionalidades la aplicación estarı́a en disposición de ser
empleada para gestionar las tareas realizadas, con visos a ser ampliada en el futuro, sobre
todo en lo referente a añadir nuevas interfaces y nuevas acciones que presenten otros tipos
de informes o datos derivados.
User : interfaces CRUD de User, su relación con User Group y de todos los históricos,
además de la extracción de informes sobre usuarios, información de horas extra y de
vacaciones pendientes.
Project: interfaces CRUD de Project y sus relaciones con Area, Customer y User,
además de la extracción de informes sobre proyectos.
Además de las interfaces propias de la lógica de negocio se creará una página sencilla
de login para poder autenticarse en la aplicación.
El diseño especı́fico de cada interfaz será comentado en el siguiente apartado sobre
implementación, ya que al emplear el framework ExtJS (apartado 2.3.2 en la página 12)
las interfaces se crearı́an en base a sus widgets. Dichos ((widgets)) poseen un gran número
de opciones de configuración y combinación, por lo que en bastantes ocasiones se cambió el
enfoque de la interfaz durante su implementación al contemplar un nuevo diseño más
cómodo y/o completo (incluso se descubrieron nuevos ((widgets)) de ExtJS, bien porque
fueron introducidos en las versiones más recientes [91] o porque se incluyen como ejemplos
en el código de ExtJS pero no se encuentran documentados en el API oficial).
6.3. Implementación
La implementación de las interfaces se realizó en JavaScript empleando el framework
ExtJS (apartado 2.3.2 en la página 12), el cual nos provee de una serie de widgets, muchos
de los cuales tienen caracterı́sticas AJAX, para combinar a la hora de crear la interfaz web.
6.3. Implementación 64
Aunque las interfaces estén basadas casi totalmente en ese JavaScript, sus ficheros son
realmente PHP, ya que incluyen una pequeña parte de código PHP que es ejecutado pre-
viamente en el lado del servidor. El código JavaScript está presente gracias a las facilidades
de PHP para combinar código del lado del servidor con el código despachado que se ejecuta
en el lado del cliente.
Además de las propias interfaces fue necesario crear servicios web. Éstos son fragmentos
de código en PHP a los cuales se realizan peticiones GET (en ocasiones pasándoles un XML
por su entrada estándar) desde las interfaces con el objetivo de que las interfaces dinámicas
realicen las operaciones CRUD requeridas. De este modo, por ejemplo una tabla puede
llamar a un servicio web pasándole los parámetros de un formulario por la url (petición
GET ), y éste realizará la operación requerida y responderá con un código XML (u otro
lenguaje de marcado) que la tabla parseará internamente para después presentar los datos
de la forma adecuada. Los servicios web requieren que el usuario esté logueado y cuente
con permisos para su uso a través del fichero de configuración.
Ya que la creación de los servicios web estuvo ı́ntimamente ligada a las necesidades que
iban surgiendo en las interfaces, serán nombrados con cada interfaz según éstas se vayan
detallando.
Todas las tablas incluidas en las interfaces emplean dicho ((widget)) de ExtJS, el cual
proporciona capacidades para ocultar columnas de la tabla y ordenar por cualquiera de
ellas en orden creciente o decreciente. Además, dicha configuración se guarda en cookies,
por lo que el usuario podrá seguir viendo la tabla con el mismo navegador tal y como la
configuró la última vez.
Algunas interfaces presentan tablas de estructura dinámica, es decir, que no siempre
presentan las mismas columnas (las más comunes son las tablas que presentan informes).
En estos casos se han aprovechado las capacidades del framework para crear dichas tablas
en base a una estructura pasada por un servicio web en un JSON1 , siendo éstos los únicos
casos en que no se emplea XML.
Antes de detallar cada interfaz señalaremos que todas incluyen cuatro ficheros PHP:
header.php: contiene las cabeceras HTTP, entre las cuales se incluyen las importa-
ciones de código JavaScript y hojas de estilo CSS necesarias.
sidebar.php: añade la barra lateral que contiene los botones para acceder a las
distintas interfaces de PhpReport.
footer.php: los tags finales de HTTP (la autorı́a y los tags que cierran aquellos
abiertos en header.php).
1
ExtJS tiene previsto dar soporte próximamente para manejar tablas dinámicas con XML, por lo
que si se considerará apropiado se podrı́a unificar el formato de intercambio de datos.
6.3. Implementación 65
Customer : sus posibles valores son recuperados mediante el servicio web getUserCus-
tomersService, y presenta capacidades ((type-ahead)) (filtra las entradas del combobox
en base a lo escrito por el usuario, pudiendo completar automáticamente el texto in-
troducido). No permite valores no devueltos por el servicio.
Project: sus posibles valores son recuperados mediante el servicio web getCustomer-
ProjectsService en base a la entrada del campo de cliente, y presenta capacidades
((type-ahead)). No permite valores no devueltos por el servicio.
Task type: sus posibles valores están incrustados en el código de la interfaz, y presenta
capacidades ((type-ahead)). No permite valores no devueltos por el servicio.
Task Story : sus posibles valores son recuperados mediante el servicio web getOpen-
TaskStoriesService en base a la entrada del campo de proyecto, y presenta capacidades
((type-ahead)). No permite valores no devueltos por el servicio.
Figura 6.2: interfaz web de PhpReport para las operaciones CRUD sobre las tareas
6.3. Implementación 67
Además presentan un pequeño botón en la parte superior derecha que permite colapsar
el panel para facilitar la ocultación de las tareas que no nos interesan.
Debajo de todos los paneles se hallan un botón, New Task, que añade un panel nuevo
para anotar una tarea adicional, y el botón Save que nos permite almacenar los cambios
realizados desde la última vez que salvamos. Para ello se emplean tres servicios web: create-
TasksService, updateTasksService y deleteTasksService. Las tareas se obtienen inicialmente
gracias a otro servicio web, getUserTasksService.
En la figura 6.3 en la página siguiente incluimos un diagrama de secuencia con todo los
pasos por los que atraviesa el proceso de salvado de las tareas de un usuario, para poder
ver comprender mejor el uso de los web services CRUD.
Aparte de los elementos centrales de la página se incluyen cuatro ((widgets)) adicionales
en la barra lateral, debajo del menú principal:
Calendario: en él se elige el dı́a del cual se quiere gestionar la anotación de tareas.
Clonación de dı́as: nos permite elegir otro dı́a del calendario para copiar de él todas
las tareas e incluirlas en el actual.
Resumen de trabajo: indica el número de horas trabajadas por el usuario el dı́a selec-
cionado, su semana y su mes, obteniéndolas mediante el servicio getPersonnalSum-
maryByDateService.
getOpenTaskStoriesService: devuelve las Task Stories activas (sin fecha de fin) ac-
tualmente para un proyecto y asignadas al usuario actualmente logueado.
Figura 6.3: diagrama UML de secuencia del proceso completo de salvado de las tareas de un
usuario
6.3. Implementación 69
Página personal
Es la interfaz en la cual un usuario puede consultar fácilmente datos sobre su cuenta
(login y grupos de usuario) y una tabla con un informe con las horas trabajadas por proyecto
y cliente entre dos fechas (imagen 6.4 en la página siguiente). Para introducir dichas fechas
se dispone de un pequeño formulario con campos para ambas (intervalo cerrado-cerrado).
La interfaz emplea los siguientes servicios web:
getUserProjectCustomerReportJsonService: devuelve un informe con las horas de tra-
bajo de un usuario para cada proyecto y cliente entre dos fechas.
Evaluación de usuarios
Es la interfaz en la cual se puede obtener en una tabla el informe de horas trabajadas por
usuario y Story entre dos fechas (imagen 6.5 en la página 71). Para introducir dichas fechas
se dispone de un pequeño formulario con campos para ambas (intervalo cerrado-cerrado).
La interfaz emplea los siguientes servicios web:
getUserStoryReportJsonService: devuelve un informe con las horas de trabajo por
cada usuario y Story entre dos fechas.
Gestión de usuarios
Es la interfaz CRUD para los usuarios y sus históricos (imagen 6.7 en la página 75).
En el panel superior se pueden crear, eliminar o editar usuarios y asignar o desasignar a
los grupos de usuarios configurados en el archivo de configuración2 . El panel superior es
2
se incluye una entrada listándolos debido a ciertos problemas que ya presentaba PhpReport al
recuperarlos del Lightweight Directory Access Protocol (LDAP), ya que se manejan distintos tipos de
grupos de usuarios que no pueden ser diferenciados más que por su nombre, y tampoco se pueden
eliminar o modificar debido a que otras aplicaciones dependen de ellos.
6.3. Implementación 70
Figura 6.6: interfaz web de PhpReport para la obtención del informe de horas extra y vacaciones
pendientes de los usuarios
6.3. Implementación 73
el encargado de la gestión de los propios usuarios, mientras que el inferior permite la ges-
tión de los históricos del usuario seleccionado en el primero (sólo carga los datos cuando el
panel se encuentra expandido). Ambas tablas permiten la edición en lı́nea de sus elementos.
Figura 6.7: interfaz web de PhpReport para la gestión de los usuarios y sus históricos
6.3. Implementación 76
Figura 6.8: interfaz web de PhpReport para la gestión de los clientes y sus sectores
6.3. Implementación 77
Detalles de proyecto
Es la interfaz que nos presenta los detalles de un proyecto, tanto sus atributos como
otros datos derivados e informes User-Story y User-Customer para el proyecto (ver ima-
gen 6.11 en la página siguiente). Existe un formulario con campos para las fechas de inicio
y fin lı́mites de los informes, aunque al cargar la página ya nos mostrará el informe con
todas las horas hasta la fecha actual.
Evaluación de proyectos
Esta interfaz presenta una tabla que nos muestra los datos económicos (facturación,
facturación por hora, etc.) y de trabajo (horas trabajadas, horas estimadas, desviación,
etc.) para todos los proyectos (figura 6.12 en la página 82). Incluye un botón en la parte
inferior que nos sirve para filtrar los proyectos y presentar sólo aquéllos actualmente activos.
Resumen de proyectos
Esta interfaz permite obtener los informes de horas de trabajo Project-User y Project-
Customer para todos los proyectos (imagen 6.13 en la página 83). Cada uno se presenta
en una pestaña diferente en el mismo panel.
Figura 6.11: interfaz web de PhpReport para ver detalles de los proyectos
6.3. Implementación 82
árbol, el cual nos muestra los elementos integrantes de la planificación respetando su je-
rarquı́a: Iteration, Story y Task Story (apartado 4.2.1 en la página 35). De sus datos se
muestran los habitualmente útiles, a quién se ha asignado, las fechas de inicio y fin y las
horas de trabajo estimadas, realizadas y pendientes (no todos los elementos de la jerarquı́a
del árbol incluyen estos campos, y en tal caso simplemente se mostrarán vacı́os). Al ha-
cer doble clic en una Iteration o Story nos llevará a su página de detalles, mientras que
una Task Story nos redirige a los detalles de su Story, ya que son manejadas en su mis-
ma interfaz. El árbol es el encargado de permitir la creación de nuevos elementos para la
planificación, existiendo en su barra inferior una serie de botones que nos permitirán crear
el primer elemento de una planificación o bien elementos hermanos o hijos de aquél que
esté seleccionado.
En las Task Story se emplea un código de colores en su fondo para identificar el estado
de su trabajo: verde nos indicará que el trabajo está terminado, rojo que todavı́a no ha
empezado y amarillo que se encuentra en progreso.
Esta interfaz emplea actualmente un único servicio web3 :
Detalles de Iteration
Esta interfaz nos presenta en un panel los datos actuales de una Iteration (ver figu-
ra 6.15 en la página 86), con un botón en la esquina superior derecha que nos permite
editarla llevándonos a su formulario. En la parte inferior presenta otro panel que incluye el
árbol de su proyecto, con la rama de la Iteration expandida para que podamos ver las Story
que contiene.
Solamente emplea el servicio web para recuperar el árbol:
Formulario de Iteration
Es el formulario empleado para crear y editar Iteration, conteniendo campos para sus
atributos (ver figura 6.16 en la página 87).
No tiene ningún elemento destacable y tampoco emplea servicios web.
3
los formularios de creación y edición de los elementos de planificación no se encuentran actualmente
con un enfoque dinámico debido a ciertas complicaciones que presenta el ((widget)) del árbol de ExtJS,
el cual acaba de salir de su fase experimental, que hacen actualmente inviable el uso de ventanas
interiores en esta misma interfaz; en todo caso, se espera que el problema se solucione en versiones
próximas del framework, lo que motivará la adopción del mismo enfoque de formularios dinámicos que
otras interfaces.
6.3. Implementación 85
Detalles de Story
Esta interfaz nos presenta en un panel los datos actuales de una Story (ver figu-
ra 6.17 en la página siguiente), además de ciertos datos derivados de las horas trabajadas,
incluyendo un botón en la esquina superior derecha que nos permite editarla llevándonos
a su formulario. Debajo presenta un panel con las Task Story que contiene, con botones
para crear, editar y eliminar, empleando para ello ventanas interiores a esta propia interfaz.
Por último contiene un panel que nos muestra la descripción de todas las tareas asociadas
a sus Task Story a modo de descripción de la Story.
Emplea los siguientes servicios web:
Formulario de Story
Es el formulario empleado para crear y editar Story (ver imagen 6.18 en la página 90),
conteniendo campos para sus atributos.
Al igual que el de iteraciones, tampoco emplea servicios web, y solamente destacaremos
que por defecto se selecciona al usuario actual como supervisor en caso de que sea una
opción disponible en el combobox correspondiente, ya que es habitual que sea él el encargado
de crear las Story.
4
de nuevo sus formularios son estáticos por el momento, pero se espera migrarlos a un conjunto
dinámico cuando el problema del ((widget)) del árbol esté solucionado.
6.3. Implementación 89
Detalles de Module
Esta interfaz nos presenta en un panel los datos actuales de un Module (ver figu-
ra 6.20 en la página siguiente), con un botón en la esquina superior derecha que nos permite
editarla llevándonos a su formulario. En la parte inferior presenta otro panel que incluye el
árbol de su proyecto, con la rama del Module expandida para que podamos ver las Section
que contiene.
Solamente emplea el servicio web para recuperar el árbol:
Formulario de Module
Es el formulario empleado para crear y editar Module, conteniendo campos para sus
atributos (ver figura 6.21 en la página 94).
No tiene ningún elemento destacable y tampoco emplea servicios web.
Detalles de Section
Esta interfaz nos presenta en un panel los datos actuales de una Section (ver figu-
ra 6.22 en la página 95), además de ciertos datos derivados de las horas trabajadas, inclu-
yendo un botón en la esquina superior derecha que nos permite editarla llevándonos a su
formulario. Debajo presenta un panel con las Task Section que contiene, con botones para
crear, editar y eliminar, empleando para ello ventanas interiores a esta propia interfaz.
Emplea los siguientes servicios web:
Formulario de Section
Es el formulario empleado para crear y editar Section, conteniendo campos para sus
atributos (imagen 6.23 en la página 96).
Al igual que el de módulos, tampoco emplea servicios web, y solamente destacaremos
que por defecto se selecciona al usuario actual como supervisor en caso de que sea una
opción disponible en el combobox correspondiente, ya que es habitual que sea él el encargado
de crear las Sections.
6.3. Implementación 93
No tocar durante su ejecución ningún elemento de la página que se está testeando (un
orden diferente en la renderización de los elementos asignará identificadores diferentes
y trastocará la ejecución de los tests).
En caso de que algún test falle, realizarlo de manera individual, ya que siempre cabe
la posibilidad de que un mensaje se haya perdido en un paso intermedio (recordemos
que es posible que la BD haya quedado en un estado inconsistente y sea necesario
limpiarla o reiniciarla con el ((dump))).
Limitaciones, mejoras
potenciales y conclusiones
globales
7.1. Limitaciones
7.1.1. Planificación de trabajo
En este apartado no se han apreciado limitaciones sobre los objetivos previstos ini-
cialmente, debido principalmente a que estuvo altamente centrado en el análisis y diseño
partiendo del modelo de XPTracker (ver apartado 4.2 en la página 34), sin encontrar ningún
problema destacable en la implementación o dilemas de diseño.
100
7.2. Mejoras potenciales 101
navegadores Firefox y derivados de WebKit [94]), pero en cada versión nueva del framework
solucionan los problemas encontrados, por lo que tampoco se considera crı́tica.
Interfaces web totalmente dinámicas para planificación: una vez que el ((widget)) para
representar árboles en ExtJS deje de estar en estado experimental y pase a estable
se deberı́a crear un conjunto de interfaces dinámicas con ventanas embebidas que
permitieran añadir, eliminar y editar componentes desde la propia interfaz del árbol,
agilizando su uso.
Mejorar el aspecto de todas las páginas con CSS: debido a que el objetivo del proyecto
era obtener las funcionalidades lo antes posible, el aspecto estético del conjunto pasó a
un segundo plano, proporcionando un aspecto espartano en ese sentido en la mayorı́a
7.3. Conclusiones globales 102
de las páginas. Crear un conjunto de hojas de estilo para lograr un aspecto más
agradable en el diseño de la página como contenedor serı́a deseable.
Unificar los ((banners)) de resultado en la interfaz de tareas: los servicios web para
operaciones de creación, edición y borrado generan banners diferentes en la interfaz
de tareas aunque las llamadas a los tres se efectúan pulsando un mismo botón. Esto
es confuso para el usuario si no conoce el funcionamiento interno de la aplicación,
por lo que serı́a aconsejable juntar de algún modo los mensajes de los tres, o cuando
menos diferenciarlos claramente.
Ordenar en el tiempo las operaciones en la interfaz de tareas: los servicios web para
operaciones de creación, edición y borrado de las tareas son llamados con peticiones
enviadas simultáneamente, lo que provoca que su orden de ejecución sea indetermi-
nado. El orden deberı́a ser:
De este modo eliminamos problemas como que creemos una tarea nueva que en
principio esté solapada con otra, desplacemos esta última en el tiempo y aún ası́ nos
dé error de solapamiento (ya que ha intentado ejecutar antes la creación que la
edición).
Las interfaces web también lograron los objetivos previstos inicialmente, con la ex-
cepción de las destinadas a la planificación, que por el momento emplean en su
mayorı́a formularios estáticos a la espera de que el ((widget)) del árbol de ExtJS pase
a ser estable. También son el apartado susceptible a un mayor número de mejoras,
principalmente por ser del cual se recibe más ((feedback)) de parte de los usuarios
(apartado 6.4.2 en la página 99) ya que es el único que realmente llegan a conocer.
Consecuentemente se puede afirmar que el producto obtenido satisface todas las nece-
sidades iniciales, con la excepción de los formularios estáticos empleados como una solución
temporal.
En cuanto al proceso en sı́, el trabajo se desarrolló por lo general de una manera ágil
y fluida, siendo la etapa de aprendizaje de ExtJS e inicios de su uso el único momento
en el que hubo una ralentización notable. Esto se debió sobre todo a la inexistencia de un
tutorial decente, documentación inacabada y elementos sin documentación (experimentales
o ad hoc) que requirieron múltiples pruebas o personalización por parte del alumno. Pese a
ello podemos afirmar sin dudas que también en ese aspecto el proyecto tuvo un resultado
satisfactorio, aportando conocimientos nuevos y experiencia al alumno en cada uno de sus
apartados.
Anexo A
Diagramas adicionales
104
A.1. Diagramas Entidad-Relación 105
Figura A.3: diagrama UML de todos los DAOs existentes en PhpReport (1/4)
A.2. Diagramas UML 108
Figura A.4: diagrama UML de todos los DAOs existentes en PhpReport (2/4)
A.2. Diagramas UML 109
Figura A.5: diagrama UML de todos los DAOs existentes en PhpReport (3/4)
A.2. Diagramas UML 110
Figura A.6: diagrama UML de todos los DAOs existentes en PhpReport (4/4)
A.2. Diagramas UML 111
Código
113
B.1. Planificación de trabajo 114
57
58 i f ( $moduleVO−>g e t I d ( ) != ” ” ) {
59 $currModuleVO = $ t h i s −>g e t B y I d ( $moduleVO−>g e t I d ( ) ) ;
60 }
61
62 // I f t h e q u e r y r e t u r n e d a row t h e n u p d a t e
63 i f ( s i z e o f ( $currModuleVO ) > 0 ) {
64
65 $ s q l = ”UPDATE module SET name=” . D B P o s t g r e s : : c h e c k S t r i n g N u l l ( $moduleVO−>getName ( ) ) .
” , i n i t =” . D B P o s t g r e s : : f o r m a t D a t e ( $moduleVO−>g e t I n i t ( ) ) . ” , e n d=” .
D B P o s t g r e s : : f o r m a t D a t e ( $moduleVO−>g e t E n d ( ) ) . ” , summary=” . D B P o s t g r e s : :
c h e c k S t r i n g N u l l ( $moduleVO−>getSummary ( ) ) . ” , p r o j e c t i d=” . D B P o s t g r e s : : c h e c k N u l l
( $moduleVO−>g e t P r o j e c t I d ( ) ) . ” WHERE i d=” . $moduleVO−>g e t I d ( ) ;
66
67 $ r e s = p g q u e r y ( $ t h i s −>c o n n e c t , $ s q l ) ;
68
69 i f ( $ r e s == NULL)
70 i f ( strpos ( p g l a s t e r r o r () , ” unique module project name ”) )
71 t h r o w new S Q L U n i q u e V i o l a t i o n E x c e p t i o n ( p g l a s t e r r o r ( ) ) ;
72 e l s e t h r o w new S Q L Q u e r y E r r o r E x c e p t i o n ( p g l a s t e r r o r ( ) ) ;
73
74 $affectedRows = pg affected rows ( $res ) ;
75 }
76
77 return $affectedRows ;
78
79 }
80
81 /∗∗ Module c r e a t o r f o r PostgreSQL .
82 ∗
83 ∗ T h i s f u n c t i o n c r e a t e s a new row f o r a Module by i t s { @ l i n k ModuleVO } .
84 ∗ The i n t e r n a l i d o f <v a r>$moduleVO</v a r> w i l l be s e t a f t e r i t s c r e a t i o n .
85 ∗
86 ∗ @param ModuleVO $moduleVO t h e { @ l i n k ModuleVO} w i t h t h e d a t a we want t o i n s e r t on d a t a b a s e .
87 ∗ @ r e t u r n i n t t h e number o f r o w s t h a t h a v e b e e n a f f e c t e d ( i t s h o u l d be 1 ) .
88 ∗ @t hr ow s { @ l i n k S Q L Q u e r y E r r o r E x c e p t i o n } , { @ l i n k S Q L U n i q u e V i o l a t i o n E x c e p t i o n }
89 ∗/
90 p u b l i c f u n c t i o n c r e a t e ( ModuleVO $moduleVO ) {
91
92 $affectedRows = 0;
93
94 $ s q l = ”INSERT INTO module ( name , i n i t , e nd , summary , p r o j e c t i d ) VALUES( ” . D B P o s t g r e s : :
c h e c k S t r i n g N u l l ( $moduleVO−>getName ( ) ) . ” , ” . D B P o s t g r e s : : f o r m a t D a t e ( $moduleVO−>g e t I n i t
( ) ) . ” , ” . D B P o s t g r e s : : f o r m a t D a t e ( $moduleVO−>g e t E n d ( ) ) . ” , ” . D B P o s t g r e s : :
c h e c k S t r i n g N u l l ( $moduleVO−>getSummary ( ) ) . ” , ” . D B P o s t g r e s : : c h e c k N u l l ( $moduleVO−>
getProjectId () ) . ”)” ;
95
96 $ r e s = p g q u e r y ( $ t h i s −>c o n n e c t , $ s q l ) ;
97
98 i f ( $ r e s == NULL)
99 i f ( strpos ( p g l a s t e r r o r () , ” unique module project name ”) )
100 t h r o w new S Q L U n i q u e V i o l a t i o n E x c e p t i o n ( p g l a s t e r r o r ( ) ) ;
101 e l s e t h r o w new S Q L Q u e r y E r r o r E x c e p t i o n ( p g l a s t e r r o r ( ) ) ;
102
103 $moduleVO−>s e t I d ( D B P o s t g r e s : : g e t I d ( $ t h i s −>c o n n e c t , ” m o d u l e i d s e q ” ) ) ;
104
105 $affectedRows = pg affected rows ( $res ) ;
106
107 return $affectedRows ;
108
109 }
110
111 /∗∗ Module d e l e t e r f o r PostgreSQL .
112 ∗
113 ∗ T h i s f u n c t i o n d e l e t e s t h e d a t a o f a Module by i t s { @ l i n k ModuleVO } .
114 ∗
115 ∗ @param ModuleVO $moduleVO t h e { @ l i n k ModuleVO} w i t h t h e d a t a we want t o d e l e t e from d a t a b a s e .
116 ∗ @ r e t u r n i n t t h e number o f r o w s t h a t h a v e b e e n a f f e c t e d ( i t s h o u l d be 1 ) .
117 ∗ @t hr ow s { @ l i n k S Q L Q u e r y E r r o r E x c e p t i o n }
118 ∗/
119 p u b l i c f u n c t i o n d e l e t e ( ModuleVO $moduleVO ) {
120 $affectedRows = 0;
121
122 // Check f o r a module ID .
123 i f ( $moduleVO−>g e t I d ( ) >= 0 ) {
124 $currModuleVO = $ t h i s −>g e t B y I d ( $moduleVO−>g e t I d ( ) ) ;
125 }
126
127 // O t h e r w i s e d e l e t e a module .
128 i f ( s i z e o f ( $currModuleVO ) > 0 ) {
129 $ s q l = ”DELETE FROM module WHERE i d=” . $moduleVO−>g e t I d ( ) ;
130
131 $ r e s = p g q u e r y ( $ t h i s −>c o n n e c t , $ s q l ) ;
132 i f ( $ r e s == NULL) t h r o w new S Q L Q u e r y E r r o r E x c e p t i o n ( p g l a s t e r r o r ( ) ) ;
133 $affectedRows = pg affected rows ( $res ) ;
134 }
135
B.1. Planificación de trabajo 115
Código B.2: fragmento de la acción para obtener las horas extra, ExtraHoursReportAction.php
1
2 /∗∗ T r a n s l a t e t o d a y s from e p o c h .
3 ∗
4 ∗ Compute t h e d a y s p a s s e d s i n c e a r e f e r e n c e d a t e c a l l e d ” e p o c h ” (”1970 −01 −05”).< b r/>NOTE : F o r
c o n v e n i e n c e r e a s o n s , t h e e p o c h ISN ’T THE SAME a s t h e s t a n d a r d u n i x epoch ,
5 ∗ b e c a u s e i t ’ s Monday and can be u s e d t o compute t h e week day d o i n g modulus .
6 ∗
7 ∗ @param DateTime $ d a t e t h e d a t e t h a t we want t o t r a n s l a t e t o d a y s from e p o c h .
8 ∗ @ r e t u r n i n t t h e number o f d a y s s i n c e 1970−01−05.
9 ∗/
10 p r i v a t e f u n c t i o n daysFromEpoch ( DateTime $ d a t e ) {
11 $aux = d a t e c r e a t e ( $ d a t e−>f o r m a t ( ”Y−m−d” ) ) ; // <−−−− T h i s c o d e a c t s a s a w o r k a r o u n d w i t h a PHP bug
12
13 // 1970−01−05 i s a b e t t e r e p o c h day , b e c a u s e i t ’ s Monday and can be
14 // u s e d t o compute t h e week day d o i n g modulus
15
16 $aux2 = $aux−>d i f f ( d a t e c r e a t e ( ”1970−01−05” ) ) ;
17 $ r e s u l t = $aux2−>d a y s ;
18 return $result ;
19 }
20
21
22 /∗∗ Compute t h e number o f w o r k i n g d a y s .
23 ∗
24 ∗ Compute t h e number o f w o r k i n g d a y s b e t w e e n two g i v e n d a t e s ( b o t h i n c l u d e d ) .
25 ∗
26 ∗ @param DateTime $ i n i t t h e i n i t d a t e o f t h e i n t e r v a l .
27 ∗ @param DateTime $end t h e e n d i n g d a t e o f t h e i n t e r v a l .
28 ∗ @ r e t u r n i n t t h e number o f w o r k i n g d a y s b e t w e e n t h e two d a t e s .
29 ∗/
30 p r i v a t e f u n c t i o n numWorkDays ( DateTime $ i n i t , DateTime $end ) {
31 // T a k i n g on a c c o u n t t h e t h i n g s s a i d i n f u n c t i o n num w e e ke nd days ,
32 // t h i s i s a f u n c t i o n t h a t w o r k s i n a s i m i l a r way t o g e t t h e number
33 // o f ∗work∗ d a y s ( t h a t means e x c l u d i n g w e e k e n d s ) b e t w e e n two d a t e s .
34
35 // NOTE : −1 b e c a u s e we a l s o i n c l u d e t h e s t a r t d a t e
36 // ( i n i t <=x<=end , INSTEAD OF i n i t <x<=end )
37 $ d a y s e p o c h t o i n i t=$ t h i s −>daysFromEpoch ( $ i n i t ) −1;
38 $ d a y s e p o c h t o e n d=$ t h i s −>daysFromEpoch ( $end ) ;
39 $ w e e k e n d d a y s e p o c h t o i n i t=f l o o r ( $ d a y s e p o c h t o i n i t / 7 ) ∗ 2 ;
40 i f ( $ d a y s e p o c h t o i n i t %7==5) $ w e e k e n d d a y s e p o c h t o i n i t +=1;
41 e l s e i f ( $ d a y s e p o c h t o i n i t %7==6) $ w e e k e n d d a y s e p o c h t o i n i t +=2;
42
43 $ w e e k e n d d a y s e p o c h t o e n d=f l o o r ( $ d a y s e p o c h t o e n d / 7 ) ∗ 2 ;
44 i f ( $ d a y s e p o c h t o e n d %7==5) $ w e e k e n d d a y s e p o c h t o e n d +=1;
45 e l s e i f ( $ d a y s e p o c h t o e n d %7==6) $ w e e k e n d d a y s e p o c h t o e n d +=2;
46
47 $result = $days epoch to end − $days epoch to init −
48 ( $weekend days epoch to end − $weekend days epoch to init ) ;
49
50
51 return $result ;
52 }
53
54
55 /∗∗ Compute t h e number o f e x t r a h o u r s worked
56 ∗
57 ∗ Compute t h e number o f e x t r a h o u r s u s e r s h a v e worked b e t w e e n two d a t e s ( b o t h i n c l u d e d ) .
58 ∗ We can p a s s an o p t i o n a l p a r a m e t e r , <v a r>$ u s e r </v a r >, i f we want t o compute o n l y a U s e r d a t a .
59 ∗ <b r/><b r/> I t r e t u r n s an a s s o c i a t i v e a r r a y w i t h t h e f o l l o w i n g d a t a r e l a t e d t o e a c h U s e r ’ s l o g i n :
60 ∗ <u l>
61 ∗ <l i >’ t o t a l h o u r s ’ : number o f t o t a l h o u r s a U s e r h a s worked i n t h e s p e c i f i e d i n t e r v a l .</ l i >
62 ∗ <l i >’ w o r k a b l e h o u r s ’ : number o f h o u r s a U s e r must work i n t h e s p e c i f i e d i n t e r v a l a c c o r d i n g t o h i s /
h e r j o u r n e y .</ l i >
63 ∗ <l i >’ e x t r a h o u r s ’ : number o f e x t r a h o u r s a U s e r h a s worked , a c c o r d i n g t o t h e p r e v i o u s d a t a .</ l i ></
u l>
64 ∗
65 ∗ @param DateTime $ i n i t t h e i n i t d a t e o f t h e i n t e r v a l .
66 ∗ @param DateTime $end t h e e n d i n g d a t e o f t h e i n t e r v a l .
67 ∗ @param UserVO $ u s e r t h e U s e r whose e x t r a h o u r s we want t o compute .
68 ∗/
69 p r i v a t e f u n c t i o n n e t E x t r a H o u r s ( DateTime $ i n i t , DateTime $end , UserVO $ u s e r = NULL) {
70
71 $ t a s k D a o = DAOFactory : : getTaskDAO ( ) ;
72 $commonDao = DAOFactory : : getCommonEventDAO ( ) ;
73 $ j o u r n e y H i s t o r y D a o = DAOFactory : : g e t J o u r n e y H i s t o r y D A O ( ) ;
74 $ c i t y H i s t o r y D a o = DAOFactory : : g e t C i t y H i s t o r y D A O ( ) ;
75
76 i f ( i s n u l l ( $user ) )
77 {
B.2. Extracción de datos avanzada 117
146 i f ( i s n u l l ( $ h i s t o r i e s [ $ i ] [ ” end ” ] ) | | ( ( $ h i s t o r i e s [ $ i
] [ ” end ” ] > $ c i t y R o w−>g e t E n d D a t e ( ) ) ) && (
$ h i s t o r i e s [ $ i ] [ ” i n i t ” ] < $ c i t y R o w−>g e t E n d D a t e ( ) ) )
147 $ h i s t o r i e s [ $ i ] [ ” end ” ] = $ c i t y R o w−>g e t E n d D a t e ( )
;
148
149 // I f b o t h d a t e s a r e NULL , t h e n end d a t e i s nowadays
150
151 i f ( i s n u l l ( $ h i s t o r i e s [ $ i ] [ ” end ” ] ) )
152 $ h i s t o r i e s [ $ i ] [ ” end ” ] = new DateTime ( ) ;
153
154 $ h i s t o r i e s [ $ i ] [ ” c i t y ” ] = $ c i t y R o w−>g e t C i t y I d ( ) ;
155
156 $ i ++;
157 }
158 }
159
160 $hours = 0;
161
162 f o r e a c h ( ( a r r a y ) $ h i s t o r i e s a s $row )
163 {
164
165 i f ( $row [ ” i n i t ” ] < $ i n i t )
166 $row [ ” i n i t ” ] = $ i n i t ;
167
168 i f ( $row [ ” end ” ] > $end )
169 $row [ ” end ” ] = $end ;
170
171 $work = $ t h i s −>numWorkDays ( $row [ ” i n i t ” ] , $row [ ” end ” ] ) ;
172 $ h o l i d a y s = c o u n t ( $commonDao−>g e t B y C i t y I d D a t e s ( $row [ ” c i t y ” ] , $row [ ”
i n i t ” ] , $row [ ” end ” ] ) ) ;
173 $ w o r k H o u r s = ( $work − $ h o l i d a y s ) ∗ $row [ ” j o u r n e y ” ] ;
174 $us e r Wor k [ $userVO−>g e t L o g i n ( ) ] [ ” w o r k a b l e h o u r s ” ] += $ w o r k H o u r s ;
175
176 }
177
178 $us e r Wor k [ $userVO−>g e t L o g i n ( ) ] [ ” e x t r a h o u r s ” ] = $us e r Wor k [ $userVO−>g e t L o g i n ( )
] [ ” t o t a l h o u r s ” ] − $us e r Wor k [ $userVO−>g e t L o g i n ( ) ] [ ” w o r k a b l e h o u r s ” ] ;
179 }
180
181 }
182
183 r e t u r n $us e r Wor k ;
184 }
Código B.2: fragmento de la acción para obtener las horas extra, ExtraHoursReportAction.php
B.2. Extracción de datos avanzada 119
Código B.3: fragmento de la acción para obtener las horas de vacaciones pendientes,
GetPendingHolidayHoursAction.php
1
2 // We compute t h e h o l i d a y h o u r s f o r e a c h U s e r
3 f o r e a c h ( ( a r r a y ) $ u s e r s a s $userVO )
4 {
5
6 // We o n l y compute i t f o r w o r k e r s , s o t h e y must be i n a g r o u p
7 i f ( ! i s n u l l ( $userVO−>g e t G r o u p s ( ) ) )
8 {
9
10 // We g e t h i s / h e r j o u r n e y s i n t h e d a t e i n t e r v a l
11 $ j o u r n e y H i s t o r y = $ j o u r n e y H i s t o r y D a o −>g e t B y I n t e r v a l s ( $ t h i s −>i n i t , $ t h i s −>end , $userVO
−>g e t I d ( ) ) ;
12
13 // He/ s h e s t a r t s w i t h no worked h o u r s
14 $workHours = 0 ;
15
16 foreac h ( ( a r r a y ) $ j o u r n e y H i s t o r y as $journeyRow )
17 {
18
19 // F i r s t o f a l l , we c l i p t h e i n t e r v a l w i t h t h e j o u r n e y
20 $ i n i t = $j our ne yR ow−>g e t I n i t D a t e ( ) ;
21 $end = $j our ne yR ow−>g e t E n d D a t e ( ) ;
22
23 i f ( $ i n i t <$ t h i s −>i n i t )
24 $ i n i t = $ t h i s −>i n i t ;
25
26 i f ( $end>$ t h i s −>end )
27 $end = $ t h i s −>end ;
28
29 // We g e t t h e d i f f e r e n c e i n d a y s . . .
30 $ d i f f J o u r n e y = $ i n i t −>d i f f ( $end ) ;
31 // and w i t h i t and t h e j o u r n e y , t h e worked h o u r s ( p l u s one day b e c a u s e i t ’ s a
closed ending i n t e r v a l )
32 $ w o r k H o u r s += ( $ d i f f J o u r n e y −>d a y s + 1 ) ∗( $j our ne yR ow−>g e t J o u r n e y ( ) ) ;
33
34
35 // We must c h e c k f o r l e a p y e a r s on t h e i n t e r v a l
36 $ i n i t Y e a r = $ i n i t −>f o r m a t ( ”Y” ) ;
37
38 // Go from t h e i n i t y e a r t o t h e end one
39 w h i l e ( $ i n i t Y e a r <= $end−>f o r m a t ( ”Y” ) )
40 {
41
42 // We c h e c k i f t h e y e a r i s a l e a p one , and i f f e b r u a r y 29 t h i s i n t h e
i n t e r v a l . T h e r e can be some u s e l e s s c h e c k i n g s h e r e
43 // ( f e b r u a r y 29 t h can be p r i o r t o t h e i n i t o n l y i n t h e f i r s t y e a r , and
l a t e r t h a n t h e end on t h e l a s t one ) , b u t i t ’ s no
44 // much c o m p u t a t i o n anyway , and t h e c o d e i s c l e a r ( and i t ’ s a l r e a d y
hard to understand at f i r s t )
45 i f ( checkdate (02 ,29 , $ i n i t Y e a r ) )
46 i f ( ( $ i n i t < d a t e c r e a t e ( $ i n i t Y e a r . ”−02−29” ) ) && ( $end >=
d a t e c r e a t e ( $ i n i t Y e a r . ”−02−29” ) ) )
47 $ w o r k H o u r s −= $j our ne yR ow−>g e t J o u r n e y ( ) ; // I t ’
s a l e a p y e a r , s o we s u b t r a c t one j o u r n e y f o r
f e b r u a r y 29 t h
48
49 $ i n i t Y e a r ++;
50 }
51
52 }
53
54 // We g e t t h e v a c a t i o n s he / s h e h a s s p e n t i n t h e i n t e r v a l
55 $ v a c a t i o n s = $taskDao−>g e t V a c a t i o n s ( $userVO , $ t h i s −>i n i t , $ t h i s −>end ) ;
56
57 // Y e a r l y h o l i d a y h o u r s i s t h e s t a n d a r d f o r an 8−h o u r j o u r n e y o v e r a y e a r , s o t h e
result is proportional
58 $ h o l i d a y H o u r s = ( $workHours /(365∗8) )∗ C o n f i g u r a t i o n P a r a m e t e r s M a n a g e r : : getParameter ( ’
YEARLY HOLIDAY HOURS ’ ) ;
59
60 // The d i f f e r e n c e i s t h e number o f p e n d i n g h o l i d a y h o u r s
61 $ u s e r P e n d i n g H o l i d a y H o u r s [ $userVO−>g e t L o g i n ( ) ]= $ h o l i d a y H o u r s −$ v a c a t i o n s [ ” a d d h o u r s ” ] ;
62
63 }
64
65 }
66
67 return $userPendingHolidayHours ;
Código B.3: fragmento de la acción para obtener las horas de vacaciones pendientes,
GetPendingHolidayHoursAction.php
Anexo C
Glosario de acrónimos
BD Base de Datos
CO Custom Object
DB Database
E-R Entidad-Relación
120
121
VO Value Object
XP Extreme Programming
Referencias
122
REFERENCIAS 123
[36] P. Chen et al., Entity-Relationship Modeling: Historical Events, Future Trends, and
Lessons Learned. Louisiana State University, Baton Rouge, LA 70803, USA. http://
bit.csc.lsu.edu/~chen/pdf/Chen_Pioneers.pdf.
[57] J. Reimer, “Total share: 30 years of personal computer market share figures.” http://
arstechnica.com/old/content/2005/12/total-share.ars.
[65] S. O’Sullivan, “History of time tracking jobs & staff in Australian and NZ
manufacturing.” http://www.google.com/url?sa=t&source=web&ct=res&
cd=3&ved=0CCYQFjAC&url=http%3A%2F%2Fwww.empowersoftware.co.nz
%2FPDFs%2FJoinersMagazineDec07.pdf&ei=8EX8S_yCHI-P4gbN1c2AAw&
usg=AFQjCNFEoXMFNAXyG7CtLbLNKF1Jmg9Qeg&sig2=YX9ao46F2ktoSOuxMuSaKw.
126