Introducción

TeloTraigodemiPueblo.com es una red social para aprovechar los viajes de los usuarios a diferentes puntos de la geografía, usualmente conocidos por el usuario, y poder traer productos del lugar a amigos de su red.

Corresponde al Trabajo de Fin de Grado (TFG) de la Universitat Oberta de Catalunya (UOC), 2016-17 de Jorge Aguilera González y en estas páginas se recoge la evolución del trabajo realizado para su consecución.

Debido a que la metodología seguida por la UOC requiere de la entrega de ciertos documentos (PEC) en unas fechas determinadas, a continuación se provee de los enlaces a estos documentos. Así mismo, se puede consultar la información contenida en ellos a través de los diferentes apartados incluidos en esta página.

Historial de actividades

Motivo del proyecto

El primer documento que se realiza es una presentación del proyecto que queremos realizar para su discusión con el tutor.

Plan de trabajo (PEC1)

Una vez llegados a un acuerdo sobre el motivo del proyecto se realiza un primer trabajo (PEC1) donde se describe el proyecto, arquitectura, , planificación, etc. Una de las mayores dificultades encontradas ha sido intentar compaginar un calendario de entregas tipo cascada (definición, requisitos, implementación,entrega) , como es el propuesto por el equipo docente, con un calendario ágil basado en Sprints

Análisis, aprovisionamiento e iteracción (PEC2)

  • Realizamos un análisis de los componentes, actores y sistemas que compondrán el sistema

  • Tras definir los componentes que requerirá nuestro aplicativo, se realiza una investigación sobre qué infraestructura necesitamos, y tras su validación se realiza el aprovisionamiento necesario

  • Una vez que contamos con la estructura que vamos a necesitar se procede a realizar una primera iteración donde creamos una primera aproximación de los elementos de dominio, productos a entregar, así como el proceso de despliegue contínuo (CD)

  • Se recogen todos los pasos anteriores en un documento a entregar

Implementación (PEC3)

En esta fase, se debe realizar la implementación del aplicativo. Debido al enfoque de proceso iterativo que se ha ido aplicando hasta ahora, gran parte de este se encuentra si no desarrollado al completo, al menos avanzado.

Memoria y presentación (PEC4)

En esta fase, se documentará el trabajo realizado a lo largo del semestre en una memoria junto con una presentación (vídeo) donde se explique el mismo.

Motivo

Origen de la idea

Durante el semestre 2013-14, cursé la asignatura de Iniciativa Emprendedora perteneciente al Grado de Informática y una de los trabajos que tuvimos que desarrollar fue la de exponer varias ideas que pudieran dar lugar al emprendimiento de un negocio.

Por votación del grupo la idea ganadora fue la mía y desde entonces he querido tener la posibilidad de hacerla realidad y creo que el TFG es una magnífica oportunidad donde poder desarrollarla al menos con un nivel suficiente que demuestre su potencial.

TelotraigodemiPueblo

Básicamente la aplicación pretende dar una solución tecnológica a todas aquellas personas que viajan con frecuencia a su pueblo y reciben encargos por parte de sus amistades de productos de su tierra. Muchas veces estos encargos se quedan en el olvido, o para un viaje tenemos demasiados pedidos que complacer, o la persona que lo encarga pospone indefinidamente el pago, etc.

La aplicación consistirá en una red social donde un usuario, después de darse de alta, podrá establecer relaciones de amistad con el resto de usuarios.

Por un lado tendrá la posibilidad de indicar a su círculo a dónde, cúando y qué puede traer, y por otro podrá realizar pedidos a alguien de su círculo.

Propuesta de Arquitectura

  • Un aplicativo web que ofrecerá un API REST

  • Un aplicativo web que consumirá dicho API.

  • Un cliente móvil (próxima versión).

Frameworks / Lenguajes

El API Rest está planteado poder desarrollarlo en Grails 3.1 (https://grails.org/). Es un framework moderno basado en Groovy con bastantes años en el mercado y con mucha aceptación y en el que tengo cierta experiencia.

Como persistencia he estado sopesando Neo4j. Es un motor de base de datos muy diferente al típico MySQL/Postgre, etc y que por lo que he leído sería ideal para aplicaciones de tipo redes sociales. No tengo experiencia en él y podría ser un riesgo, pero por otro lado me motiva hacer algo un tanto diferente.

La parte cliente, se plantea como una aplicación Angular 1.5

Metodología

Pretendo aplicar una metodología ágil y contínua (en la medida que pueda 1 persona) en la que tras una planificación inicial general pueda ir haciendo entregas sucesivas tanto de código, test y despliegue.

Herramientas

Se va a usar Git y las herramientas de CI/CD que ofrece tanto para el control de código, incidencias como test.

Para el despliegue de la aplicación se plantea utilizar OpenShift de Redhat o similar.

Hito 1 (PEC1)

La PEC1 consiste en la entrega de documento donde se detalle la idea del proyecto así como la arquitectura y una planificación de tareas a realizar. En el documento Consultar el "Plan de Trabajo" PEC1 se recogen los siguientes apartados:

Incepción

"Te lo traigo de mi pueblo" pretende ser el aplicativo donde personas con relaciones de confianza puedan indicar a su grupo que van a ir de visita a un lugar típico y pueden traer productos de ese lugar.

La aplicación permitirá a cada usuario gestionar un número indeterminado de lugares y productos locales del mismo, de tal forma que cuando publique en su red que va a ir a ese lugar en una fecha determinada, los miembros de la misma puedan realizarle pedidos. El usuario podrá decidir qué pedidos puede comprometerse a traer y de esa forma optimizar su viaje.

El viajante queda bien con sus amistades al poder cumplir con los encargos, las amistades contentas por disponer de productos locales y los vendedores locales por el incremento de sus ventas.

La red de amistades tendrá una forma típica de red social donde un usuario puede estar enlazado con un número indeterminado de usuarios. Para realizar este enlace un usuario enviará a otro una solicitud de enlace que el segundo usuario podrá aceptar o ignorar. A partir del momento en que se encuentren enlazados un usuario podrá ver los viajes futuros que publique el otro.

Para este Minimum Value Product (MVP) se busca la sencillez por lo que las pantallas y navegación estarán enfocadas hacia la funcionalidad del sistema y no a su presentación estética.

La evolución lógica del aplicativo, que queda fuera del MVP, sería buscar la monetirización de la misma, incluyendo una pasarela de pago, publicidad de los vendedores locales, etc.

Objetivo

Como podemos ver por la incepción de la idea, el producto a conseguir tiene por objetivo obtener un producto mínimo viable (MVP), en un tiempo reducido, que sirva como presentación ante un posible grupo de inversores para seguir evolucionándolo. Para la consecución de este MVP se deberá implementar una serie de funcionalidades imprescindibles, de primer nivel, así como otras básicas, de segundo nivel, que deberán ser definidas al inicio del proyecto.

Así mismo presenta un alto componente tecnológico (gestionar redes de contactos, indeterminado número de lugares y productos, etc) lo que implica definir una arquitectura y herramientas que permitan un desarrollo rápido pero fiable.

Épicas

Entendemos por épica, dentro del marco de desarrollo ágil, aquellas historias de usuario demasiado genéricas y que nos sirven para delimitar el producto en áreas. De la división de estas en elementos más pequeños obtenemos las historias de usuario y de estos a su vez los items a desarrollar.

Así para el caso de TelotraigodemiPueblo encontramos las siguientes épicas y para cada una de ellas las historias de usuario.

Red Social (EP1)

Como red social que es, TelotraigodemiPueblo permitirá registrar a usuarios nuevos, los cuales deberán proporcionar su email como identificador así como establecer una contraseña para validar el acceso. Como esperamos un alto grado de aceptación del aplicativo, no nos centraremos en el borrado del usuario hasta que el departamento de asuntos legales nos confirme su necesidad. Mediante formularios de búsqueda, el usuario encontrará personas que no están en su red y a las que podrá enviar una invitación de contacto.

  • Registro de usuarios (HU1)

Como persona ajena al sistema deseo registrarme en el mismo introduciendo mi email. Tras la comprobación de aquél podré añadir información en lo que será mi perfil como mi password, nombre, edad, etc.

  • Búsqueda de gente (HU2)

Como usuario identificado en cualquier momento puedo realizar búsquedas en la red global para buscar conocidos. Para ello introduciré un nombre y el sistema me buscará los que concuerden con el mismo.

  • Búsqueda de lugares (HU3)

Como usuario identificado podré buscar por lugares lo que me ofrecerá un listado de personas que tienen el nombre del lugar introducido entre sus sitios de viaje.

  • Solicitud de enlace (HU4)

En ambos casos, una vez obtenido el listado de usuarios podré enviar una solicitud de enlace en el caso de que no se encuentre en mi red de contactos. Si ya se encuentra el sistema no hará nada.

  • Aceptación de solicitud (HU5)

Como usuario registrado quiero ver las solicitudes de contacto que tengo pendientes y si decido aceptarla se creará un enlace entre el demandante y yo.

Lugares y productos (EP2)

Como usuario "telotraigo" quiero poder gestionar un número indeterminado de lugares que visito, como puede ser el pueblo de mi padre, de mi madre, novia, etc. Básicamente quiero poder decirle a mi red cómo se llama el lugar y dar alguna indicación para que puedan buscarlo, por ejemplo mediante geolocalización. En versiones futuras se podría incluir otros elementos a cada lugar que ayuden a describirlo mejor e incluso abrir una vía de monetarización.

Cada lugar tiene productos típicos que quiero poder mostrar a mi red. En este MVP vale una pequeña descripción y un precio aproximado de cada uno de ellos aunque lo ideal sería poder incluir fotos, enlaces, etc. El número de productos que puedo indicar por cada lugar es variable e indeterminado.

  • ver mis lugares (HU6)

Como usuario identificado quiero poder ver un listado de mis lugares con la información necesaria para poder identificarlos

  • crear un lugar (HU7)

Como usuario identificado quiero poder crear un nuevo lugar indicando el nombre, latitud y longitud.

  • borrar un lugar (HU8)

Como usuario identificado con al menos un lugar añadido, quiero poder borrarlo de mi lista, siempre y cuando no tenga ningún viaje con pedidos pendientes al mismo.

  • modificar un lugar (HU9)

Como usuario identificado quiero poder modificar la información de cualquiera de mis lugares.

  • añadir productos a un lugar (HU10)

Como usuario identificado quiero poder añadir un producto a un lugar por lo que tras seleccionar el lugar añado un producto indicando la descripción y precio aproximado

  • modificar un producto a un lugar (HU11)

Como usuario identificado quiero poder modificar un producto existente por lo que tras seleccionarlo puedo modificar los datos del mismo. Si hubiera un pedido pendiente que incluyera este producto debería enviarse un mensaje al solicitante notificandole del cambio.

  • borrar un producto a un lugar (HU12)

Como usuario identificado quiero poder eliminar un producto existente por lo que tras seleccionarlo puedo eliminarlo de la lista. Si hubiera un pedido pendiente que incluyera este producto debería enviarse un mensaje al solicitante notificandole de la situación y eliminandolo de la lista.

Telopido (EP3)

Cuando voy a realizar un viaje a uno de mis lugares quiero hacerselo saber a mi red de contactos mediante una nota en la que indique además del sitio al que voy, la fecha en la que volveré (no importa cúando me voy, sino cúando vuelvo). Además indicaré cuántos pedidos puedo aceptar en ese viaje de una forma orientativa y estableceré una fecha tope para aceptarlos.

De esta forma, mis contactos podrán apuntarse enviando una petición de qué producto y la cantidad que quieren pedirme. Yo recibiré estas peticiones y las podré aceptar o rechazar en función de la capacidad disponible. Tanto si acepto como rechazo, quien me ha hecho el pedido recibirá una notificación sobre su petición.

  • planificar un viaje (HU13)

Como usuario identificado quiero poder planificar un viaje a alguno de mis lugares para lo cual proporcionaré una fecha de retorno y un número de pedidos máximos que puedo aceptar. Mi red recibirá un aviso de esta situación

  • realizar pedido (HU14)

Como usuario seguidor recibiré mensajes en mi tablón sobre los viajes de mi red y al seleccionar uno podré realizar un pedido, indicando el producto y la cantidad que deseo. Hasta no recibir la confirmación (o rechazo) el pedido no será efectivo. En caso de que el viaje tuviera una fecha tope de aceptación de pedidos y esta se haya sobrepasado el sistema no me permitirá realizar el pedido.

  • aceptar pedido (HU15)

Como usuario "telotraigo" recibiré mensajes en mi tablón sobre los pedidos que me realizan mis contactos y tras seleccionarlos podré aceptarlos o rechazarlos. En caso de aceptarlos el pedido será adjuntado a mi viaje mientras que si es rechazado no se hará nada. En ambos casos mi seguidor recibirá un mensaje sobre su pedido.

  • ver situación de un viaje (HU16)

En cualquier momento como usuario "telotraigo" podré comprobar los pedidos realizados para un viaje. En una versión futura podría disponer de un mecanismo de exportarlo o enviarlo por correo, etc.

Tecnología y Arquitectura

Tras un estudio de los requisitos y épicas relativas al proyecto decidimos optar por una aplicación web que permita a los diferentes usuarios del sistema interactuar con él de forma independiente. Así mismo aunque en esta primera versión nos centraremos en una aplicación web, la arquitectura deberá contemplar posibles integraciones futuras con dispositivos móviles, Smart TV, etc por lo que deberá ofrecer un API REST de acceso.

Para el desarrollo de la aplicación optaremos por un framework de desarrollo rápido como es Grails el cual aúna diferentes productos tecnológicos como son Spring Framework, Hibernate, y otros, contando además con un extenso ecosistemas de plugins que nos pueden ayudar en la elaboración del producto.

Debido a la naturaleza de red social del proyecto se ha hecho una investigación consultando diferentes artículos y casos de uso (como por ejemplo http://www.grapheverywhere.com/portfolio-item/social-network-2/ ) sobre el motor de base de datos que mejor se adecúa a la misma, resultando que aunque es totalmente factible realizar un desarrollo de este tipo usando un producto SQL típico (MySQL, PosgreSQL, SqlServer, etc) no son muy adecuados para modelar y mantener relaciones del tipo indeterminado que implica nuestro caso. Así como alternativas se optan por motores NoSQL tipo CouchDB o MongoDB, o por motores de grafos como Neo4j.

Del resultado de la misma optamos por utilizar Neo4j la cual entre otras cualidades nos permite usar una versión embebida en nuestra aplicación o una remota accesible mediante servicios REST. Además Grails tiene un plugin que nos permite utilizar cualquiera de estas dos, de tal forma que podremos usar la embebida en una primera versión y movernos a una remota en caso de necesidad.

Para la vista del aplicativo web utilizaremos el framework Angular 1.x el cual nos permitirá desarrollar lógica de negocio en la parte del cliente mientras dialoga con el backend en background solicitando recursos REST.

Así pues la arquitectura de la aplicación puede resumirse en:

  • motor de base de datos basado en grafos (Neo4j)

  • servicio REST (Grails) securizado

  • cliente web en Javascript (Angular)

Artefactos

Como se ha dicho anteriormente, esta versión será una aplicación web por lo que se deberá obtener al final del trabajo un artefacto (WAR) que pueda ser desplegado en un servidor de aplicaciones.

Además de este artefacto, y con cara a posibles evoluciones del aplicativo, otro elemento importante a generar será la documentación del API por lo que desde el inicio del proyecto se deberán articular las herramientas necesarias para que se genere y se mantenga actualizada.

Herramientas de desarrollo y despliegue

Un desarrollo ágil debe utilizar herramientas y técnicas que lo permitan. Con esta premisa, para este trabajo vamos a utilizar las siguientes herramientas:

  • Gradle como herramienta de automatización para la construcción de artefactos.

  • Control de versiones Git. En concreto usaremos Gitlab.com donde alojaremos todo lo relativo al proyecto (código, documentación, etc)

  • Infraestructura de despliegue. Se estudiarán diferentes alternativas como pueden ser OpenShift , Heroku, etc y según los resultados se optará por una u otra.

El código se encontrará accesible en https://gitlab.com/telotraigodemipueblo/tfg mientras que la documentación podrá ser consultada mediante un navegador en https://telotraigodemipueblo.gitlab.io/tfg

Riesgos

Aunque los frameworks y herramientas propuestos para el desarrollo de la solución cuentan con bastante tiempo en el mercado y son de reconocido prestigio, algunos de ellos no son de uso común como por ejemplo Neo4j por lo que habrá que realizar pruebas de modelado al inicio para confirmar su elección y en caso de no adaptarse poder optar por alternativas.

Por otra parte corremos el riesgo de intentar definir con mucho detalle ciertos casos de uso que consuman demasiado tiempo de desarrollo y que nos impidan completar otros por lo que las pantallas de interacción con el usuario deberán ser lo suficientemente completas como para validar la funcionalidad pero no tan complejas que requieran demasiado esfuerzo.

Planificación

El desarrollo del producto debe adaptarse al calendario de entregas propio del TFG tal que en las fechas propuestas por el mismo se hayan alcanzado los hitos propuestos.

Hito Fecha Descripcion

PAC1

5/10/2016

Definición del proyecto.

PAC2

9/11/2016

Requerimientos funcionales.

PAC3

23/12/2016

Implementación.

PAC4

12/01/2017

Memoria final.

Para ello, y teniendo en cuenta que deseamos utilizar una metodología ágil, debemos establecer un calendario de sprints que permita cumplir con los hitos previos. Se establece como primera aproximación la siguiente planificación:

Sprint Fecha Inicio Descripcion

1

3/10/2016

Aprovisionamiento de infraestructura y depliegue contínuo.

2

10/10/2016

Diseño modelo de Negocio mediante tests.

3

17/10/2016

HU1 HU2.

4

31/10/2016

HU6 HU7 HU8 HU9.

5

14/11/2016

HU3 HU4 HU5.

6

28/11/2016

HU10 HU11 HU12.

7

12/12/2016

HU13 HU14 HU15 HU16.

8

2/1/2017

Memoria y Presentación.

Cada sprint consta de un período de 15 días en el cual se revisará el trabajo realizado en el anterior sprint para evaluar si la estimación ha sido correcta, tanto en exceso como en defecto, para poder tomar las medidas necesarias. Así mismo se realizará una revisión del trabajo a realizar.

Hito 2 (PEC2)

La PEC2 consiste en la entrega de un documento donde se detalle un análisis del sistema junto con los componentes, diagramas de secuencia, etc. En nuestro caso además incluiremos en el mismo, los pasos dados de cara a poder disponer de un proceso de entrega contínua (CD) en todos los aspectos del producto (entregable, documentación del proyecto y documentación del API generado)

En el documento "PEC2" se recogen en un único punto los apartados que se detallan a continuación:

Análisis funcional

Consultar el documento: "Análisis funcional"

Casos de uso

  • Actores Principales

actores
  • Registro

casos de uso registro
  • Identificación

casos de uso login
  • Búsquedas

casos de uso busqueda
  • Mi Red

casos de uso network
  • Lugares y productos

casos de uso crud

Componentes

En esta fase realizamos una definición de componentes de alto nivel donde distinguimos un cliente que comunicará con diferentes partes del API, las cuales a su vez delegarán en los servicios oportunos la resolución de la petición. Todos los servicios utilizarán el mismo repositorio (Neo4j).

diagrama

Diagrama de Secuencias

A continuación se representan los tres diagramas de secuencia principales de la aplicación.

Diagrama de secuencia donde un usuario anónimo desea registrarse en el sistema. Al no estar registrado el API no puede securizarse mediante el intercambio de tokens

secuencia register

Diagrama de secuencia donde un usuario anónimo desea identificarse en el sistema. Si la identificación es correcta obtendrá un token para usar en futuras peticiones

secuencia login

Diagrama de secuencia donde un usuario identificado previamente y que disponde de un token, desea acceder a un recurso protegido (por ejemplo ver sus mensajes)

secuencia login

Objetos de Dominio

  • Usuario

Un Usuario es un elemento central del modelo de dominio a definir. En él recogemos los datos personales del usuario y sus relaciones con los demás elementos del modelo.

Usuario.groovy
package ttp
import grails.persistence.Entity
import grails.rest.Resource

@Entity

class Usuario {

    String nombre       (1)
    String username
    String password

    boolean enabled = true
    boolean accountExpired
    boolean accountLocked
    boolean passwordExpired

    static hasMany = [          (2)
            confia : Usuario,
            conoce : Lugar
    ]

    Set<Role> getAuthorities() {
        UserRole.findAllByUser(this)*.role
    }

    def beforeInsert() {
        encodePassword()
    }

    def beforeUpdate() {
        if (isDirty('password')) {
            encodePassword()
        }
    }

    protected void encodePassword() {
        password = springSecurityService?.passwordEncoder ? springSecurityService.encodePassword(password) : password
    }

    transient springSecurityService

    static transients = ['springSecurityService']

    static constraints = {          (3)
        nombre nullable:false
        username nullable: false, email:true
        password nullable:false, password:true
    }

    static mapping = {              (4)
        username index:true, unique:true
    }


    Usuario amigos(Usuario amigo){ (5)
        this.addToConfia(amigo)
        amigo.addToConfia(this)
        this
    }

}
1 Definimos propiedades de la entidad
2 Definimos relaciones con otras entidades que gestionará Grails
3 Podemos indicar que restricciones tiene nuestra entidad
4 Ajustamos nuestro modelo al motor
5 Podemos incluir funciones en una entidad que nos ayuden a centralizar la lógica

Entidad donde cada usuario puede geolocalizar un punto de interés

Lugar.groovy
package ttp
import grails.persistence.Entity

@Entity
class Lugar {

    String nombre
    float longitud
    float latitud

    static belongsTo = [usuario:Usuario]

    static hasMany = [
            recibe : Viaje,
            tiene : Producto
    ]

    static mapWith = "neo4j"

    static constraints = {
        nombre nullable:false
    }

    static mapping = {
        nombre index:true
    }
}
  • Producto

Donde cada usuario detalla qué es típico de un lugar

Producto.groovy
package ttp

import grails.converters.JSON
import grails.persistence.Entity

@Entity
class Producto {

    String texto
    double precio

    static mapWith = "neo4j"

    static belongsTo = [lugar : Lugar]

    static constraints = {
        texto   nullable: false, maxLength:500
    }

    static mapping = {
        dynamicAssociations true
    }

}
  • Viaje

Entidad por la que un usuario avisa a su red de que va a viajar a un lugar en una fecha determinada

Viaje.groovy
package ttp
import grails.persistence.Entity

@Entity
class Viaje {

    String  texto
    Date    fechatope
    Date    vuelvo

    static belongsTo = [ lugar : Lugar]

    static hasMany = [pedidos:Pedido]

    static mapWith = "neo4j"

    static constraints = {
        texto   nullable: false, maxLength:500
        fechatope nullable: false
        vuelvo  nullable: false
    }

    static mapping = {
    }
}
  • Mensaje

Entidad destinada a permitir el diálogo entre usuarios

Mensaje.groovy
package ttp
import grails.persistence.Entity

@Entity
class Mensaje {

    String tipo = TipoMensaje.MENSAJE
    String texto
    Date    enviado= new Date()
    Date    leido = null
    Usuario remitente

    static hasMany = [destinatarios:Usuario]

    void setRemitente(Usuario usuario){
        this['REMITENTE'] = [usuario]
    }

    Usuario getRemitente(){
        this['REMITENTE']
    }

    Mensaje addToDestinatarios(Usuario usuario){
        List destinatarios = this['DESTINATARIOS'] ?: []
        destinatarios.add usuario
        this['DESTINATARIOS'] = destinatarios
        this
    }

    Mensaje responde(Mensaje mensaje){
        List respuestas = this['RESPONDE'] ?: []
        respuestas.add mensaje
        this['RESPONDE']=respuestas
        this
    }

    static mapWith = "neo4j"

    static transients = ['remitente']

    static constraints = {
        tipo    blank:false
        texto   nullable: false, maxLength:500
        enviado nullable: false
        leido   nullable:true
    }

    static mapping = {
        dynamicAssociations true
        leido index:true
    }
}
  • Pedido

Creado por un usuario amigo donde nos solicita un producto

Pedido.groovy
package ttp

import grails.persistence.Entity

@Entity
class Pedido {

    Producto producto

    int cantidad

    Usuario solicitante

    static mapWith = "neo4j"

    static belongsTo = Viaje

    static constraints = {
    }

    static mapping = {
        dynamicAssociations true
    }
}

Aprovisionamiento de infraestructura

Una vez establecidas las líneas generales del proyecto y con una idea sobre qué herramientas y tecnología vamos a trabajar procedemos a aprovisionar aquellos recursos que necesitaremos para realizar un ciclo completo inicial. La idea es conseguir, de una forma rápida, un pipeline completo desde el desarrollo hasta el despliegue que nos ayude a identificar todos los elementos que intervendrán y así reducir riesgos.

En nuestro caso, para el desarrollo y de cara a infraestructura, vamos a necesitar:

  • un repositorio de códigos y artefactos accesible desde diferentes sitios (Gitlab)

Así mismo para el despligue requeriremos:

  • registrar un nombre de dominio

  • proveedor de cuentas de correo.

  • un servidor de aplicaciones accesible desde Internet (OpenShift, Heroku, ..)

  • un servidor de base de datos Neo4j. Crearemos uno desde cero o usaremos servicios como GrapheneDB que permiten crear una base de datos Neo4j para pruebas de concepto.

Dominio y correo

El registro de un dominio nos permite principalmente tener presencia en Internet de nuestro producto. Hoy en día existen sufijos de dominio (.com, .es, .info, etc) por unos 12 euros pero recientemente se han creado nuevos sufijos que nos permiten registrar nuestro nombre por menos de 1 euro. En nuestro caso el dominio registrado sera http://telotraigodemipueblo.club

La mayoría de proveedores de dominios suelen ofrecer planes donde incluyen un espacio para alojar contenido estático y alguna cuenta de correo. Mientras que el contenido estático para nuestro caso no reporta grandes ventajas, el poder disponer de alguna cuenta de correo nos va a permitir poder acceder a servicios de infraestructura PaaS, SaaS, IaaS, etc y asociarlo al mismo, de tal forma que podremos disponer de un repositorio de código Git, instancias donde correr la aplicación, etc (si bien hay que tener en cuenta que algunos de ellos no ofrecerán capacidad como para desplegar nuestro producto al mercado sino más bien a validar la idea de negocio).

Repositorio de código Git

Hoy en día el sistema por excelencia para el control del código es sin duda Git, por encima de Subversion, Mercurial, etc.

Git puede ser instalado de una manera fácil en un equipo alojado en nuestra propia red (incluso en el mismo equipo que usamos para trabajar) aunque existen proveedores que ofrecen este servicio de forma gratutita o a un precio asequible. La ventaja que ofrecen estos servicios no es sólo que nos evitamos el tener que instalar y mantener el sistema sino la posibilidad de dar visibilidad a nuestro código a la comunidad permitiendo así tener feedback e incluso colaboraación de la misma.

Como servicios principales podemos destacar a:

  • Bitbucket, ofrece alojamiento gratuito para equipos de menos de 5 miembros.

  • Github, ofrece alojamiento gratuito para proyectos OpenSource

  • Gitlab, igual que los anteriores pero también permite crear repositorios privados con un límite de espacio.

Además del servicio básico de repositorio de código suelen incluir herramientas de gestión de incidencias, procesos de Integración Contínua (CI), generación de páginas estáticas (útiles para documentar el proyecto), etc.

Para este proyecto hemos seleccionado Gitlab básicamente por experiencias anteriores positivas aunque cualquiera de los anteriores hubieran sido válidos.

Servidor de aplicaciones

Debido a que nuestro proyecto será una aplicación J2EE Grails debemos buscar proveedores que permitan el despliegue de aplicaciones de este tipo, lo cual no es fácil. A diferencia de aplicaciones PHP (por ejemplo) los requisitos de un servidor J2EE son mayores por lo que los proveedores habituales no ofrecen este servicio.

Aunque desactualizada, la página https://grails.org/wiki/hosting nos proporciona un listado de proveedores que ofrecen servicio de alojamiento para este tipo de aplicaciones. Sin embargo de todos ellos los únicos que proporcionan un plan free son:

  • Heroku, ofrece una aplicación free con 512 Mb de memoria y con un sistema integrado en Git de despliegue. Para probar este servicio se ha creado un aplicación Grails de prueba que se encuentra en el directorio "testheroku" de este proyecto.

  • Cloudbees ofrece el mismo servicio pero con sólo 128 Mb de memoria las cuales son insuficientes para una aplicación mínima.

Así mismo, y con la madured de la tecnología de la "Nube" existen proveedores que nos ofrecen crear máquinas virtuales donde alojar nuestras aplicaciones con unos requisitos mínimos como pueden ser:

  • Amazon Web Services (AWS), ofrece un año de prueba gratuito en casi todos sus productos, incluido una instancia EC2. Sin embargo la máquina que se permite en dicho plan es realmente escasa y deberíamos optar a una instancia superior, aunque a un precio muy económico.

  • OpenShift de RedHat. Hasta hace poco ofrecía un servicio en su version 2 donde podíamos aprovisionar hasta 3 aplicaciones de forma gratuita. Sin embargo dicho plan se encuentra en proceso de desaparición por el nuevo plan 3 basado en Docker. Aún así se ha probado dicho plan con una instancia DIY (DoItYourself) donde hemos podido desplegar una aplicación Grails para probar el proceso de despliegue. Dicha aplicación se encuentra en el directorio "testopenshift" de este proyecto. La idea básica para realizar una integración contínua en este contenedor reside en los ficheros que se encuentran en el directorio .openshift y que actuan como "hooks"

Tras evaluar las diferentes posibilidades la que mejor se ha adaptado a nuestro proyecto ha sido Heroku la cual nos ha permitido desplegar la aplicación sin mayores complicaciones en un tiempo corto y de forma integrada en nuestro pipeline. Básicamente la idea de Heroku es que una vez que realizamos un push en la rama "heroku" de nuestro proyecto se lanza un deploy del mismo y si el resultado es satisfactorio se reemplaza la instancia en poco más de un minuto. Para ello debemos incluir un fichero Procfile que le indica el tipo de proyecto , y el comando a ejecutar para desplegar nuestra aplicación.

Proveedor Neo4j

Al ser Neo4j un motor de base de datos un tanto atípico, encontrar una solución donde alojarle resulta un tanto problemática. Actualmente multitud de servicios de hosting ofrece MySql, PostgreSQL, o similares de forma prácticamente gratuita y con recursos más que suficientes para desarrollar un producto listo para el mercado.

Así pues la elección de Neo4j en un primer momento ha sido desplegar una instancia en alguno de los proveedores citados anteriormente. De esta forma hemos conseguido crear una instancia en OpenShift donde poder alojar un motor de Neo4j pero a costa de demasiado esfuerzo (gestión de puertos, paradas y arranques, etc)

La segunda elección ha sido optar por un proveedor de Neo4j, GrapheneDb que ofrece un plan gratuito orientado al desarrollo de prototipos donde alojar hasta 1.000 nodos y 10.000 relaciones, y con interface REST lo que nos permitirá conectar nuestra aplicación alojada en Heroku dialogar con la base de datos alojada en GrapheneDb.

El proyecto testheroku incluye algunas clases de Dominio así como un Controller y test de integración, destinados a validar dicha arquitectura.

Base de datos de Grafos

Conceptos básicos

El diseño del modelo de datos en una aplicación de grafos como es Neo4j difiere del diseño tradicional de una base de datos relacional.

En una base de datos de grafos las entidades se identifican como nodos con atributos que pueden tener un número indeterminado de relaciones entre sí. Por ejemplo en el siguiente diagrama podemos ver:

  • entidad Usuario (4 nodos verdes)

  • entidad Mensaje (4 nodos rojos)

  • entidad Lugar (8 nodos azules)

  • relaciones diferentes entre nodos (remitente, destinatario, usuario) que nos permiten navegar entre ellos

Ejemplo de nodos y sus relaciones

Así mismo la forma de consultar a la base de datos difiere de la tradicional SQL. En este tipo de motores la consulta básica se realiza mediante "MATCH":

MATCH (n) return n  (1)
MATCH (n:Usuario) return n  (2)
MATCH (n:Usuario {nombre:'name'}) return n (3)
MATCH (n:Usuario {nombre:'name'})-[:VISITO]->(l:Lugar) return n,l (4)
1 retorna todas las entidades de la bbdd
2 retorna todas las entidades del tipo Usuario
3 retorna las entidades del tipo Usuario con el atributo nombre='name'
4 retorna un usuario y todos los lugares con los que tiene una relacion de 'VISITO'

Grails y Neo4j

Para manejar nuestro modelo de datos utilizaremos el plugin de Grails Neo4j el cual nos facilitará la creación de las entidades, sus relaciones y consultas.

De esta forma nuestro trabajo consistirá en definir nuestras entidades programáticamente y delegar en dicho plugin la gestión de las mismas creando una clase Domain.groovy en la carpeta domain

Así por ejemplo para definir una entidad de dominio Usuario la definiríamos en el propio código:

Usuario.groovy
package ttp
import grails.persistence.Entity
import grails.rest.Resource

@Entity

class Usuario {

    String nombre       (1)
    String username
    String password

    boolean enabled = true
    boolean accountExpired
    boolean accountLocked
    boolean passwordExpired

    static hasMany = [          (2)
            confia : Usuario,
            conoce : Lugar
    ]

    Set<Role> getAuthorities() {
        UserRole.findAllByUser(this)*.role
    }

    def beforeInsert() {
        encodePassword()
    }

    def beforeUpdate() {
        if (isDirty('password')) {
            encodePassword()
        }
    }

    protected void encodePassword() {
        password = springSecurityService?.passwordEncoder ? springSecurityService.encodePassword(password) : password
    }

    transient springSecurityService

    static transients = ['springSecurityService']

    static constraints = {          (3)
        nombre nullable:false
        username nullable: false, email:true
        password nullable:false, password:true
    }

    static mapping = {              (4)
        username index:true, unique:true
    }


    Usuario amigos(Usuario amigo){ (5)
        this.addToConfia(amigo)
        amigo.addToConfia(this)
        this
    }

}
1 Definimos propiedades de la entidad
2 Definimos relaciones con otras entidades que gestionará Grails
3 Podemos indicar que restricciones tiene nuestra entidad
4 Ajustamos nuestro modelo al motor
5 Podemos incluir funciones en una entidad que nos ayuden a centralizar la lógica

Ejemplos de diagramas de nodos

Ejemplo de una red de amigos donde dos de ellos tienen previsto viajar a lugares diferentes:

Ejemplo de nodos y sus relaciones

Ejemplo de una consulta donde dado un usuario 'nombre' podemos ver los viajes de su red de amistades (extraído del ejemplo anterior):

Lista de viajes de mis contactos

Despliegue contínuo

Mediante el Despliegue Contínuo lo que se busca es poder detectar los fallos cuanto antes y de una forma lo más automatizada posible. Si un simple error en una línea es detectado al instante, podremos actuar inmediatamente sin tener que esperar a días o semanas donde sería más difícil relacionar el error.

Para nuestro proyecto hemos diseñado el siguiente pipeline:

  • separación en dos proyectos diferentes la generación de la documentación y el proyecto en sí

  • uso de dos repositorios Git diferentes ( Gitlab y Heroku ). En el primero se realizarán los procesos de test de integración y si son correctos se actualizará el segundo repositorio.

  • uso de diferentes ramas en Git que permitan la evolución del código sin necesidad de desplegar a real hasta que no se esté listo (no se utiliza git-flow de master/develop/features en profundidad)

  • activación de ejecuciones remotas según commit en ciertas ramas. Así un commit en el master de Gitlab provocará que se ejecuten todos los test de integración contra la base de datos de test, mientras que ese mismo commit en el master de Heroku provocará que el aplicativo se despliegue en sus infraestructuras.

  • como caso particular, se ha creado un pipeline sobre la rama publish que permite generar la documentación a entregar sin necesidad de realizar los test de integración.

Hito 3 (PEC3)

En la planificación de la asignatura el Hito 3 corresponde a la codificación del proyecto. Gracias al enfoque de integración contínua desarrollada hasta ahora, nos encontramos con que una parte de dicha codificación se encuentra realizada e incluida en un pipeline que permite hasta el despliegue en real de los cambios.

Así por ejemplo contamos con los casos de uso de registro, login, sistema de mensajería básica, etc. Disponemos también de un conjunto de Specificacion (test unitarios y de integración) que no sólo nos valida la API del aplicativo sino que nos permite generar una documentación actualizada de la misma.

Sin embargo hasta este punto la parte cliente (Angular+Javascript+HTML) no ha sido explorada con suficiente profundidad por lo que deberemos esperar situaciones no contempladas en los test así como afrontar revisiones del API tanto en sus EndPoints como en los parámetros de envío y de recepción a medida que avancemos en la codificación de esta parte. Estos cambios en el API volverán a ser testeados de forma automática por el sistema y nos avisarán de cualquier cambio en el contrato de aquél.

De forma general cada caso de uso se desarrollará siguiendo los siguientes pasos:

  • primera definición de una especificación que sirva para poder testear el modelo de Dominio. Este test no necesita de la infraestructura de documentación ni hacer uso del interface Rest, etc. Simplemente nos ayuda en modelar el objeto de Dominio junto con sus relaciones así como a buscar la forma idónea para consultar y actualizar el objeto.

  • segunda definición de una especificación que sirva para testear el caso de uso en cuestión. Esta especificación se desarrollará con vistas a que sirva para documentar el API Rest por lo que su comunicación con el aplicativo será a través de este protocolo y donde haremos uso de elementos comunes (funciones de login, campos de documentación existentes, etc).

  • desarrollo de un Controller que implemente el caso de uso y contra el que probaremos usando la especificación anterior. En la mayoría de los casos este Controller extenderá de RestController proporcionado por el framework.

  • iteraciones sucesivas hasta que los test definidos sean correctos.

  • creación de la parte Cliente (AngularJS) junto con un el interface HTML. En este punto el API debería responder a las necesidades del cliente JS pero debemos esperar diferentes comportamientos que puedan llevar a tener que modificar el controller y con ello tener test erróneos. Así por ejemplo el caso más llamativo se produce al utilizar los IDs de objetos proporcionados por Neo4j los cuales exceden de la capacidad de Javascript si los tratamos como número.

Así mismo iremos realizando commit y subidas del código al repositorio para que los procesos automáticos realicen el testeo en el entorno CI así como que generen la documentación ( informes de test, API, etc)

Entorno de desarrollo

Para la gestión del proyecto (compilado, dependencias, despliegue, etc) utilizaremos http://gradle.org

Gradle es similar a Maven en el sentido de que nos proporciona herramientas para organizar nuestros proyectos, declarar las dependencias de los mismos, etc.

En nuestro caso la estructura del proyecto será una estructura de multiproyecto donde tenemos un proyecto principal vacío que simplemente declara dependencias a los subproyectos.

Subproyecto docs

El proyecto docs es un proyecto donde hacemos uso del plugin asciidoctor de gradle (entre otros) para que al ser invocado se genere la documentación tanto HTML como Pdf. Esta documentación hace referencia a las diferentes entregas del TFG, como es la planificación, hitos, memoria, etc

Dicha documentación se encuentra estructura en múltiples ficheros .asciidoc para poder ser reutilizados tanto a la hora de generar un HTML como a la hora de generar los Pdfs a entregar siendo el documento src/docs/asciidoc/index.adoc el fichero principal para la parte HTML y los ficheros src/docs/asciidoc/pec2.adoc y src/docs/asciidoc/pec3.adoc ficheros principales para la generación PDF.

Cuando se invoca la tarea build, este proyecto ejecuta dos tareas (buildHtml y buildPdf) que generan un HTML index.html y diferentes PDFs, todos ellos en la carpeta de salida buid/asciidoctor. Dicha carpeta será utilizada para su publicación en las páginas públicas de Gitlab haciendolos accesibles por Internet.

Subproyecto telotraigodemipueblo

Este proyecto corresponde al aplicativo a generar y contiene básicamente el código groovy a generar junto con los test de integración para asegurar la calidad del software.

Cuando se invoca la tarea build en este proyecto se ejecuta todo el pipeline propio de Grails donde se pasan por las fases propias de compilado, ensamblado, test de integración, y generación del producto final. Este producto final es utilizado por la herramienta de despliegue de Heroku para reemplazar la versión actual por la nueva de forma automática.

Subproyecto api

Este proyecto en realidad es un proyecto "virtual" en el sentido de que no existe como tal sino que es un proyecto creado en Gitlab con el nombre api para disponer de una URL donde poder publicarla. Cuando se hace un versionado de la aplicación se ejecuta un trigger que descarga la última versión del proyecto y ejecuta los test los cuales a su vez generan la documentación del API lista para ser publicada en http://telotraigodemipueblo.gitlab.io/api

Subproyecto reports

Al estilo del anterior, este proyecto también es un proyecto "virtual" con la particularidad de que, a diferencia del anterior, permite errores en los test pues está destinado a generar un report de los test tanto satisfactorios como erróneos en http://telotraigodemipueblo.gitlab.io/reports

Database (Neo4j)

La persistencia de la aplicación se hace enteramente sobre un motor Neo4j (base de datos de grafos, diferente a la tradicional relacional). Dicho motor puede ser instalado siguiendo el tutorial de la página oficial https://neo4j.com/download/ o bien si tenemos Docker instalado podemos usar la imagen oficial https://hub.docker.com/_/neo4j/ .

Así mismo http://www.graphenedb.com/ ofrece alojamiento gratuito donde crear instancias de Neo4j aunque limitadas a un número de nodos y relaciones (suficientes para el objetivo de este proyecto). Tras probar las diferentes opciones al final se ha optado por utilizar este servicio por las siguientes razones:

  • aunque ofrece un número limitado de nodos y relaciones son suficientes para poder mostrar la funcionalidad del aplicativo

  • accesible desde cualquier estación de trabajo con conexión a Internet, lo que permite el desarrollo en diferentes sitios incluso simultáneos

  • fácil de instalar (sólo requiere de una cuenta de correo para confirmar las credenciales) y de administrar.

Gracias a que GrapheneDB nos permite crear varias bases de datos (todas con la misma limitación de nodos) se han creado tres instancias:

  • telotraigodemipueblo_dev, para el entorno de desarrollo

  • telotraigodemipueblo_ci, utilizada por los test de integración y despligeue contínuo

  • telotraigodemipueblo, utilizada por el entorno de real

A continuación se detalla la configuración necesaria para el entorno de desarrollo y de test:

${HOME}/.gradle/gradle.properties
NEO4J_URL_DEV=http://hobby-pdjgpmbeoeaggbkeccahdkol.dbs.graphenedb.com:24789/db/data/
NEO4J_USER_DEV=telotraigodemipueblo_dev
NEO4J_PWD_DEV=XXXXXXXXXXXXXX  (1)

NEO4J_URL_TEST=http://hobby-ocnnamhijildgbkeiaigdgol.dbs.graphenedb.com:24789/db/data/
NEO4J_USER_TEST=telotraigodemipueblo_ci
NEO4J_PWD_TEST=XXXXXXXXXXXX (1)
1 Configurar la password correspondiente

En el entorno de producción (Heroku) se han configurado las variables correspondientes al entorno de producción mediante el interface que proporciona dicha plataforma.

NEO4J_URL=http://hobby-xxxxxxxxxxx.dbs.graphenedb.com:24789/db/data/
NEO4J_USER=telotraigodemipueblo_dev
NEO4J_PWD=XXXXXXXXXXXXXX  (1)
1 Configurar la password correspondiente

Grails

Para el backend hemos usado Grails ( http://www.grails.org ) como framework de desarrollo. Grails nos proporciona un entorno donde la convención prevalece sobre la configuración de tal forma que si seguimos las convenciones establecidas (nombre, rutas, etc) prácticamente no tendremos que realizar ninguna tarea de configuración.

Así mismo Grails proporciona todo un stack J2EE ( spring-framework, hibernate, sitemesh, etc ) junto con un ecosistema de plugins muy amplio destinado a proporcionar un desarrollo muy rápido.

Por último comentar que Grails se basa en el lenguaje Groovy, el cual es un lenguaje dinámico que corre sobre una JVM y que cuenta con una gran popularidad actualmente.

Respecto de nuestra aplicación, a continuación se describen los artefactos de interés:

  • grails-app

    • controllers

      • telotraigodemipueblo.UrlMappgings: configuración de puntos de entrada a los diferentes controllers

      • telotraigodemipueblo/api/core: Controllers de uso básico (registrarse, mi perfil, invitar a unirse, etc)

      • telotraigodemipueblo/api/crud: Controllers orientados al CRUD de diferentes recursos (lugares, productos,etc) relacionados con un usuario logeado

      • telotraigodemipueblo/api/network: Controllers destinados a interconectar a un usuario con su red (hacer un pedido, ver viajes en mi red, etc)

    • domain

      • ttp: Objetos de dominio con etiquetas necesarias para la persistencia. Siguiendo las convenciones de Grails las propiedades de estos serán persistidas en el motor de datos.

    • views: Siguiendo las conveciones de Grails cada carpeta está destinada a renderizar los diferentes objetos en formato json

    • services

      • telotraigodemipueblo/EventToMessageService: Servicio destinado a recibir en un solo punto los eventos que genera la aplicación (como por ejemplo LugarCreado, PedidoSolicitado, etc) y convertirlos en Mensajes hacia los usuarios interesados.

  • src

    • integration-test/groovy/ttp

      • domain: Test de integración (Spock Framework) destinados a validar las querys básicas de los objetos de dominio.

      • docuapi: Test de integración (Spock Framework) destinados a validar las diferentes APIs. Estos test son usados así mismo para generar la documentación del API creando cada uno de ellos fragmentos de documentación relativos a la petición REST (parámetros de envío, cabeceras, respuesta esperada, etc). En caso de que un test falle o no la respuesta recibida no coincida con la espera se aborta la generación del aplicativo. Debido a que estos test se ejecutan a través de HTTP contra el propio servidor se han desarrollado una serie de utilidades que nos permitan realizar la autentificación, crear elementos para pruebas, etc.

  • plugins: en el fichero build.gradle definimos los plugins necesarios para nuestra aplicación. En concreto para TelotraigodemiPueblo hemos añadido "org.grails.plugins:spring-security-rest:2.0.0.M2" (para securizar las llamadas al API), 'org.springframework.data:spring-data-neo4j-rest:3.4.6.RELEASE' (para conectar con una base de datos Neo4j remota), y "org.springframework.restdocs:spring-restdocs-core:$springRestdocsVersion" (para generar la documentación del API)

Cliente (Javascript+HTML con AngularJS)

Para la parte cliente hemos utilizado el framework Javascritp Angular 1.5 el cual nos permite por un lado una interacción con el cliente y por otro nos ofrece funcionalidades de comunicación con el backend vía REST.

Respecto de nuestra aplicación, a continuación se describen los artefactos de interés:

  • grails-app

    • assets/javascripts/telotraigodemipueblo

      • core: Módulo AngularJS donde definimos componentes de uso genérico como el buzón del usuario, el perfil de este, y los Resource mapeados con los diferentes REST del backend

      • index: Módulo AngularJS donde definimos componentes de inicio, como la bienvenida, registro y login

      • network: Módulo AngularJS donde definimos componentes de gestión de la red, como la búsqueda de usuarios o los viajes de mis amigos

Para cada módulo organizamos los componentes de la misma forma:

  • controllers: donde ubicamos los controllers característicos de Angular

  • domain: donde mapeamos los Resouces REST

  • templates: donde diseñamos los componentes HTML

Grails nos permite crear test de la parte cliente pero para esta fase se han suprimido por no complicar más el desarrollo.

API REST

Durante la preparación de los test de integración se realizará la documentación del API de tal forma que podrá ser accesible de forma online ( https://telotraigodemipueblo.gitlab.io/api )

Al utilizar los propios test de integración para la generación de la documentación nos aseguraremos que esta siempre esté actualizada pues si no se ejecutan correctamente los primeros la segunda no se genera.

Test de Integración

Los test de integración se ejecutan automáticamente ante cada commit en la rama master y pueden consultarse en https://telotraigodemipueblo.gitlab.io/reports

Glosario de términos

MVP

Minimum Viable Product. La versión de un nuevo producto que permite a un equipo recolectar, con el menor esfuerzo posible, la máxima cantidad de conocimiento validado sobre sus potenciales clientes. (https://es.wikipedia.org/wiki/Producto_viable_m%C3%ADnimo)

API

Application Programming Interface. Conjunto de subrutinas, funciones y procedimientos (o métodos, en la programación orientada a objetos) que ofrece cierta biblioteca para ser utilizado por otro software como una capa de abstracción (https://es.wikipedia.org/wiki/Interfaz_de_programaci%C3%B3n_de_aplicaciones)

REST

Transferencia de Estado Representacional Estilo de arquitectura software para sistemas hipermedia distribuidos (https://es.wikipedia.org/wiki/Representational_State_Transfer)

Backlog

Es el conjunto de todos los requisitos de proyecto, el cual contiene descripciones genéricas de funcionalidades deseables (https://es.wikipedia.org/wiki/Scrum_(desarrollo_de_software)#Product_backlog)

Sprint

El Sprint es el período en el cual se lleva a cabo el trabajo en sí (https://es.wikipedia.org/wiki/Scrum_(desarrollo_de_software)#Sprint)

Sprint backlog

subconjunto de requisitos que serán desarrollados durante el siguiente sprint (https://es.wikipedia.org/wiki/Scrum_(desarrollo_de_software)#Sprint_backlog)

Groovy

Lenguaje de programación dinámico para la máquina virtual Java. http://www.groovy-lang.org/

Grails

Framework basado en Groovy que aúna diferentes librerías para el prototipado rápido de aplicaciones https://grails.org/

Grafo (Base de datos)

"Una base de datos orientada a grafos (BDOG) representa la información como nodos de un grafo y sus relaciones con las aristas del mismo …​" https://es.wikipedia.org/wiki/Base_de_datos_orientada_a_grafos

Agradecimientos

Prácticamente estoy terminando una etapa que inicié hace ya unos años y en la que he tenido la oportunidad de aprender de muchas personas tanto docentes como alumnos y sería injusto nombrar a unos y olvidarse de otros, por lo que creo que me limitaré a mostrar mi gratitud a una sóla persona de ellas con la convicción de que el resto lo entenderán:

Quiero agradecer a Antonio Cauto, mi tutor durante todos estos años, su apoyo contínuo en esta andadura. Estoy seguro que sin él y sus consejos, hace tiempo que habría pospuesto esta aventura de forma indefinida.

Tribunal

  • El proyecto ha sido desarrollado bajo la plataforma Java EE Grails, nos gustaría preguntar que te ha hecho escoger Grails? Que ventajas/inconvenientes tiene? Que alternativas valoraste o piensas que tenias para las funcionalidades a implementar en el proyecto?

Hace varios años buscaba una alternativa más ágil para el desarrollo de aplicaciones J2EE que las que se estaban usando en ese momento, (Spring, Spring MVC, Struts2 , JSP, etc) demasiado exigentes en ficheros de configuración XML, sin posiblidad de recargar código sin tener que reiniciar la aplicación, etc. Tras un primer intento de aproximación a Ruby on Rails descubrí Grails que ofrecía las características de este pero en un lenguaje (Groovy) más cercano a Java el cual conocía.

Desde aquel momento he usado este framework en todos los proyectos que he tenido oportunidad y desde el principio del TFG intenté que así fuera en este también.

Grails cuenta con numerosas características que le convierten en un candidato a tener en cuenta en el desarrollo de aplicaciones web (tanto típicas cliente-servidor HTML como backend de servicios REST):

  • Basado en Groovy, un lenguaje JVM dinámico que reduce la verbosidad del código (más alla de que no uses el punto y coma)

  • Basado en la convención sobre la configuración. Prácticamente no se necesita ningún fichero de configuración de dependencias, o similar. Los controllers van en la carpeta controllers, los servicios en services, las vistas en carpetas según el nombre del controller, etc

  • Recarga del código en caliente lo que reduce los tiempos de desarrollo y pruebas.

  • Un sistema ORM que añade dinámicamente métodos a las clases de Dominio para facilitar la persistencia (incluso en motores tan atípicos como Neo4j o MongoDB).

  • Un ecosistema de plugins numeroso y muchos de ellos muy buenos (security, security-rest, json, etc)

  • Una curva de aprendizaje realmente corta. Un programador con conocimientos de Java J2EE puede desarrollar una aplicación CRUD en cuestión de días.

  • En las últimas versiones (3.x) se ha integrado con SpringBoot por lo que ambos ecosistemas pueden compartir funcionalidades.

Como evangelizador de Grails pocos inconvenientes puedo apuntar aunque suele ser recurrente la opinión de que tiene demasiada "magia" interna. Todavía a muchos programadores les gusta escribir ficheros donde configurar los componentes pues les da la sensación de que son ellos los que controlan el sistema.

Probablemente como alternativa a Grails hubiera elegido desarrollar una aplicación REST con Spring Boot en sus versiones últimas. Existe mucha documentación y es realmente sencillo desarrollar controllers con este framework. Así mismo existen dos plugins vitales para el proyecto como son el security y neo4j aunque los correspondientes a Grails incluyen muchas más facilidades.

  • Nos gustaria que nos dieras una definición de que es un servidor de aplicaciones? En tu proyecto has utilizado Heroku tras un detallado estudio. Nos puedes comentar que cambios se deberían realizar si quisiérmaos utilizar otor servidor de aplicaciones? Nos podrias mencionar si existen diferencias exiten entre diferents servidores de aplicaciones, aparte de cuestiones económicas

En mi opinión, el concepto de servidor de aplicaciones se ha ido redefiniendo o dicho más coloquialmente "diluyendo" a medida que la tecnología J2EE ha ido madurando. En un principio existía una distinción entre servidor de aplicaciones y servidor web donde el primero estaba destinado a contener los artefactos comunes al negocio (EJB principalmente) y donde los conceptos de concurrencia, escalabilidad, etc estaban presentes mientras que el segundo estaba destinado a contener únicamente la vista (principalmente en JSP) y los proxys hacia los primeros. (Análogamente en el mundo Net las páginas web ASP se ejecutarían en un servidor web IIS mientras que los componentes se implementarían como componentes DCOM).

Sin embargo hoy en día los aplicativos destinados a correr nuestras aplicaciones no hacen tanta distinción y es común hablar de servidor de aplicaciones a una instancia Tomcat en la que no se despliega ningún componente de negocio.

Respecto del aplicativo TelotraigodemiPueblo aclarar que Heroku NO es ningún servidor de aplicaciones como tal. Es un proveedor de servicios en la nube, como pueden ser Amazon, Google, OpenShift, etc. Este proveedor (al igual que prácticamente el resto de los demás) nos permite desplegar nuestra aplicación en diferentes servidores de aplicaciones (Tomcat, Jetty, etc) o incluso en una implementación propia.

De hecho, en un primer momento el proveedor que evalúe fue OpenShift de RedHat, pero justo tras unas primeras versiones, este proveedor cambio el sistema de capa gratuita y no me aseguraban disponer de una cuenta a tiempo por lo que cambie a Heroku.

Así pues, propiamente hablando el aplicativo puede correr en su estado actual en cualquier servidor donde se ejecute Tomcat versión 7.x o superior. En principio al ser un WAR que cumplen las especificaciones J2EE podría ejecutarse en cualquier otro tipo de servidor como Jetty o Glassfish aunque probablemente habría que revisar las dependencias pues casi todos añaden alguna librería que puede provocar algún tema de incompatibilidad.

Por ejemplo para el caso de que quisieramos ejecutarlo en un Jetty el único cambio a priori que habría que realizar
es en el fichero build.gradle del subproyecto telotraigodemipueblo, línea 73 reemplazando.
provided "org.springframework.boot:spring-boot-starter-tomcat"
por
provided "org.springframework.boot:spring-boot-starter-jetty"

Los servidores de aplicaciones se diferencian básicamente en funcionalidades de administración, librerías que incorporan etc por lo que va un poco en gusto de cada cual la elección.

Respecto al proveedor que se elija (Heroku, Amazon, etc) a parte del tema económico existen diferencias entre ellos, si bien es verdad que todos tienden a implementar las funcionalidades de los demás antes o después.

Particularmente Heroku me ha gustado por su facilidad de despliegue del aplicativo. Simplemente realizar un commit en la rama adecuada dispara un proceso de validación y despliegue en diferentes entornos totalmente desatendido. Así mismo cuenta con un interface simple y muy cuidado orientado al programador, a diferencia por ejemplo del de Amazon donde está más orientado a sistemas.

  • ¿Qué conocimientos de las asignaturas cursadas en la UOC has utilizado en la realización del TFG? que ventajas valores que tiene una ingeniera informática en la realización de un proyecto respecto a la realización del mismo proyecto por una persona que no sea ingeniero informático? (sin tener en cuenta la experiencia profesional) ¿Qué valor añadido aporta ser ingeniero informático?

Varias son las asignaturas que he tenido presente durante la realización del TFG:

  • desde un punto de vista puramente técnico, la asignatura de "OOP" es fundamental y aunque la base de datos que he elegido no es la estudiada, la asignatura de "uso de bases de datos" aporta los conocimientos suficientes para entender el problema de las mismas. Así mismo "Ingeniería del Software" me ha ayudado mucho a la hora de formalizar los conceptos mediante los diferentes diagramas y técnicas, aunque la realización de las prácticas en grupo me permitió tener la primera toma de contacto con Git que ha sido vital para la buena marcha del proyecto.

  • de cara a la organización del proyecto destacaría en primer lugar la "Gestión de Proyectos" junto con la asignatura de "Ingenieria de Requisitos" para preparar las diferentes épicas y casos de uso así como entender la importancia de los test.

  • mención especial sería la asignatura de "Iniciativa Emprendedora" pues ha sido el germen de la idea para el TFG.

Obviamente siempre habrá personas que por sus capacidades intelectuales o circunstancias no requieran de unos estudios de ingeniería para realizar un TFG de estas características, pero en mi opinión lo que aporta una ingeniería informática es la visión global de lo que representa un proyecto donde NO importa únicamente el código que uno sea capaz de escribir sino otras dimensiones como pueden ser la calidad del software, análisis, documentación, etc.

Así pues, en mi opinión, un ingeniero informático lo que debe aportar a todo proyecto es su visión de conjunto. Obviamente se especializará en aquello que más le guste o sea capaz pero debería seguir teniendo esa capacidad de ver el todo.

  • Enumera cuáles son los puntos débiles de tu TFG y propon mejoras que puedan ser incluidas en una futura extensión. Te pido que seas auto-crítico.

Desde luego TelotraigodemiPueblo es un prototipo que en su estado actual no puede ser puesto en producción sin una profunda revisión. En esta revisión destacaría los siguientes puntos:

  • ahora que tenemos un flujo de trabajo completo (desde que se crea un viaje hasta que se aceptan pedidos, etc) y entiendo mejor la casuística sería importante realizar un análisis de cara a mejorar la experiencia de usuario, diseñando los elementos que ayuden al usuario. En este diseño descubriría componentes y los organizaría mejor pues ahora mismo son componentes muy "bastos" (por ejemplo el inbox mezcla conceptos de negocio diferentes, etc)

  • siguiendo con el interface gráfico buscaría un diseño más amigable y que utilice mejor la pantalla.

  • por la parte de backend lo primero que revisaría es el sistema de mensajería diseñado. En un primer momento pensé que con un único objeto de dominio Mensaje podría manejar todas las situaciones en las que un usuario podría comunicarse con su red, pero creo que o tendría que diferenciar en varios objetos de dominio (Mensaje, Invitación, SolicitudPedido, etc) o si uso un único objeto de dominio tipificarle mejor las situaciones en las que se usaría.

  • así mismo, el objeto de dominio Lugar es una aproximación que debería ser completado. Actualmente tiene longitud y latitud que sirven únicamente para demostrar que un lugar puede tener atributos pero habría que revisar qué atributos son necesarios

  • el API requiere de una revisión para unificar mejor los recursos que ofrece pues en diferentes puntos retornamos el mismo recurso pero no con los mismos atributos.

    • Indica los riesgos más importantes observados durante el desarrollo de tu TFG y que han dificultado el seguimiento de la planificación. Especialmente interesante es comentar la experiencia adquirida en este sentido aplicable a otros proyectos similares.

El riesgo principal (detectado desde el primer momento) era el uso de una base de datos grafos como Neo4j. Nunca había trabajado con ninguna de ellas y únicamente había leído alguna referencia sobre las mismas. Sin embargo en la literatura que había leído la indicaban como adecuada para una aplicación del tipo de TelotraigodemiPueblo por lo que decidí asumir el riesgo.

Al ser un riesgo alto, e identificado desde el principio, me reservé tiempo en la planificación para poder "jugar" con el modelo y poder experimentar y aunque fue muy extimulante tengo que admitir que me generó tensiones hasta que pude alcanzar un nivel suficiente de confianza.

Como mi intención era llegar a disponer de un aplicativo completo que estuviera accesible vía Internet, pero sin incurrir en gastos, corría el riesgo de que ningún proveedor de servicios (Heroku, AWS, etc) me ofreciera dicho servicio. Por suerte en el estado actual, el aplicativo tiene unos requisitos de memoria que se ajustan a los que requiere la capa gratuita. Si no hubiera sido así hubiera tenido que elegir entre provisionar unos fondos para contratar el servicio (unos 100-200 euros), sacrificar esta funcionalidad o montar un servidor de aplicaciones en casa utilizando la IP fija.

Por otra parte, durante el desarrollo del aplicativo y a pesar de haber aplicado una metodología TDD para el backend que me permitiera avanzar sobre código testeado me encontré con que los identificadores que maneja Neo4j son demasiados largos para Javascript por lo que la parte cliente demostraba unos comportamientos inesperados y erráticos que me llevo cierto tiempo detectar. Si hubiera aplicado dicha metodología para la parte cliente probablemente lo hubiera detectado a tiempo. Así pues, por lo que a mí respecta, he aprendido la necesidad de utilizar frameworks para testear esta parte.

Destacar por último que para la realización del proyecto he utilizado Git de una forma intensa lo cual podía haber sido un riesgo pues si no se tiene unos conocimientos mínimos puede provocar mucha confusión. Por suerte durante el año anterior, y tras realizar la asignatura de práctica en grupo, lo he utilizado de forma intensa y he podido aprovechar sus ventajas.

  • Comenta qué soporte haría falta y qué condiciones ideales (técnicas, económicas, etc.) se tendrían que dar, como también qué barreras principales prevés que haya que superar, para hacer posible la explotación correcta y completa en de la aplicación web que has desarrollado a una escala mayor (miles de usuarios, centenares de conexiones concurrentes y almacenamiento de recursos del orden de TB).

La aplicación está diseñada siguiendo un modelo stateless en el cual una vez que un usuario se ha identificado se le proporciona un JWT (Javascript Web Token) que debe usar para cada petición que realice al API. De esta forma el aplicativo NO requiere de sesiones por usuario por lo que por la parte backend puede escalar horizontalmente tanto como se necesite.

Respecto a la persistencia de los datos la conexión a la misma se realiza mediante un sistema idéntico vía REST por lo que su escalabilidad horizontal también está asegurada. Así mismo Neo4j cuenta con funcionalidades de alta disponibilidad , distribución entre máquinas, etc y todo ello aprovisionado por el propio proveedor de servicios con lo que reducimos necesidad de conocimientos técnicos específicos.

Gracias al modelo actual de los proveedores de servicio (Heroku y GrapeheDB en nuestro caso) de aprovisionamiento de infraestructura dinámico, se podría plantear un crecimiento en función de la demanda sin incurrir en gastos innecesarios.

Así pues, y tras una revisión del aplicativo de los puntos comentados en los puntos anteriores, creo que la explotación correcta de la aplicación no viene tanto por el lado técnico sino por el lado de negocio, definiendo cúal será el modelo a aplicar, es decir, de donde procederían los ingresos (publicidad de productos, comisión en los pedidos o por número de viajes, etc)

  • Indica las facilidades y dificultades encontradas en esta asignatura, a nivel de los recursos académicos y técnicos ofrecidos por la UOC para conducir tu TFG con éxito. Añade, si lo consideras necesario, sugerencias para mejorar el curso en este sentido. Finalmente, además de lo dicho en tus respuestas anteriores, te pido unas pocas lineas más con comentarios y sugerencias globales sobre tu recorrido por el Grado.

Respecto de los recursos académicos/técnicos en lo que respecta a mi TFG debo decir sinceramente que no los he usado (salvo el caso del @presenta para entregar el vídeo). Los materiales sobre edición de vídeo, cómo redactar un documento , etc los había trabajado ya en asignaturas anteriores por lo que no los he prestado mucha atención. Creo que el estudiante que llega a este punto de una forma u otra dispone de las habilidades/recursos y no creo que les preste mucha atención.

Desde mi punto de vista lo que peor he encajado ha sido el modelo "en cascada" que plantean las PECS. A grandes rasgos mi impresión es que la primera entrega debe ser un análisis, la segunda un diseño y la tercera la implementación con una par de semanas al final para documentar lo hecho. Creo que transmite un modelo equivocado al estudiante. Particularmente he intentado aplicar un modelo más "ágil" haciendo entregas (a mi mismo) más contínuas y que me hubiera gustado fueran visionadas por el consultor para irme orientando. Gracias a este modelo he conseguido llegar al final del TFG con una gran cantidad de documentación disponible para realizar la memoria.

Respecto de mi recorrido por el Grado, mi tutor puede dar fe de que aquello que me ha parecido mal lo he transmitido (con mayor o menor fortuna en mis expresiones) y lamento decir que creo que no se nos ha tenido en cuenta. En alguna asignatura el malestar ha sido general y a pesar de nuestras quejas no se han tomado medidas (lo sé porque compañeros posteriores han sufrido lo mismo).

Creo que salvo alguna asignatura como excepción, se sigue usando un modelo educativo individual donde no se premia el trabajo en grupo. Cuando el estudiante termine sus estudios se enfretará a un mundo colaborativo para el cual no se le ha preparado. Se debería promocionar que los alumnos compartieran sus experiencias, que hubiera más trabajos en grupo, etc.

Por otra parte y desde un lado técnico, no entiendo que una universidad online con tantos años de experiencia como la UOC haya que seguir usando unos foros tan pobres que no fomentan la comunicación. Me considero orgulloso de haber desarrollado un plugin para Chrome que nos permite saber cuando alguien ha escrito en el foro y poder leerlo de forma inmediata. Este plugin (y derivados) es usado por cientos de usuarios que de esta forma se mantienen al día de sus aulas.

Screenshots

A continuación se adjuntan capturas de pantallas de todos los casos contemplados por la aplicación, desde el registro , invitación y aceptación de amistad, mantenimiento de lugares, productos y lugares, así como solicitud de pedido y aceptación del mismo.

1
Figure 1. Inicio
2
Figure 2. Registro
3
Figure 3. Login
4
Figure 4. Welcome
5
Figure 5. Nuevo amigo
6
Figure 6. Aceptado
7
Figure 7. Menú
8
Figure 8. Mis pueblos
9
Figure 9. Productos de un pueblo
10
Figure 10. Viajes a un pueblo
11
Figure 11. Viajes en mi red
12
Figure 12. Solicitar pedido
13
Figure 13. Pedido solicitado
14
Figure 14. Notificación de pedido
15
Figure 15. Lista de pedidos