reciclaweb - web.ua.es€¦ · encontramos en (puelles, y otros, 1993), que definen reciclar como...
TRANSCRIPT
0
ReciclaWeb
Grado en Ingeniería Informática
Trabajo Fin de Grado
Autor:
Alberto Rico García
Tutor/es:
Cristina Cachero Castro
Santiago Meliá Beigbeder
Junio 2018
1
Justificación y objetivos
Nuestra modelo económico ha seguido tradicionalmente una estructura lineal: extraemos
recursos de la tierra, producimos algo y, tras, usarlo, lo desechamos. Este modelo ha
mostrado tener diversas consecuencias negativas para el medio ambiente, como es el
agotamiento de los recursos o el deterioro de los sistemas naturales. La solución a estos
problemas pasa por avanzara hacia una economía circular (Ye, y otros, 2018). En este nuevo
modelo, basado en las 5 Rs (rediseñar, reducir, reparar, reutilizar y reciclar), el reciclaje es
una piedra angular de los procesos productivos. Una posible definición de este concepto la
encontramos en (Puelles, y otros, 1993), que definen reciclar como el proceso de deshacernos
de un material ya utilizado para someterlo a un proceso que permita volverlo a utilizar y darle
nueva vida.
El signo de reciclaje más conocido (ver Figura 1) refleja perfectamente esta idea de
economía circular: una flecha indica el paso de recopilación de los desechos, otra hace
referencia al proceso por el cual las materias reciclables se convierten en nuevos productos,
y la tercera se refiere al consumo de los productos realizados con materiales reciclados.
Figura 1: Símbolo de reciclaje. Fuente: Pixabay (CC0 Creative Comons)
Según un informe reciente de Ecoembes de 2017 (Ecoembes, 2018), el reciclaje ha ido
avanzando en España en los últimos años hasta situarse, para cierto tipo de residuos como
son los envases de plástico, en tasas que alcanzan el 77.1%. Sin embargo, a nivel global,
2
en España sólo se recicla un 29.7% del total de residuos generados, una cifra que nos sitúa
lejos de países como Austria, Alemania o Bélgica, cuyas tasas superan el 50%.
Aumentar estas cifras sólo es posible con el compromiso ciudadano e institucional. Como
ciudadanos, necesitamos mejorar nuestro conocimiento de qué y cómo reciclar, así como
incrementar nuestra concienciación acerca del impacto que las acciones de reciclaje tienen
en el medio ambiente. Desde las instituciones es importante facilitar el reciclaje,
aumentando el número de contenedores y puntos de reciclaje selectivo disponibles y
fomentando su buen uso.
Conscientes de esta situación, el “Proyecto Reciclaje” (PR), lanzado por la red de
investigación IDoI (Red IDoI, 2018) , tiene como principal meta durante el año 2018 incidir en
el comportamiento de la comunidad universitaria de la UA en relación con el reciclaje, y
contribuir a que ésta transmita los valores de compromiso con su entorno y con la sociedad.
El proyecto cuenta con la colaboración del Consejo de Estudiantes, y con la supervisión y el
visto bueno del Vicerrectorado de Estudiantes y del Vicerrectorado de Campus y Tecnologia
de la Universidad de Alicante, que ha autorizado la instalación de nuevos contenedores (ver
Figura 2) de tapones y material de escritura en dependencias repartidas por todo el campus.
Figura 2: Contenedores negro y blanco de la UA para material de escritura y tapones. Fuente: red IDoI
En paralelo a esta mejora de los rincones de reciclaje del campus, y con el fin de aumentar
el nivel de conciencia de la comunidad universitaria y su implicación activa en el proceso, en
este proyecto hemos desarrollado una app para móviles Android e iOS. Esta aplicación
informa a los usuarios sobre estos nuevos rincones y cómo deben ser usados, al mismo
tiempo que registran sus acciones de reciclaje, proporcionan información relevante y crean
comunidad. De este modo se pretende aumentar el volumen de objetos reciclados en la UA,
3
al mismo tiempo que se incide en los niveles de concienciación de la comunidad
universitaria.
4
Índice de Contenidos
1. Introducción 11
2. Marco teórico 12
2.1. Funcionalidades típicas de apps móviles de reciclaje 12
2.1.1. iRecycle (Earth911, 2017) 12
2.1.2. RecycleNation (RecycleNation, 2017) 12
2.1.3. TapIt Metro DC (TapIt Metro D.C., 2017) 13
2.1.4. OLIO (OLIO, 2017) 13
2.1.5. Comparativa 13
2.2. Gamificación 14
2.3. Comportamiento de reciclaje del universitario 15
2.4. Dificultades percibidas por la comunidad universitaria para el reciclaje 18
2.5. Funcionalidades que debería tener un app de reciclaje útil para la comunidad
universitaria 19
3. Objetivos 21
4. Método de desarrollo del proyecto 22
4.1. SCRUM 22
4.1.1. Iteraciones y reparto del trabajo 22
4.1.2. Iteración 1 23
4.1.3. Iteración 2 24
4.1.4. Iteración 3 25
5. Diseño de Interfaz de Usuario 26
5.1. Prototipo de diseño inicial 26
5.2. Diseño final 28
6. Diseño Arquitectural 39
6.1. Modelo de diseño arquitectural 39
6.2. Modelo de datos 41
6.2.1. Parte 1: Gestión de usuarios 41
6.2.2. Parte 2: Gestión de Contenedores e Ítems 43
6.2.3. Clases auxiliares 44
6.2.4. Historial de versiones del Diagrama de Clases 45
6.3. Servidor (Backend) 47
5
6.3.1. Arquitectura web API REST 48
6.3.2. Patrón MVC 49
6.3.2.1. Modelo 49
6.3.2.2. Vista 49
6.3.2.3. Controlador 50
6.3.3. Operaciones CRUD con Spring MVC 50
6.4. Cliente 51
7. Seguridad 53
7.1. Separación parte pública privada y administración del API Rest 53
7.2. Uso de contraseñas y librerías necesarias 54
7.3. Peticiones API REST abiertas 55
7.4. Tokens y regeneración de tokens 57
7.5. Control de cambios no permitidos mediante peticiones HTTP 58
7.6. Sistema de logs 59
7.7. Inicio de sesión mediante redes sociales 59
8. Distribución de funcionalidades 62
9. Tecnologías 68
9.1. Servidor 68
9.1.1. Maven 70
9.1.2. Spring Boot Framework 70
9.1.4. JPA 71
9.1.5. PostgreSQL 71
9.1.6. Jackson 72
9.1.7. Envío de correos 72
9.1.7.1. Creación del HTML a partir de una plantilla 73
9.1.8. Swagger UI 74
9.2. Cliente 74
9.2.1. Ionic Framework 75
9.2.2. Apache Cordova 75
9.2.3. API Google Vision 77
9.3. Administración 79
9.3.1. React Native (admin-on-rest) 80
9.4. Control de versiones 80
9.5. Heroku 82
9.6. Servidor de ficheros FTP 83
10. Justificación de decisiones de implementación 84
6
10.1. Servidor 84
10.2. Cliente 88
10.3. Administración 94
11. Conclusiones 96
11.1. Mejoras 97
11.1.1. Mejoras técnicas 97
11.1.2. Mejoras funcionales 97
Bibliografía 99
13. Apéndices 101
13.1. Wiki del proyecto y puesta en marcha 101
13.2. Resultados Encuesta concepto producto 101
7
Índice de Figuras
Figura 1: Símbolo de reciclaje 1
Figura 2: Contenedores negro y blanco de la UA para material de escritura y tapones 2
Figura 3: Pregunta para medir la concienciación de la comunidad UA con el reciclaje.
Fuente: red IDoI 16
Figura 4: Pregunta para medir el conocimiento de la comunidad UA del reciclaje 17
Figura 5: Nube de palabras relacionadas con problemas de reciclaje 19
Figura 6: Prototipo inicial: Home 26
Figura 7: Prototipo inicial: Perfil e inicio de sesión 27
Figura 8: Prototipo inicial: Nuevo item y mapa 27
Figura 9: Diseño final: Login y registro 28
Figura 10: Diseño final: Recuperar contraseña 29
Figura 11: Diseño final: Inicio y ranking 29
Figura 12: Diseño final: Reciclar 30
Figura 13: Diseño final: Perfil e historial 30
Figura 14: Diseño final: Editar perfil 31
Figura 15: Diseño final: Adivina dónde se recicla 31
Figura 16: Admin: Listados (Ordenador) 1 32
Figura 17: Admin: Listados (Ordenador) 2 32
Figura 18: Admin: Creación (Ordenador) 1 33
Figura 19: Admin: Creación (Ordenador) 2 33
Figura 20: Admin: Edición (Ordenador) 1 34
Figura 21: Admin: Edición (Ordenador), appLog con imagen 34
Figura 22: Admin: Edición (Ordenador), appLog sin imagen 35
Figura 23: Admin: Edición (Ordenador) 2 35
Figura 24: Admin: Login (Ordenador) 36
Figura 25: Admin: Listados (Móvil) 36
Figura 26: Admin: Creación (Móvil) 37
Figura 27: Admin: Edición (Móvil) 37
Figura 28: Admin: Login (Móvil) 38
Figura 29: Diagrama de componentes 39
Figura 30: Diagrama de clases (Primera parte) 41
Figura 31: Diagrama de clases (Segunda parte) 43
Figura 32: Diagrama de clases, clases auxiliares 44
Figura 33: Diagrama de clases inicial 46
8
Figura 34: Seguridad: Acceso a rutas privadas 53
Figura 35: Seguridad: Acceso a rutas referentes a administración 54
Figura 36: Seguridad: Seguridad en el acceso a datos 57
Figura 37: Seguridad: Problema de acceso por redes sociales 60
Figura 38: Seguridad: Inicio de sesión mediante redes sociales 61
Figura 39: Swagger 74
Figura 40: Reconocimiento de objetos a través de una imagen, comparativa 77
Figura 41: Ejemplo de reconocimiento de un objeto 78
Figura 42: Cambios realizados en el repositorio de GitHub 80
Figura 43: GitHub: Detección de paquetes por GitHub 81
Figura 44: GitHub: Aviso de qué paquetes tienen un problema de seguridad 81
Figura 45: Aplicación de Heroku 82
Figura 46: Comparativa del formato de almacenamiento de las imagenes 83
Figura 47: Compartir relaciones a la hora de devolver un JSON 85
Figura 48: Paginación de acuerdo a Admin-On-Rest 87
Figura 49: Ocultación menú inferior al mostrar el teclado 92
9
Índice de Tablas
Tabla 1: Comparativa de aplicaciones sobre el reciclaje 14
Tabla 2: Principales problemas encontrados a la hora de reciclar 18
Tabla 3: Funcionalidades principales de una app de reciclaje 19
Tabla 4: Clase User 41
Tabla 5: Clase Storage 42
Tabla 6: Clase UserQuestion 42
Tabla 7: Clase Logs 43
Tabla 8: Clase ItemTypeNames 44
Tabla 9: Clase ItemType 44
Tabla 10: Clases LabelAnnotationsWithImage, LabelAnnotations, MyMail 44
Tabla 11: Clases LastQuestionDone, RecycleItems_Users 45
Tabla 12: Funcionalidad 1: Buscar tipo de objeto a partir de una imagen 62
Tabla 13: Funcionalidad 2: Buscar punto más cercano a partir de un tipo de objeto 62
Tabla 14: Funcionalidad 3: Cambiar tipo y/o nombre y mostrar ruta 62
Tabla 15: Funcionalidad 4: Finalizar reciclaje 62
Tabla 16: Funcionalidad 5: Registro e inicio de sesión mediante Facebook e Instagram 63
Tabla 17: Funcionalidad 6: Registro e inicio de sesión normal 63
Tabla 18: Funcionalidad 7: Modo Debug 63
Tabla 19: Funcionalidad 8: Recuperar contraseña 64
Tabla 20: Funcionalidad 9: Ranking 64
Tabla 21: Funcionalidad 10: Inicio de sesión de usuario social con contraseña 64
Tabla 22: Funcionalidad 11: Editar perfi 65
Tabla 23: Funcionalidad 12: Ver perfil 65
Tabla 24: Funcionalidad 13: Ver historial del usuario 65
Tabla 25: Funcionalidad 14: Listar últimos reciclajes 66
Tabla 26: Funcionalidad 15: Listar últimos usuarios reciclando 66
Tabla 27: Funcionalidad 16: Adivina dónde se recicla 66
Tabla 28: Funcionalidad 17: Consejos sobre el reciclaje 67
Tabla 29: Funcionalidad 18: Sistema de logs 67
Tabla 30: Funcionalidad 19: Administración 67
Tabla 31: Ofertas de empleo de acuerdo al lenguaje de programación 68
Tabla 32: Ofertas de empleo de acuerdo a los frameworks más populares 69
Tabla 33: Plugins para la cámara 75
Tabla 34: Plugins para la localización 1 75
10
Tabla 35: Plugins para la localización 2 76
Tabla 36: Plugin para el almacenamiento de la sesión local 76
Tabla 37: Plugin para la transferencia de archivos 76
Tabla 38: Plugin para la integración de Facebook 76
Tabla 39: Alternativas para el desarrollo de la administración: LightAdmin 79
Tabla 40: Alternativas para el desarrollo de la administración: JHipster 79
Tabla 41: Alternativas para el desarrollo de la administración: Admin-On-Rest 79
11
1. Introducción
En el actual contexto mundial, la demanda creciente de recursos naturales obliga a las
sociedades modernas a utilizarlos de modo natural y sostenible. La conocida regla de las 5R
(Rediseñar, Reducir, Reparar, Reutilizar y Reciclar) sobre los hábitos de consumo debe ser
promovida desde todos los ámbitos, incluido el universitario (Ye, y otros, 2018).
Con el fin de contribuir a ello, en este TFG hemos desarrollado la app ‘ReciclaUA’, una app
que nace con el objetivo de ayudar a fomentar el hábito del reciclaje y hacer visible el
impacto de las acciones individuales sobre el medio ambiente.
La aplicación incluye algunas funcionalidades clásicas de este tipo de aplicaciones, como es
la localización de contenedores, y también otras novedosas, como la identificación de
categorías de residuo a partir de fotografías subidas por el usuario. Además, incluye
elementos sociales y de gamificación que buscan mejorar la experiencia de reciclaje de los
usuarios y aumentar su nivel de concienciación.
La aplicación ha sido diseñada para poder ser utilizada en dispositivos tanto iOS como
Android.
12
2. Marco teórico
2.1. Funcionalidades típicas de apps móviles de reciclaje
Con el fin de entender mejor el contexto de nuestra app, a continuación presentamos un
resumen de las principales aplicaciones de reciclaje disponibles en el mercado Android e
iOS, junto con sus principales características.
2.1.1. iRecycle (Earth911, 2017)
Se trata de una de las aplicaciones más famosas en la categoría del reciclaje. Esta
aplicación (utilizada en Estados Unidos) tiene los siguientes rasgos principales:
● Es compatible con Android e iOS.
● Cuenta con una base de datos con alrededor de 350 objetos concretos.
● Incluye más de un millón de lugares donde reciclar en Estados Unidos.
● Da la posibilidad de compartir tu actividad en las redes sociales (Facebook, Twitter).
● Principales funcionalidades:
○ Buscar punto de reciclaje más cercano a partir de un objeto concreto.
○ Buscar puntos de reciclaje en una zona.
○ Ver información detallada sobre un punto de reciclaje.
○ Ver los contenedores cercanos.
Su principal fortaleza radica en disponer de una base de datos enorme que facilita su uso en
todo el territorio. Su interfaz puede llegar a hacerse difícil de utilizar debido a la gran
cantidad de menús que incluye.
2.1.2. RecycleNation (RecycleNation, 2017)
Como la aplicación anterior, RecycleNation también ofrece la posibilidad de encontrar el
contenedor cercano, pero esta vez a partir de un tipo de objeto.
Sus principales rasgos son:
● Instalable tanto en iOS como Android.
● Permite reciclar a partir de un tipo de objeto en el contenedor más cercano.
● Proporciona una vista de contenedores cercanos.
13
● Interfaz cuidada.
● Proporciona noticias, consejos y curiosidades acerca del reciclaje.
● Incluye una vista del historial por días y peso reciclado.
● Define trece categorías de reciclaje distintas.
Con una interfaz muy cuidada, se trata de una aplicación que pretende fomentar el reciclaje
mediante la muestra de la actividad de reciclaje del usuario. Además, ofrece multitud de
consejos sobre el reciclado.
2.1.3. TapIt Metro DC (TapIt Metro D.C., 2017)
Aplicación desarrollada por el Consejo de Gobierno de Washington DC para la promoción
del consumo de agua local de grifo. Así, se pretende reducir la demanda de agua
embotellada, que genera grandes cantidades de residuos.
Principales características:
● Compatible tanto con iOS como con Android.
● Cuenta con la ayuda de una institución pública.
● Permite buscar puntos donde obtener agua gratuita a través de un mapa en la
ciudad.
2.1.4. OLIO (OLIO, 2017)
Con un enfoque distinto, OLIO ofrece la posibilidad de compartir comida para que ésta no
sea desechada. Para esto, la aplicación ofrece una interfaz cuidada que permite, a través de
una foto compartir algo que ya no necesites, o incluso donarlo a causas benéficas.
Funcionalidades:
● Compatible con Android e iOS.
● Permite compartir comida que no se vaya a utilizar mediante una foto.
● Permite buscar comida cercana a la localización del usuario.
● Interfaz muy detallada.
2.1.5. Comparativa
De las cuatro aplicaciones estudiadas, las dos primeras se enfocan en el reciclaje de
residuos genéricos, mientras que las dos últimas se centran en el agua y la comida. Nuestra
14
aplicación permite, como las dos primeras, en el reciclaje de residuos genéricos, aunque se
centra en reciclaje de tapones y material de escritura, material este último para el que la UA
ha sido seleccionada como uno de los puntos de recogida de la provincia de Alicante dentro
del proyecto TerraCicle (TerraCycle, 2018).
La Tabla 1 lista las características de las apps de reciclaje identificadas en esta comparativa,
junto con su presencia (sí) o ausencia (no) en las cuatro aplicaciones estudiadas (1:
iRecycle, 2: recicleNation, 3: tapitmetrodc, 4: Olio) y en la aplicación reciclaUA (5).
Tabla 1: Comparativa de aplicaciones sobre el reciclaje. Fuente: Elaboración propia
Funcionalidad 1 2 3 4 5
Ubicación de contenedor más cercano según tipo de residuo
sí sí sí no sí
Orientación para llegar al contenedor seleccionado no no no no sí
Registro de acciones de reciclaje no sí no sí sí
Compatibilidad con Android e iOS sí sí sí sí sí
Interfaz cuidada no sí no sí sí
Inicio de sesión por redes sociales no no no sí sí
Sistema de motivación no sí no sí sí
Extensa base de datos de lugares o tipos de ítems sí sí no no no
Consejos y noticias sobre el reciclaje no sí no no sí
2.2. Gamificación
La gamificación de aplicaciones se define como el uso de elementos de diseño de juegos en
contextos que no son juegos (Deterding, y otros, 2011). La gamificación busca, mediante la
incorporación de elementos y mecánicas típicas de los juegos (game atoms), mejorar el
atractivo de la tarea y, de este modo, persigue la mejora de la motivación, compromiso y
rendimiento del usuario en dicha tarea.
Existen distintos elementos que pueden producir este efecto. Los “Diez ingredientes de los
grandes juegos” (Reeves, y otros, 2009) incluyen auto-representación mediante avatares,
entornos tridimensionales, contexto narrativo, retroalimentación, reputación, rankings y
niveles, economías y mercados, competición bajo reglas que son específicas y obligatorias,
15
equipos, sistemas de comunicación paralela que pueden ser configurados fácilmente y
presión de tiempo. Obviamente, la pertinencia de estos elementos depende en gran medida
de la aplicación que estemos construyendo.
Nos ha sorprendido constatar cómo, a pesar del impacto positivo de la gamificación sobre la
motivación y el engagement del usuario final, las principales aplicaciones estudiadas no
incluyen elementos reseñables en este sentido, más allá de la visualización del historial de
acciones de reciclaje o un simple sistema en el que indicar mediante estrellas la la fiabilidad
o popularidad de un usuario. Por tanto, más allá de la mayor o menor sofisticación de las
funcionalidades, la inclusión de esta característica es uno de los objetivos que sin duda
diferencian nuestra app de las apps competidoras.
2.3. Comportamiento de reciclaje del universitario
Otro elemento importante relativo al contexto de este proyecto es el conocimiento de cuál es
el punto de partida respecto al grado de concienciación actual en cuanto al reciclaje en la
comunidad universitaria de la UA. Conocer estos datos es la única manera de poder medir
en un futuro de forma objetiva el impacto de la app sobre los comportamientos de interés.
Para ello, contamos con los datos de una encuesta que se realizó a la comunidad
universitaria de la UA y que incluye cuatro constructos: conocimiento básico, preocupación
medioambiental, implicación medioambiental y comportamiento ecológico (De-Juan-Vigaray, y
otros, 2017). De entre las distintas escalas utilizadas para medir estos constructos, todas
ellas validadas, la escala que mide el comportamiento ecológico introduce dos de preguntas
que abordan de manera específica el grado de conocimiento y concienciación con el
reciclaje del colectivo universitario. Dichas escalas pueden ser vistas en la Figura 3 y la
Figura 4.
16
Figura 3: Pregunta para medir la concienciación de la comunidad UA con el reciclaje. Fuente: red IDoI
17
Figura 4: Pregunta para medir el conocimiento de la comunidad UA del reciclaje. Fuente: Red IDoI
18
2.4. Dificultades percibidas por la comunidad universitaria para
el reciclaje
Por último, y con el fin de diseñar un producto que de verdad cubra las necesidades de la
comunidad universitaria, como parte de este proyecto se diseñó una encuesta que constaba
de cinco preguntas:
1.- ¿Qué significa para ti 'reciclar'?
2.- ¿Cómo te sientes cuando reciclas?
3.- ¿Qué impedimentos encuentras actualmente a la hora de reciclar?
4.- ¿Qué funcionalidades te gustaría que tuviese una app que te ayudara a reciclar?
5.- ¿Cómo te gustaría verte a ti mismo con respecto al reciclaje en un futuro?
Este cuestionario se pasó a una muestra de 45 estudiantes de último curso del grado de
Ingeniería Informática. Se recibieron 29 respuestas (65% de ratio de respuesta). En base a
dichas respuestas, el ranking de problemas percibidos a la hora de desarrollar acciones de
reciclaje puede ser visto en la Tabla 2.
Tabla 2: Principales problemas encontrados a la hora de reciclar. Fuente: elaboración propia
Problema %
Falta contenedores/servicios recogida enseres 48.3%
Falta de formación en cuanto a cómo reciclar 27.6%
Desconocimiento ubicación contenedores 24.1%
Falta de motivación/concienciación 17.2%
Falta de espacio/medios en casa para reciclar correctamente 13.8%
Falta de información/desconfianza sobre el destino e impacto del material
reciclado (falta de trazabilidad)
10.3%
La nube de palabras que refleja los términos más usados por las personas consultadas a la
hora de definir sus principales dificultades a la hora de reciclar puede ser visto en la Figura
5.
19
Figura 5: Nube de palabras relacionadas con problemas de reciclaje. Fuente: elaboración propia (creada en https://worditout.com/)
Tanto el estudio de aplicaciones relacionadas con el reciclaje como la encuesta realizada
han servido de base para la definición de las funcionalidades principales que debería tener
una aplicación como ReciclaUA, tal y como detallamos a continuación.
2.5. Funcionalidades que debería tener un app de reciclaje útil
para la comunidad universitaria
A partir de los datos de la encuesta realizada, se puede concluir que las principales
funcionalidades que un usuario espera encontrar en una app de ayuda al reciclaje se listan
en la Tabla 3.
Tabla 3: Funcionalidades principales de una app de reciclaje. Fuente: elaboración propia.
Funcionalidad %
Mapa de contenedores y puntos limpios 55.2%
¿Cómo reciclo? 55.2%
20
Trazabilidad de mi reciclaje 20.7%
Consejos para formar en reciclaje/Hechos para concienciar en la necesidad de
reciclar/Estadísticas
13.8%
Solicitud de nuevos puntos de reciclaje 6.9%
Mapa de puntos limpios para reciclaje de enseres especiales, con horarios y datos
de contacto
6.9%
Tal y como podemos observar si comparamos la Tabla 3 con la Error! Reference source
not found., las funcionalidades esperadas por usuarios de la comunidad universitaria
constituyen un enriquecimiento de los requisitos funcionales más importantes incluidos en
otras aplicaciones similares:
• La funcionalidad de inclusión de un mapa de contenedores y puntos limpios engloba
tanto la funcionalidad de la ubicación del contenedor más cercano como la funcionalidad
de proporcionar indicaciones para llegar hasta él.
• En cuanto al registro de acciones de reciclaje, en la encuesta se ha detectado una
necesidad más amplia (que también se relaciona con incluir sistemas de motivación): los
usuarios de la UA no sólo desean saber lo que han reciclado (registro de acciones), sino
cuál ha sido su impacto (trazabilidad de dichas acciones).
21
3. Objetivos
A partir de toda la información recopilada, el objetivo general de este proyecto ha sido el
análisis, diseño e implementación de una app multiplataforma dirigida a alumnos de la UA
que ayude a aumentar su implicación con el reciclaje.
Los objetivos específicos son:
• OE1: Aumentar el grado de implicación de la comunidad UA con respecto al reciclaje
• OE2: Aumentar la conciencia de la comunidad UA de la existencia de puntos de
reciclaje específicos para tapones y material de escritura, y de dónde se encuentran
ubicados.
• OE3: Aumentar la conciencia de la comunidad UA del impacto que sus acciones de
reciclaje tienen en otros y en el medio ambiente
• OE4: Crear una comunidad de usuarios ‘amigos de reciclaje’ en la UA
• OE5: Educar a los usuarios en la elección del contenedor más adecuado para cada
tipo de desecho.
Con el fin de evaluar la consecución de estos objetivos, se han definido una serie de
medidas que se propone tomar en tres momentos: antes del lanzamiento del proyecto, tras
seis meses del lanzamiento y tras un año del lanzamiento de la app. Estas medidas son:
● Número de kg de tapones y material de escritura recogido correctamente en los
distintos contenedores de la UA (OE1, OE2, OE5)
● Número de usuarios de la app (OE4)
● Número de acciones de reciclaje dirigidas por la app (OE1, OE5)
● Opinión subjetiva de la comunidad universitaria con respecto al reciclaje
(cuestionario) (OE3)
● Conocimiento objetivo de cómo reciclar por parte de los distintos colectivos de la
comunidad universitaria (cuestionario) (OE5) (ver Figura 4)
● Nivel de concienciación de los distintos colectivos de la comunidad universitaria con
respecto al reciclaje (cuestionario) (OE3) (ver Figura 3)
22
4. Método de desarrollo del proyecto
4.1. SCRUM
Para el desarrollo de la app se ha optado por adaptar el marco de trabajo ágil SCRUM
(Schwaber, y otros, 2002) a la idiosincrasia del proyecto (un solo desarrollador, tiempo de
desarrollo limitado al curso académico). Así, se han tomado las siguientes decisiones
metodológicas:
- Todas las iteraciones han utilizado la técnica del timebox. De este modo, nos hemos
asegurado de que todas las funcionalidades definidas se incluyan en el proyecto,
aunque eso nos ha forzado a redefinir a la baja el alcance de algunas de ellas, tal y
como detallaremos más adelante.
- Cada dos semanas se ha realizado una reunión donde el primer paso ha sido una
demo de un prototipo funcional. Esto ha permitido verificar que las funcionalidades
estaban implementadas de acuerdo a su diseño previo, y validar que en cada caso
dichas funcionalidades contribuían a cubrir las necesidades fijadas por los objetivos.
- En cada iteración se ha incluido un conjunto de historias de usuario de entre las
disponibles en la pila de producto, en base al valor que añadían al producto final.
Dichas historias se han definido en base al trabajo detallado en la sección 2.
4.1.1. Iteraciones y reparto del trabajo
Tal y como hemos detallado en la sección 2, este TFG comenzó con una etapa de definición
del producto, en base a (a) análisis de aplicaciones competidoras y (b) investigación de las
necesidades de la comunidad UA mediante encuestas.
Una vez clarificado nuestro contexto y principales funcionalidades, se definieron 3
iteraciones SCRUM, con una asignación temporal de 1 mes y medio cada una. Asimismo, se
definió la pila de producto a partir de los datos de la sección 2.
Dado que el equipo de desarrollo está formado por un solo miembro, no se estimó necesario
crear un tablero donde controlar el desarrollo del proyecto; sí se establecieron sin embargo
reuniones bisemanales con los tutores (viernes de 13h a 14h). El feedback de cada reunión
sirvió para ir refinando el trabajo.
Al final de cada iteración se realizó una reunión final con formato de demo en la que se
valoró el grado de cumplimiento de las historias de usuario incluidas en la iteración, se
actualizó la pila de producto y se definió el alcance de la siguiente iteración.
23
4.1.2. Iteración 1
26-12-2017 → 16-02-2018
En esta primera iteración se creó una primera versión estable que abordaba la funcionalidad
clave del proyecto: la localización de contenedores de reciclaje en función del objeto.
Durante la descomposición de las historias de usuario en tareas, se definieron una serie de
spikes para evaluar las distintas tecnologías utilizadas en este proyecto:
- Spring Boot: Para la implementación del servidor que llama a la base de datos
donde encontrar los tipos de objetos.
- Ionic: Para la implementación del cliente.
- API de Google Maps y Apple Maps para mostrar el mapa y ver ruta.
Las historias de usuario finalmente introducidas en este Sprint fueron:
● HU1: Como persona concienciada con el reciclaje quiero saber dónde se encuentra
el contenedor más cercano de tipo X (papel, orgánico, plástico, material escritura,
tóner, pilas, CDs) para poder reciclar de la manera más eficiente posible.
● HU2: Como persona concienciada con el reciclaje quiero que, al seleccionar un
contenedor de reciclado, la app me guíe hasta él por el camino más rápido/más corto
para poder reciclar de la manera más eficiente posible.
● HU3: Como persona concienciada con el reciclaje quiero poder introducir un objeto
que quiero reciclar y que la app me diga en qué tipo de contenedor debe ir para
reciclar de manera correcta.
Reunión final: 16-02-2018
- ¿Qué se ha realizado?
- Creación de backend y frontend, despliegue en Heroku.
- Integración con la base de datos.
- Diagrama de clases y prototipos de diseños.
- Reciclaje por tipo de objeto.
- Ver ruta al contenedor más cercano.
- ¿Qué no se ha hecho?
- La ruta debe realizarse desde la aplicación de Google Maps o Apple Maps
puesto que dicha funcionalidad está limitada fuera de la aplicación.
- Se ha limitado el alcance de la HU3 y se ha implementado sólo el reciclaje
por tipo de objeto
24
- Decisiones tras la reunión.
- Se ha decidido dar un carácter más actual a la aplicación, eliminando
funcionalidades como la de foro y dándole a la aplicación un carácter más
similar a otras aplicaciones populares. Así, se ha decidido valorar la entrada
diaria del usuario a la aplicación y crear, en lugar del foro, un feed de noticias
con los últimos objetos reciclados por los usuarios.
- Se ha añadido la posibilidad de registrarse sin utilizar redes sociales.
4.1.3. Iteración 2
17-02-2018 → 02-04-2018
En esta segunda iteración se abordaron las siguientes historias:
● HU4: Como persona concienciada con el reciclaje quiero que la app guarde mis
acciones de reciclado con el fin de tener un registro de lo que he reciclado en un
período concreto y sentirme bien.
● HU5: Como persona concienciada con el reciclaje quiero poderme conectar con mis
amigos en una ‘comunidad’ y ver un ranking donde salgamos todos ordenados en
función de la cantidad de reciclaje que hemos efectuado.
● HU6: Como persona concienciada con el reciclaje, quiero saber qué otros usuarios
están reciclando para sentirme parte de una comunidad.
Reunión final: 06-04-2018
- ¿Qué se ha realizado?
- Se ha creado un perfil de usuario en el que se puede ver los items ya
reciclados.
- Se ha creado un feed de noticias donde ver las últimas acciones de reciclaje
por parte de los usuarios.
- Se ha creado un ranking donde ver quiénes han reciclado más.
- Se han añadido nuevos datos al perfil del usuario.
- Ahora las peticiones privadas al API Rest requieren un token de
autenticación.
- Creado sistema de logs para interceptar los errores en el servidor.
- Se ha implementado el registro de usuarios sin necesidad de usar redes
sociales.
- ¿Qué no se ha hecho?
25
- No se ha conseguido que las listas se actualicen de manera lo
suficientemente inmediata.
- A la hora de reciclar se han detectado diversos problemas para los que no se
controla el tiempo de respuesta de la app.
- Decisiones tras la reunión.
- Debe controlarse el tiempo de todas las peticiones al API REST y al servidor
FTP con un tiempo máximo de espera.
- Se debe definir un modo de proporcionar al usuario consejos sobre el
reciclado.
- Se debe comenzar a diseñar el apartado para la gamificación de la
plataforma.
4.1.4. Iteración 3
Esta iteración se ha realizado un spike para evaluar las posibles tecnologías para
implementar las historias:
- Google Vision: Necesario para la obtención de un objeto a partir de una foto.
- admin-on-rest: Gestión de la administración.
03-04-2018 → 18-05-2018
Historias incluidas en la última iteración:
● HU7: Como persona concienciada con el reciclaje quiero poder hacer una foto desde
la app a lo que quiero reciclar y que la app me diga qué es para no tener que teclear
el producto en la app
● HU8: Como persona concienciada con el reciclaje, quiero poder introducir desde la
app nuevos puntos de reciclaje con el fin de que la información que me proporcione
posteriormente al buscar los puntos más cercanos esté actualizada.
Reunión final: 18-05-2018
- ¿Qué se ha realizado?
- Reciclaje a partir de una foto.
- Mejora del tiempo de carga en el apartado de reciclar.
- Panel de administración del sitio.
- Gamificación mediante un juego de preguntas y respuestas.
- Consejos en la vista de reciclar.
- Integración de usuarios sociales y normales.
- Mejoras de seguridad de la aplicación y el servidor.
26
- ¿Qué no se ha hecho?
- Al tratarse de la última iteración, se ha tratado de realizar todas las historias
más los cambios acordados tras cada reunión.
- Decisiones tras la reunión.
- Perspectivas de la aplicación para sus posibles mejoras.
5. Diseño de Interfaz de Usuario
5.1. Prototipo de diseño inicial
A continuación presentamos la primera versión de la interfaz de la aplicación, consistente en
un prototipo temprano cuyo objetivo fue el servir de base para conocer la opinión del tipo de
usuario que utilizará la aplicación.
Vista #1: Home
Figura 6: Prototipo inicial: Home. Fuente: elaboración propia
Vista #2: Perfil y login
27
Figura 7: Prototipo inicial: Perfil e inicio de sesión. Fuente: elaboración propia
Vista #3: Nuevo Ítem a Reciclar y mapa
Figura 8: Prototipo inicial: Nuevo item y mapa. Fuente: elaboración propia
Este prototipo inicial fue mostrado a varios usuarios potenciales para recabar información
acerca de potenciales problemas de usabilidad.
28
5.2. Diseño final
A partir de la evaluación informal realizada sobre el prototipo temprano y del conocimiento
que íbamos ganando sobre el contexto del problema, se definió un prototipo avanzado. Si
comparamos el prototipo temprano con el avanzado, podemos observar cómo se ha
mantenido la idea general. Sin embargo, se han añadido elementos, como la gamificación, y
se han unido otros como por ejemplo la vista de reciclar con la de subir imagen. Además, se
han actualizado las interfaces de perfil e inicio para mejorar su adaptación a los dispositivos
móviles.
Vista #1: Login y registro
Figura 9: Diseño final: Login y registro. Fuente: elaboración propia.
Vista #2: Recuperar contraseña
29
Figura 10: Diseño final: Recuperar contraseña. Fuente: elaboración propia.
Vista #3: Inicio, y ranking
Figura 11: Diseño final: Inicio y ranking. Fuente: elaboración propia.
Vista #4: Reciclar
30
Figura 12: Diseño final: Reciclar. Fuente: elaboración propia.
Vista #5: Perfil e historial
Figura 13: Diseño final: Perfil e historial. Fuente: elaboración propia.
Vista #6: Editar perfil
31
Figura 14: Diseño final: Editar perfil. Fuente: elaboración propia.
Vista #7: Adivina dónde se recicla
Figura 15: Diseño final: Adivina dónde se recicla. Fuente: elaboración propia.
Vista #8: Admin: Listados (Ordenador)
32
Figura 16: Admin: Listados (Ordenador) 1. Fuente: elaboración propia.
Figura 17: Admin: Listados (Ordenador) 2. Fuente: elaboración propia.
Vista #9: Admin: crear entidad (Ordenador)
33
Figura 18: Admin: Creación (Ordenador) 1. Fuente: elaboración propia.
Figura 19: Admin: Creación (Ordenador) 2. Fuente: elaboración propia.
Vista #10: Vista de edición de entidad en el panel de administración (Ordenador)
34
Figura 20: Admin: Edición (Ordenador) 1. Fuente: elaboración propia.
Figura 21: Admin: Edición (Ordenador), appLog con imagen. Fuente: elaboración propia.
35
Figura 22: Admin: Edición (Ordenador), appLog sin imagen. Fuente: elaboración propia.
Figura 23: Admin: Edición (Ordenador) 2. Fuente: elaboración propia.
Vista #11: Vista inicio de sesión del panel de administración (Ordenador)
36
Figura 24: Admin: Login (Ordenador). Fuente: elaboración propia.
Vista #12: Admin: Listados (Móvil)
Figura 25: Admin: Listados (Móvil). Fuente: elaboración propia.
Vista #13: Creación (Móvil)
37
Figura 26: Admin: Creación (Móvil). Fuente: elaboración propia.
Vista #14: Admin: Edición (Móvil)
Figura 27: Admin: Edición (Móvil). Fuente: elaboración propia.
38
Vista #15: Admin: Login (Móvil)
Figura 28: Admin: Login (Móvil). Fuente: elaboración propia.
39
6. Diseño Arquitectural
6.1. Modelo de diseño arquitectural
Figura 29: Diagrama de componentes. Fuente: elaboración propia.
Como se puede observar en la Figura 29, el sistema está distribuido del siguiente modo:
● Servidor:
○ Modelo en el servidor utilizado por las 3 capas, correspondiente al de la base
de datos.
○ Rest API proporcionado automáticamente por Spring-Boot.
○ Controlador para definir las peticiones HTTP.
○ Capa de servicio intermedia entre capa de acceso a datos y controlador. La
utilidad de esta capa es crear un puente por si cambian las definiciones de los
métodos de la capa DAO, no tener que cambiar los nombres de los métodos
en la capa controlador.
○ Capa DAO que accede a la base de datos mediante CrudRepository1.
● Cliente:
1 "CrudRepository (Spring Data Core 2.0.7.RELEASE API)." https://docs.spring.io/spring-
data/commons/docs/current/api/org/springframework/data/repository/CrudRepository.html.
40
○ Modelo en el cliente para almacenar las respuestas a las peticiones y
manejar los datos.
○ Interfaz que se encarga de interactuar con el usuario.
○ Proveedor Cliente REST, es el encargado de llamar al API mediante
peticiones HTTP.
● Administración (obtenido de la documentación oficial2):
○ Admin-on-Rest, framework para generar una base de datos.
○ Cliente REST, encargado de llamar al API mediante peticiones HTTP.
2 "admin-on-rest/README.md at master · marmelab/admin-on-rest · GitHub."
https://github.com/marmelab/admin-on-rest/blob/master/README.md.
41
6.2. Modelo de datos
6.2.1. Parte 1: Gestión de usuarios
Figura 30: Diagrama de clases (Primera parte). Fuente: elaboración propia
A continuación se detallan las clases en las que puede surgir confusión:
Tabla 4: Clase User. Fuente: elaboración propia
User
- El usuario no requiere de verificación por correo para ser activado.
- Los métodos incluidos son utilizados en múltiples ocasiones en distintos
controladores, por lo tanto, al ser añadidos en la clase usuario se evita la
duplicación de código.
- getHoursDifferenceToPlay()
42
- Devuelve la diferencia de horas entre la fecha actual y la del usuario.
(GMT).
- pwdRecoverDateIsOutDated(): Devuelve true si han pasado 24 horas desde que
creó el código de activación, en dicho caso, el código ya no será válido.
Tabla 5: Clase Storage. Fuente: elaboración propia
Storage
- Esta clase intermedia entre RecycleItem y StoragePoint se ha creado puesto que
en un punto de reciclaje pueden existir muchos contenedores de varios tipos.
Tabla 6: Clase UserQuestion. Fuente: elaboración propia
UserQuestion
- Dado que un usuario puede tener muchas preguntas contestadas y una pregunta
puede tener muchos usuarios, se ha tenido que implementar una tercera clase que
represente dicha relación.
43
6.2.2. Parte 2: Gestión de Contenedores e Ítems
Figura 31: Diagrama de clases (Segunda parte). Fuente: elaboración propia
En el repositorio del proyecto se puede ver el diagrama de clases completo.
A continuación se detallan las clases relacionadas con la gestión de contenedores e ítems
que pueden resultar más confusas.
Tabla 7: Clase Logs. Fuente: elaboración propia
Logs
- Status: Se refiere al valor HTTP de respuesta.
- StatusName: Nombre del valor HTTP.
- base64Image: En caso de ser un log por no encontrar el tipo de objeto a partir de
una lista de nombres encontradas a partir de una imagen
(List<LabelAnnotations>) por Google Vision, se guardará la imagen codificada
en Base64.
44
Tabla 8: Clase ItemTypeNames. Fuente: elaboración propia
ItemTypeNames
- Clase que almacena nombres de objetos junto a un tipo, en inglés.
- La utilidad de esta clase es encontrar a partir de una lista de nombres
proporcionada por el usuario previamente.
Tabla 9: Clase ItemType. Fuente: elaboración propia
ItemType
- A diferencia de EnumUser o EnumGender, los tipos de objetos se ha decidido
utilizar una clase puesto que es una lista que puede tiene una gran probabilidad de
ser modificada (para añadir nuevos tipos). El problema es que añadir tipos de
acuerdo a una enumeración tiene el problema de que debe ser modificada la
numeración tanto en el cliente como en el servidor, por tanto, el único que
almacena dichos valores es la base de datos.
6.2.3. Clases auxiliares
En este caso no se representan las relaciones a las respuestas o preguntas, sin embargo,
se trata de una relación de asociación hacia dichas clases.
Figura 32: Diagrama de clases, clases auxiliares. Fuente: elaboración propia
Tabla 10: Clases LabelAnnotationsWithImage, LabelAnnotations, MyMail. Fuente: elaboración propia
45
LabelAnnotationsWithImage, LabelAnnotations, MyMail
- Leer datos proporcionados a través de un JSON recibido por parte del cliente.
Tabla 11: Clases LastQuestionDone, RecycleItems_Users. Fuente: elaboración propia
LastQuestionDone (1), RecycleItems_Users (2)
- Devolver datos en formato JSON de un modo específico.
1. Utilizado al devolver la ultima respuesta junto pregunta al responder el usuario un
pregunta del cuestionario.
2. Paginación en la vista principal de la aplicación, para mostrar los últimos objetos
reciclados junto su usuario.
6.2.4. Historial de versiones del Diagrama de Clases
En la primera reunión, realizada antes de comenzar el proyecto, se creó un posible
diagrama de clases inicial de la aplicación (ver Figura 33). Este diagrama ha sufrido cambios
que, sin embargo, han sido pequeños, lo que nos permite afirmar que se ha mantenido la
esencia del modelo de datos inicial.
Como se puede observar, en la primera iteración no se contemplaba la mayoría de
funcionalidades, aunque estas sí se conocía que no iban a afectar al grueso de la aplicación.
46
Figura 33: Diagrama de clases inicial. Fuente: elaboración propia
En la wiki del proyecto se puede ver la imagen del diagrama de clases inicial en pantalla
completa.
Sin embargo, sí que se hubo una pequeña confusión en la relación de posiciones y las rutas.
En un principio, se pensó almacenar las rutas entre puntos de reciclaje y usuarios. Sin
embargo, más tarde, en el desarrollo de dichas rutas se encontró la restricción del API de
Google Maps para ionic al no existir aún su desarrollo3.
Al final, la ruta al contenedor más cercano se calcula a través de la aplicación de mapas del
dispositivo móvil, compatible tanto con Apple Maps y Google Maps. Para este cálculo tan
solo es necesario proporcional la posición inicial y destino, por lo que no hace falta
almacenar las rutas.
Para generar la base de datos se ha creado un script SQL que puede ser consultado en
https://github.com/bertus193/reciclaWeb/blob/master/reciclaweb.sql.
3 "ionic-native-google-maps/README.md at master · ionic-team ... - GitHub." https://github.com/ionic-
team/ionic-native-google-maps/blob/master/documents/README.md.
47
6.3. Servidor (Backend)
A la hora de estructurar el contenido en el servidor se ha tratado de separar claramente las
capas. Por ello, se ha decidido seguir la siguiente estructura de ficheros:
reciclaServer
│ ReciclaServerApp.java
└───config
│ │ AppConfig.java
│ │ AppInterceptor.java
│ │ CorsConfig.java
│ │ EntityIdResolver.java
│ │ SwaggerConfig.java
└───utils
│ │ JsonReader.java
│ │ SendMail.java
└───controller
│ │ Controller_Class_1.java
│ │ Controller_Class_2.java
│ │ [...]
│ └───controller
│ │ AdminController_Class_1.java
│ │ AdminController_Class_2.java
│ │ [...]
└───services
│ │ Service_1.java
│ │ Service_2.java
│ │ [...]
└──models
│ │ Class_1.java
│ │ Class_2.java
│ │ [...]
│ └───DAO
│ │ │ DAO_Class_1.java
│ │ │ DAO_Class_2.java
│ │ │ [...]
│ └───exceptions
│ │ │ ExceptionClass1.java
│ │ │ ExceptionClass2.java
│ │ │ [...]
│ └───auxiliar
│ │ │ AuxiliarClass1.java
│ │ │ AuxiliarClass2.java
│ │ │ [...]
48
En este caso, además de las 3 capas (Controlador-Servicio-Modelo) se han añadido
paquetes para la configuración del proyecto, clases auxiliares para devolver los datos en
formato JSON y utilidades necesarias para realizar algunos comportamientos del servidor
que se detallarán más adelante.
Se ha decidido separar los controladores de administración y los normales puesto que se ha
querido separar ambas funcionalidades para una mayor claridad del código. No obstante,
ambos comparten la capa de servicio y modelo.
6.3.1. Arquitectura web API REST
Para la definición de las URL se ha dado un enfoque API Rest. Este enfoque es básico hoy
en día para cualquier plataforma software dada su eficiencia (BBVA, 2016).
Para ello, todas las peticiones al servidor se operan con los siguientes métodos:
● GET para leer.
● POST para crear un objeto de una entidad.
● PUT para modificar un objeto.
● DELETE para eliminar un objeto.
En este enfoque, las URLs siempre siguen el mismo patrón, que comienza con el nombre de
la entidad que se desea utilizar (en plural). Por ejemplo, para la entidad “User”, la URL sería:
GET /users/
En caso de requerir objetos concretos se utilizan campos de dicha entidad, o su propio
identificador4.
En nuestro caso, se han querido distinguir entre (a) las peticiones públicas, (b) las peticiones
privadas de usuario y (c) las peticiones de administración, ya que estas dos últimas
requieren de identificación. Para separar estas rutas, se ha decidido anteponer una subruta:
/private/ para peticiones privadas de usuario y /admin/ para las peticiones de
administración.
Otra característica del API REST desarrollado es la decisión de evitar cualquier tipo de
respuesta en un idioma concreto, así se evita un problema de traducción y además se
siguen los estándares al utilizar códigos de estado HTTP.
4 "REST Resource Identifier (URI) Naming – REST API Tutorial." https://restfulapi.net/resource-
naming/.
49
Los códigos de estado HTTP permiten devolver un estado concreto de respuesta al cliente.
El cliente leerá el estado y será el que se encargue de devolver un mensaje de acuerdo a
dicho estado.
6.3.2. Patrón MVC
El patrón modelo-vista-controlador es probablemente el patrón de diseño más popular a la
hora de desarrollar para crear contenido web dinámico. Spring-Boot utiliza internamente
spring-mvc, por tanto no es necesario preocuparse por crear estas capas ya que viene
preparado desde un inicio con éstas.
No obstante, sí es necesario crear la capa de negocio y controlador puesto que son estas
dos capas las que se encargan de manejar los datos desde la base de datos al cliente y
viceversa.
Spring-boot tiene por defecto una vista para imprimir los resultados en JSON, no obstante,
se ha añadido otra vista mediante swagger UI.
6.3.2.1. Modelo
El modelo se divide en dos entidades, la lógica del negocio, es decir, las clases de los
objetos utilizados en la aplicación y la capa de acceso a datos, o en otras palabras, DAO,
que se encarga, a partir de la lógica de negocio, realizar las peticiones CRUD (crear, leer.
actualizar y eliminar) a la base de datos mediante JPA.
6.3.2.2. Vista
El framework incluye una vista que se encarga, a partir de una petición del cliente, dar una
respuesta mediante una vista cuyo contenido tiene en su cabecera la etiqueta Content-
type: application/json;charset=UTF-8.
Por tanto, el contenido de la respuesta tendrá el formato JSON y estará codificado en UTF-8
para permitir caracteres especiales, como la “ñ”.
50
6.3.2.3. Controlador
Spring-Boot, a través de los controladores sirve contenido web a través de rutas HTTP.
Pueden definirse los controladores que se consideren oportunos. El controlador hace uso de
la capa de servicio, que éste a su vez utiliza la capa de modelo.
6.3.3. Operaciones CRUD con Spring MVC
Mediante JPA, se utilizará la interfaz CrudRepository para manejar la entidad que se
desee. Para ello se hará uso de esta interfaz (obtenido de la documentación oficial)5:
public interface CrudRepository<T, ID extends Serializable> extends
Repository<T, ID> {
<S extends T> S save(S entity);
Optional<T> findById(ID primaryKey);
Iterable<T> findAll();
long count();
void delete(T entity);
boolean existsById(ID primaryKey);
// ... more functionality omitted.
}
Dicha interfaz ofrece todos los métodos necesarios utilizados en la plataforma. Además de
éstos, otros pueden ser construidos a partir de la modificación del nombre.
Por defecto, la interfaz devuelve las listas utilizando la clase “Pageable”, sin embargo, su
gran versatilidad permite almacenar el resultado de llamar al método en listas. Además, al
heredar de la interfaz, no es necesario agregar los métodos explícitamente para ser
llamados, aunque sí es recomendable para conocer qué métodos de la interfaz se está
utilizando.
5 "Spring Data JPA - Reference Documentation." 8 may.. 2018, https://docs.spring.io/spring-
data/jpa/docs/current/reference/html/.
51
6.4. Cliente
La estructura de ficheros del cliente se estructura del siguiente modo:
src
└───app
│ │ AppConfig.ts
│ │ AppInterceptor.ts
│ │ CorsConfig.ts
│ │ EntityIdResolver.ts
│ │ SwaggerConfig.ts
└──models
│ │ Class_1.ts
│ │ Class_2.ts
│ │ [...]
└──providers
│ │ index.ts
│ │ provider_1.ts
│ │ provider_2.ts
│ │ [...]
│ └───api
│ │ provider_Class_1.ts
│ │ provider_Class_2.ts
│ │ [...]
└──pages
│ index.ts
└───page_1
│ │ page_1.ts
│ │ page_1.html
│ │ page_1.scss
└───page_2
│ │ page_1.ts
│ │ page_1.html
│ │ page_1.scss
│ └───page_2_subpage_1
│ │ │ page_2_subpage_1.ts
│ │ │ page_2_subpage_1.html
│ │ │ page_2_subpage_1.scss
│ │ └───page_2_subpage_1_subpage_1
│ │ │ │ page_2_subpage_1_subpage_1.ts
│ │ │ │ page_2_subpage_1_subpage_1.html
│ │ │ │ page_2_subpage_1_subpage_1.scss
│ │ └───[...]
│ └───[...]
└───[...]
52
Por tanto:
- El componente principal de la aplicación está en la carpeta app, junto los archivos de
configuración.
- Cada componente posee: Un CSS interno, la clase del mismo con una etiqueta
representativa para el HTML que pueda llamarlo y por último su HTML.
- Todas las páginas (1) y proveedores (2) son importadas en el archivo index.ts, para
luego ser importado dicha carpeta en la configuración del proyecto (app.module.ts).
1. APP_PAGES es incluido como una declaración y componentes a compilar
import { APP_PAGES } from '../pages/index';
[...]
declarations: [
MyApp,
APP_PAGES
],
[...]
entryComponents: [
MyApp,
APP_PAGES
],
2. APP_PROVIDERS es importado junto el resto de proveedores:
import { APP_PROVIDERS } from '../providers';
[...]
providers: [
APP_PROVIDERS,
[...]
]
- Cada página puede tener subpáginas dentro, esto sirve para estructurar en carpetas
vistas que dependen de otras o son utilizadas por estas. Por ejemplo, en la pestaña
del perfil, se puede encontrar el historial de objetos del usuario como otro
componente interno.
- La carpeta api tiene como objetivo abstraer al cliente del acceso al servicio API
Rest, así, en caso de cambiar una ruta del API Rest, solo deba ser cambiado en un
lugar y además todas estas URL estén localizadas con facilidad.
53
7. Seguridad
7.1. Separación parte pública privada y administración del API
Rest
El API soporta todo tipos de consultas ya que son requeridas a la hora de ser administrado
mediante una herramienta externa. Esto puede ocasionar un problema a la hora de clasificar
las peticiones de acuerdo a quién la utiliza y crear problemas a la hora de compartir
controlador entre distintos clientes del API debido a que tienen necesidades distintas.
Por tanto, es necesario separar del modo más claro posible las URL utilizadas por cada
cliente API Rest. Con esto se consigue que, mediante una ruta predefinida, puedan
controlarse todas las rutas hijas de la misma.
Para realizar esto, se han definido 2 rutas:
● /private/**
○ Todas sus subrutas requieren un token cuyo id de usuario que posea dicho
token coincida con el id de usuario proporcionado en la URL.
Figura 34: Seguridad: Acceso a rutas privadas. Fuente: elaboración propia
Los datos del ejemplo son ficticios, el token se obtiene tras iniciar sesión.
54
● /admin/**
○ Se requiere:
■ El usuario debe ser de tipo administrador.
■ El token debe coincidir con el del usuario.
■ Debe además coincidir el segundo token de seguridad global de
administración.
Figura 35: Seguridad: Acceso a rutas referentes a administración. Fuente: elaboración propia
Los datos del ejemplo son ficticios, el token se obtiene tras iniciar sesión.
7.2. Uso de contraseñas y librerías necesarias
Para el cifrado de las contraseñas se utiliza un hash generado mediante sha256 a partir de
la contraseña en claro.
Las contraseñas son siempre cifradas en el cliente y enviadas al servidor, evitando, en la
medida de lo posible una captura de datos por parte de un atacante mediante un ataque, por
ejemplo de man in the middle6.
Para ello se utilizarán 3 librerías:
Cliente:
El cliente tiene definido el siguiente método, en el que a partir de un string obtiene el hash
utilizando SHA-256:
//File: /reciclaClient/src/providers/encryptProvider.ts
6 "Ataque de intermediario - Wikipedia, la enciclopedia libre."
https://es.wikipedia.org/wiki/Ataque_de_intermediario.
55
export class EncryptProvider {
constructor() { }
encryptPassword(password: string): string {
let shaObj = new jsSHA("SHA-256", "TEXT");
shaObj.update(password)
let hash = shaObj.getHash("HEX");
return hash
}
}
La librería utilizada es jsSHA7 instalada mediante node.
Administración:
Para la administración en cambio, se utiliza otra librería: sha2568. Esta librería es utilizada al
iniciar sesión mediante un usuario de tipo “Admin” y su respectiva contraseña.
hash = sha256(password)
Servidor:
Por defecto, el framework utilizado en la plataforma de administración envía las contraseñas
en claro, siendo esta característica un defecto. Para solventar el problema se ha decidido
cifrar la contraseña en el lado del servidor.
Para cifrar la contraseña se utiliza la librería java.security9 convirtiendo a un array de
bytes el string, y tras esto, obteniendo el hash correspondiente utilizando sha-256.
7.3. Peticiones API REST abiertas
El API dispone de una serie de peticiones a las que cualquier usuario puede acceder. Estas
URL, sin embargo, tienen referencias a entidades cuyos campos son privados. Por tanto, sin
añadir su correspondiente capa de seguridad, con una simple petición al servidor se podría
obtener toda la información de un usuario.
7 "jssha - npm." 10 jun.. 2017, https://www.npmjs.com/package/jssha. 8 "sha256 - npm." 18 mar.. 2015, https://www.npmjs.com/package/sha256. 9 "java.security (Java Platform SE 7 ) - Oracle Help Center."
https://docs.oracle.com/javase/7/docs/api/java/security/package-summary.html.
56
Para solucionar este problema, a la hora de devolver datos personales, se crean nuevas
instancias de esos objetos incluyendo en ellos únicamente los atributos que sean
necesarios. Ejemplo:
HTTP GET https://reciclaweb-server.herokuapp.com/recycleItems/latest/?page=0&perPage=20
Respuesta:
"userList": [
[...]
{
"id": 39,
"email": null,
"password": null,
"username": null,
"fullName": "Alberto Rico García",
"profilePicture":
"https://reciclaweb.000webhostapp.com/uploads/avatars/-
1_1525890453340.png",
"accessToken": null,
"createdDate": null,
"type": null,
"lastPosition": null,
"recycleItems": null,
"points": 0,
"gamePoints": 0,
"lastGameDate": null,
"questionsDone": null,
"enabled": false,
"collective": null,
"birthdate": null,
"school": null,
"gender": null,
"resetPwdCode": null,
"resetPwdCodeDate": null
},
Como se puede comprobar, dicha petición solo requiere del nombre, id e imagen del perfil,
por tanto, son los únicos atributos que son escogidos a la hora de construir la respuesta:
57
Figura 36: Seguridad: Seguridad en el acceso a datos. Fuente: elaboración propia
7.4. Tokens y regeneración de tokens
Desde un principio, la plataforma fue pensada para utilizar tokens, puesto que inicialmente,
eran necesarios para la validación de un usuario de redes sociales. Conforme el desarrollo
fue avanzando, aparecieron los usuarios normales y contraseñas. En este momento se
comenzó a replantear el tema de las sesiones, tokens y rangos de usuario.
Problemas encontrados:
● El token es generado únicamente al iniciar sesión.
○ Un atacante podría cambiar datos del usuario conociendo el token.
● Existe una restricción que indica que la sesión nunca se debe cerrar.
○ El usuario debe tener la sensación de que la aplicación funciona siempre, sin
tener que pedir sus credenciales de nuevo, a no ser que cierre sesión.
● El token, por tanto nunca cambia.
Para solucionar estos problemas se plantearon 2 posibles soluciones:
● Regenerar token al guardar el usuario.
● Añadir tiempo de vida a los token, creando en cada petición un segundo token
almacenado continuamente por la aplicación que al dejar de funcionar el primero, se
utilice éste, reemplazando el primero.
58
La segunda opción planteada suponía un alto coste en cuanto a tiempo y recursos, por
tanto, al ser actualizado el usuario constantemente al almacenar ítems de reciclaje, se ha
decantado por la primera opción.
Para la generación y posterior regeneración de tokens se ha utilizado identificadores guid:
java.util.guid, generados desde el servidor:
userFound.setAccessToken(UUID.randomUUID().toString());
userFound = userService.saveUser(userFound);
[...]
return new ResponseEntity<>(userFound, HttpStatus.OK);
Por tanto, al ser actualizado el token en la base de datos el usuario, debe ser actualizado
también en el cliente. Para ello, se ha programado la actualización automática de la sesión.
//File: /reciclaClient/src/providers/api/userProvider.ts
return this.http.put(this.config.apiEndpoint + "/private/users/" + user.id + parameters,
JSON.stringify(user),
this.requestJsonOptions).timeout(this.config.defaultTimeoutTime).map(res => {
this.sessionProvider.updateSession(res.json())
return Observable.of(res.json())
}, error => {
return Observable.of(error)
})
7.5. Control de cambios no permitidos mediante peticiones
HTTP
De igual modo que un usuario puede modificar un atributo de su usuario, puede modificar
otro mediante una petición HTTP al servidor ya que el servidor almacena todo el usuario que
recibe como entrada.
Por tanto, debe controlarse qué campos deben ser actualizados y cuales no deben, como es
el caso de los puntos del usuario, por ejemplo. El servidor, a la hora de actualizar un
usuario, busca el usuario que posea dicho identificador único (id), y actualiza los datos del
usuario que no deben cambiar con esos datos:
//PUT: "/private/users/{id}"
User currentUser = userService.findById(id);
[...]
//Estos valores no deben cambiar, por tanto, se dejan como estaban
user.setId(currentUser.getId());
user.setUsername(currentUser.getUsername());
user.setCreatedDate(currentUser.getCreatedDate());
59
user.setType(currentUser.getType());
user.setPoints(currentUser.getPoints());
user.setGamePoints(currentUser.getGamePoints());
7.6. Sistema de logs
En ocasiones, una plataforma software puede sufrir problemas o debe almacenar
información que pueda ser útil. Por ello, se ha creado un sistema de logs cuya finalidad es
almacenar:
● Excepciones ocasionadas en el servidor.
● Peticiones no autorizadas y el contenido de las mismas.
● Anotaciones junto a sus imágenes no encontradas en la base de datos.
Esta entidad, por tanto, tiene un constructor con sobrecarga para inicializar un objeto que
posteriormente será añadido.
AppLog appLog = new AppLog(HttpStatus.UNAUTHORIZED, "Unauthorized",
this.extractPostRequestBody(request) ,request.getRequestURI());
this.appLogService.saveAppLog(appLog);
Sus campos son: Hora en la que se originó el evento, estado HTTP de respuesta en formato
numérico junto su significado, el título de la excepción, el mensaje, la URL utilizada al
realizar la petición al servidor y por último, una imagen en base64 en caso de ser una
anotación no encontrada.
En el panel de administración se podrá ver con detalle cada log, incluyendo la imagen en
caso de no ser vacío dicho atributo.
7.7. Inicio de sesión mediante redes sociales
Un usuario que utiliza las redes sociales para iniciar sesión nunca utiliza la contraseña, por
tanto, se utiliza el id del usuario para identificarlo. A la hora de iniciar sesión de un usuario
ya registrado mediante redes sociales se planteó el siguiente problema:
60
Figura 37: Seguridad: Problema de acceso por redes sociales. Fuente: elaboración propia
Paso 3.2 y 5.2 son alternativas al paso 3 y 5.
El paso 3.2 es el primer paso realizado por el atacante.
Como se puede ver en la imagen superior, un atacante podría iniciar sesión conociendo
únicamente el id del usuario inyectando su propio token que podría utilizar posteriormente
para guardar datos de usuario.
Para solucionar este problema, se revisó el API de las redes sociales que la plataforma
utiliza, en este caso Instagram y Facebook. Ambas, a través de únicamente el token de
autenticación podían validar un usuario. Por ello se empleó dichas URL para obtener de
ellas el id del usuario:
Para Facebook10:
JSONObject fbUser =
JsonReader.readJsonFromUrl("https://graph.facebook.com/me/?access_token=" + token);
username = fbUser.getString("id");
user = this.userService.findByUsername(username);
10 "Identificadores de acceso - Inicio de sesión con Facebook."
https://developers.facebook.com/docs/facebook-login/access-tokens?locale=es_ES.
61
Para Instagram11:
JSONObject instagramUser =
JsonReader.readJsonFromUrl("https://api.instagram.com/v1/users/self/?access_token=" +
token);
username = instagramUser.getJSONObject("data").getString("id");
user = this.userService.findByUsername(username);
Para realizar esta acción se necesitará leer el JSON obtenido como respuesta, por tanto se
utilizará la clase JsonReader para:
1. Convertir la respuesta en un String.
2. Convertir String a JSONObject.
3. Devolver JSONObject.
Por tanto, una vez autentificado tanto en el servidor como en el cliente devolverá el usuario
con el token actualizado. Por tanto los pasos seguidos quedarían como indica la siguiente
imagen:
Figura 38: Seguridad: Inicio de sesión mediante redes sociales. Fuente: elaboración propia
11 "Instagram API." https://www.instagram.com/developer/.
62
8. Distribución de funcionalidades
Tabla 12: Funcionalidad 1: Buscar tipo de objeto a partir de una imagen. Fuente: elaboración propia
#1 Buscar tipo de objeto a partir de una imagen
El sistema a partir de una imagen debe obtener el tipo del objeto.
Servidor A partir de una lista de nombres debe buscar en la bases de datos el primero que coincidan, en orden de mayor éxito obtenido mediante Google Vision.
Cliente Una vez obtenida la lista de nombres se llama al API Rest y se recoge el tipo obtenido, en caso de no encontrarlo, se pedirá al usuario elegir un tipo o cancelar si no lo conoce.
Tabla 13: Funcionalidad 2: Buscar punto más cercano a partir de un tipo de objeto. Fuente: elaboración propia
#2 Buscar punto de reciclaje más cercano a partir de un tipo de objeto
El sistema a partir de un tipo de objeto debe mostrar el punto más cercano.
Servidor De acuerdo al tipo de objeto, devolverá una lista de puntos que posean contenedores de dicho tipo.
Cliente
A partir de la lista, debe encontrarse el punto más cercano al usuario, mostrando un mapa con el objeto y el punto encontrado.
● En caso de querer volver, mostrará una alerta para asegurarse de realizar dicha acción.
Tabla 14: Funcionalidad 3: Cambiar tipo y/o nombre y mostrar ruta. Fuente: elaboración propia
#3 Cambiar tipo y/o nombre del objeto y mostrar ruta
El usuario podrá modificar el tipo de objeto o su nombre en el mapa.
Servidor -
Cliente
En el menú superior existirá la posibilidad de modificar dichos valores en caso de que el usuario lo desee, además de poder ver la ruta al punto de reciclaje.
● En caso de querer ver la ruta, mostrará una alerta para asegurarse de realizar dicha acción.
● Al cambiar el tipo volverá a calcular el punto de reciclaje más cercano.
Tabla 15: Funcionalidad 4: Finalizar reciclaje. Fuente: elaboración propia
63
#4 Finalizar reciclaje
El usuario podrá finalizar el reciclado.
Servidor El servidor deberá almacenar los datos correspondientes a dicho reciclado.
Cliente
En el menú superior existirá la posibilidad de finalizar, preguntando al usuario de si está seguro y redirigiendo al historial de dicho usuario tras ser almacenado el objeto en la base de datos.
● Se actualizará la vista de inicio de la aplicación mostrando el avatar como el primero de la lista y mostrando al comienzo de la lista de objetos el objeto almacenado.
● Se actualizará el historial de objetos reciclados del usuario.
Tabla 16: Funcionalidad 5: Registro e inicio de sesión mediante Facebook e Instagram. Fuente: elaboración propia
#5 Registro e inicio de sesión mediante Facebook e Instagram.
El usuario podrá registrarse utilizando dichas redes sociales.
Servidor El servidor deberá almacenar el usuario al registrarse o comprobar la veracidad de esas cuentas e iniciar sesión.
● Solo podrá haber 1 sesión abierta por usuario.
Cliente Deberán aparecer en la vista de inicio de sesión 2 botones los cuales estarán más a la vista en caso de querer utilizar las redes sociales.
Tabla 17: Funcionalidad 6: Registro e inicio de sesión normal. Fuente: elaboración propia
#6 Registro e inicio de sesión normal
El usuario podrá registrarse utilizando su correo electrónico.
Servidor El servidor deberá almacenar el usuario al registrarse o comprobar los datos al iniciar sesión.
Cliente Deberán aparecer en la vista de inicio de sesión 2 opciones para registrarse o iniciar sesión.
● Para el registro solo se requerirá el usuario y contraseña.
Tabla 18: Funcionalidad 7: Modo Debug. Fuente: elaboración propia
64
#7 Modo Debug
El administrador podrá activar un modo debug para poder probar la aplicación desde el navegador.
Servidor -
Cliente
Se podrá activar el modo debug desde el archivo de configuración del proyecto, permitiendo:
● Inicio de sesión más rápido mediante usuario debug. ● Buscar objetos a partir de un tipo, evitando requerir los permisos de
Android e iOS. ● Mostrar un mensaje en la vista del mapa indicando que no está
disponible en la versión del navegador.
Tabla 19: Funcionalidad 8: Recuperar contraseña. Fuente: elaboración propia
#8 Recuperar contraseña
El usuario podrá crear una nueva contraseña a partir de un código generado.
Servidor Deberá generar el código, enviarlo por correo y comprobar que sea correcto posteriormente.
● El código debe tener una validez de 24 horas.
Cliente ● A partir de un correo generará un código que es recibido por email. ● Redirigirá a otra vista en la que pedirá el correo, el código y una nueva
contraseña e iniciará la sesión.
Tabla 20: Funcionalidad 9: Ranking. Fuente: elaboración propia
#9 Ranking
El usuario podrá ver el ranking de los usuarios que más han reciclado.
Servidor Devuelve un ranking con los usuarios (con los datos imprescindibles) que no sean de tipo administrador.
Cliente Imprime el ranking en la vista dedicada a ello.
Tabla 21: Funcionalidad 10: Inicio de sesión de usuario social con contraseña. Fuente: elaboración propia
#10 Iniciar sesión con un usuario social desde inicio de sesión normal
El usuario social podrá añadirse un correo (no existente en la base de datos) y una contraseña e iniciar sesión de modo normal.
Servidor En caso de no encontrar el usuario mediante las redes sociales, buscará mediante el token de usuario.
65
Cliente Se generarán 2 tipos de token, uno desde Facebook y otro iniciando sesión normal.
Tabla 22: Funcionalidad 11: Editar perfil. Fuente: elaboración propia
#11 Editar información del usuario
El usuario podrá modificar: Correo, foto del perfil, nombre, contraseña, género, escuela y colectivo al que pertenece, y año de nacimiento.
Servidor Almacenaje de los datos.
Cliente
Se crearán 3 vistas para los datos principales: 1. Nombre y foto. 2. Contraseña. 3. Datos restantes.
● El colectivo se podrá elegir entre: PDI, PAS, Alumno (por defecto) y
externo. ● Año por defecto: Fecha de registro. ● Nombre por defecto: “Mi nombre”. ● Género se podrá elegir entre: Masculino, Femenino, Otro (Por defecto). ● Al editar los campos se actualizará la vista del perfil y la vista de inicio.
Tabla 23: Funcionalidad 12: Ver perfil. Fuente: elaboración propia
#12 Ver perfil
El usuario podrá ver en su perfil todos sus datos.
Servidor -
Cliente Mostrar el perfil recuperado de la sesión.
Tabla 24: Funcionalidad 13: Ver historial del usuario. Fuente: elaboración propia
#13 Ver historial del usuario
El usuario podrá ver la lista de ítems que ha reciclado junto en una pestaña junto el perfil.
Servidor Devolver la lista paginada de objetos que el usuario ha reciclado.
Cliente
Mostrar un listado limitado de objetos. ● En caso de mover la lista hasta el final de ella, obtener la siguiente
página de la lista. Realizar esta acción hasta llegar al límite de objetos reciclados del usuario.
● En caso de hacer click en el icono del menú inferior, subir al comienzo de la lista.
66
Tabla 25: Funcionalidad 14: Listar últimos reciclajes. Fuente: elaboración propia
#14 Listar últimos reciclajes
EL usuario podrá ver el historial de la aplicación de ítems reciclados.
Servidor Devolver una lista paginada de todos los usuarios junto a la lista de objetos reciclados.
Cliente
Mostrar un listado limitado de objetos. ● En caso de mover la lista hasta el final de ella, obtener la siguiente
página de la lista. Realizar esta acción hasta llegar al límite de objetos registrados en la base de datos.
● En caso de hacer click en el icono del menú inferior, subir al comienzo de la lista.
● En caso de mover la vista hacia abajo en el comienzo de la lista, deben añadirse nuevos objetos en caso de ser actualizada la base de datos.
Tabla 26: Funcionalidad 15: Listar últimos usuarios reciclando. Fuente: elaboración propia
#15 Listar últimos usuarios reciclando
El usuario podrá ver un listado de usuarios en la vista de ítems reciclados.
Servidor Devolver una lista paginada de todos los usuarios junto a la lista de objetos reciclados. (#13)
Cliente
Mostrar un listado limitado de usuarios. ● En caso de mover la lista de objetos hasta el final de ella, obtener la
siguiente página de la lista y actualizar los usuarios. Realizar esta acción hasta llegar al límite de objetos registrados en la base de datos.
● En caso de mover la vista hacia abajo en el comienzo de la lista, debe: ○ Desplazar los usuarios al comienzo de la lista en caso de que
un usuario que ya estaba en la lista recicle un nuevo objeto. ○ Añadir un usuario al comienzo la lista de usuarios en caso de
ser actualizada la lista de objetos de la base de datos.
Tabla 27: Funcionalidad 16: Adivina dónde se recicla. Fuente: elaboración propia
67
#16 Adivina dónde se recicla
El usuario podrá participar en un juego de preguntas y respuestas y ganar puntos.
Servidor Debe devolver una pregunta aleatoria que el usuario no haya realizado aún.
● Solo si ha pasado 24 horas desde su última respuesta.
Cliente
Mostrar la pregunta junto sus 4 posibles respuestas. ● Solo una es correcta. ● Debe mostrar un mensaje de verificación al seleccionar una respuesta. ● Al responder la pregunta debe aparecer si ha acertado o no y la
pregunta. ○ En caso de no acertar debe aparecer la respuesta correcta.
● Si ha respondido todas las preguntas disponibles deberá aparecer un mensaje indicandolo.
● En caso de actualizar la vista se mostrará otra pregunta aleatoria.
Tabla 28: Funcionalidad 17: Consejos sobre el reciclaje. Fuente: elaboración propia
#17 Consejos sobre el reciclaje
El administrador podrá añadir consejos sobre el reciclado.
Servidor Debe devolver un consejo aleatorio.
Cliente El consejo se mostrará en la vista de reciclar. En caso de actualizar la vista, debe actualizarse el consejo (puede ser el mismo puesto que es aleatorio).
Tabla 29: Funcionalidad 18: Sistema de logs. Fuente: elaboración propia
#18 Sistema de logs
El administrador desea controlar si se producen excepciones en el servidor o fallos de autenticación.
Servidor
Capturar y almacenar: ● Fallos de autenticación. ● Errores en el servidor. ● No encontrar el tipo de objeto a partir de lista de nombres obtenida
mediante Google Vision.
Cliente -
Tabla 30: Funcionalidad 19: Administración. Fuente: elaboración propia
68
#19 Administración
El administrador desea administrar todas las entidades de la base de datos.
Servidor
Creación de panel de administración para realizar CRUD de todas las entidades.
● El usuario administrador no aparecerá en el ranking. ● El administrador no podrá iniciar sesión en la aplicación, tan solo en el
panel de administración. ● Un usuario de tipo administrador no podrá cambiar el tipo. ● Solo podrá haber 1 sesión abierta por usuario.
Cliente -
9. Tecnologías
9.1. Servidor
El servidor es el pilar maestro de la aplicación, puesto que es el único que posee los
permisos necesarios para acceder a los datos de la base de datos.
A la hora de elegir un framework para este apartado de la plataforma no se han encontrado
grandes diferencias entre unos lenguajes y otros, por lo que se ha tratado de buscar,
objetivamente, el framework cuya comunidad y/o inclusión en la vida laboral está más
presente.
Por tanto, se ha realizado una búsqueda para conocer el número de oportunidades laborales
(Rocca, 2017), teniendo en cuenta los siguientes lenguajes:
Tabla 31: Ofertas de empleo de acuerdo al lenguaje de programación. Fuente: elaboración propia
Lenguaje Número de ofertas laborales
Java 68918
Python 57546
Javascript 39319
69
Ruby 22838
PHP 14633
Datos obtenidos de Indeed el día 28/05/2018.
Partiendo del lenguaje, tanto Java como Python, están en cabeza con una clara diferencia,
pero se puede hacer una comparación de acuerdo a los principales frameworks:
Tabla 32: Ofertas de empleo de acuerdo a los frameworks más populares. Fuente: elaboración propia
Lenguaje Framework Número de ofertas laborales
Ruby Rails 18377
Java Spring 12530
Java Play 4807
Python Django 2050
Javascript Express 1203
PHP Laravel 665
PHP Symfony 307
Javascript Meteor 101
Datos obtenidos de Indeed el día 28/05/2018.
En este caso, Rails se trata de un framework claramente más utilizado hoy en día para
construir un proyecto web, sin embargo, su utilización puede reducirse a ese campo puesto
que el 80,46% de las ofertas del lenguaje en su totalidad se reduce a dicho framework. Por
tanto, puede ser menos útil en caso de que ya esté o vaya a trabajar en diversos proyectos.
PHP en este caso, es más famoso para otro tipo de servicios, sin embargo, el uso de este
lenguaje para esta finalidad se ve reducido considerablemente.
Javascript, al tratarse de un lenguaje con una gran ventaja en el desarrollo al frontend, cada
día es más famoso. No obstante, para realizar tareas de backend no tiene datos tan
significativos.
Por último el lenguaje Java, junto sus dos más famosos frameworks en este campo, están
muy presentes hoy en día en el mercado laboral puesto que es un lenguaje que puede estar
en una multitud de diferentes proyectos además del desarrollo web.
70
Además, existen multitud de tablas comparativas de acuerdo a su uso en la actualidad, en
este caso, Spring se encuentra en primera posición con una alta ventaja estando spring boot
mejorando poco a poco su posición en el ranking como se puede ver en el siguiente
diagrama.
Por tanto ha sido escogido java junto su framework más conocido (Spring) encargado de
actuar como backend puesto que se trata de un lenguaje muy utilizado en el mundo laboral y
por tanto, la curva de aprendizaje es mucho menor, además de su posible integración con
otros proyectos
9.1.1. Maven
Dado que se requiere automatizar el proceso de construcción del backend, es necesario
utilizar una herramienta que permita crear un ciclo de vida. En este caso, se ha optado por
maven.
Esta herramienta permite de un modo sencillo, agregar librerías o alterar el proceso de
construcción del proyecto. Por ejemplo, para utilizar Heroku se requiere la creación de un
JAR que posea la clase main del proyecto.
Para realizar esto, utilizando el plugin maven-jar-plugin se puede indicar que se utilice la
clase que se desee de la carpeta main del proyecto.
Es recomendable consultar antes de añadir una dependencia/plugin la última versión12.
9.1.2. Spring Boot Framework
Debe añadirse al fichero pom.xml la siguiente dependencia como indica la guía oficial13:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.RELEASE</version>
</parent>
<dependencies>
12 "Maven Repository." https://mvnrepository.com/. 13 "Guía básica de inicio." https://projects.spring.io/spring-boot/.
71
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
Para la fachada API Rest se ha optado por utilizar un Framework actual, utilizado por una
amplia mayoría de desarrolladores permitiendo:
- Desarrollar el backend en java.
- Uso de la herramienta Maven.
- Respuestas en formato JSON, permitiendo leer los datos rápidamente.
- Direcciones URL amigables, para crear una fachada RestFul.
9.1.4. JPA
Para el acceso a la base de datos se utilizará JPA, más concretamente, una librería de
spring que permite su integración. Esta API permite la persistencia de los datos y abstrae su
funcionamiento del tipo de bases de datos utilizado.
Spring proporciona una guía14 donde explica todas sus posibles variantes.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
9.1.5. PostgreSQL
Heroku ofrece de manera gratuita una base de datos utilizando esta tecnología, por tanto,
se ha optado por utilizar este sistema de gestión de bases de datos.
Para ello se añadirá al fichero pom la siguiente dependencia:
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.2</version>
14 "Spring Data JPA - Reference Documentation." 8 may.. 2018, https://docs.spring.io/spring-
data/jpa/docs/current/reference/html/.
72
</dependency>
9.1.6. Jackson
A la hora de responder el servidor a la petición del usuario, mediante JPA, requiere ser
enviado el objeto completo para todos sus atributos. Por tanto, esto puede llegar a ser un
problema si se posee objetos complejos ya que se requiere pasar como parámetro todos los
objetos que contenga y no simplemente sus referencias.
Por ello, se ha requerido utilizar la librería Jackson que permite enviar un atributo
simplemente por una referencia a éste. En este caso, dicho atributo será la clave principal
(id) del objeto puesto que es única y sirve para identificar a dicho objeto.
Por tanto, debe añadirse al fichero de configuración del proyecto (pom.xml) la siguiente
referencia:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.5</version>
</dependency>
9.1.7. Envío de correos
A la hora de comenzar a utilizar los usuarios no registrados mediante redes sociales, se
planteó un problema. ¿Y si un usuario pierde su contraseña?
Por tanto, se tuvo que idear un modo de recuperar la cuenta de usuario, y se decidió utilizar
el correo electrónico para ello. Para esto, se ha decidido utilizar la librería javax.mail, para
ello debe añadirse la siguiente dependencia:
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>
Por tanto, en la clase SendMail se utilizará el método sendRecoverMail pasandole el
usuario los atributos de un objeto SendMail con los datos necesarios. Por tanto, un HTML es
rellenado mediante con los datos necesarios y es enviado al usuario mediante GMail.
73
Sin embargo, la escritura en dicho HTML plantea un problema, puesto que se requiere
añadir una librería más para poder desarrollar dicha característica.
9.1.7.1. Creación del HTML a partir de una plantilla
Para generar el HTML necesario a la hora de enviar el correo, se ha decidido utilizar la
librería jsoup.
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.3</version>
</dependency>
Una vez añadida dicha dependencia, se creará un String mediante el fichero HTML alojado
en la carpeta resources: /resources/emailRecoverPassword.html
Y se localiza el elemento a modificar: "span[id^=code-recover-password]"
Modificando el contenido de dicha etiqueta.
74
9.1.8. Swagger UI
El API al ser abierto, contiene una serie de consultas a las que cualquier persona puede
utilizar, para informarse o para desarrollar. Sin embargo, Spring Boot por defecto, no indica
cuales son las URL a las que se puede acceder mediante peticiones HTTP.
Para agregar este complemento se ha añadido al pom la siguiente dependencia:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.8.0</version>
</dependency>
Para visualizar dicha lista de direcciones se ha utilizado Swagger UI. Esta herramienta
proporciona la generación de una web para visualizar de un modo sencillo qué peticiones al
API Rest existen. En este caso, se muestran las URL privadas, administrativas y públicas
existentes en el proyecto:
https://reciclaweb-server.herokuapp.com/swagger-ui.html
Figura 39: Swagger. Fuente: elaboración propia
9.2. Cliente
La principal funcionalidad del cliente es dotar al usuario de una interfaz amigable, intuitiva y
moderna para poder utilizar el sistema. El cliente, que en este caso se trata de una
75
aplicación para dispositivos móviles, la cuál actua de interfaz puesto que los datos de
usuarios son obtenidos mediante peticiones HTTP al servidor.
9.2.1. Ionic Framework
Puesto que existen usuarios tanto de iOS como Android, se ha decidido utilizar una
plataforma común, desarrollando así para ambas plataformas al mismo tiempo.
Este framework es híbrido, por tanto, funciona en diferentes sistemas operativos como si de
una página web se tratara y además utiliza características propias del sistema operativo
mediante el uso de plugins (cordova).
Por tanto utiliza:
- AngularJS que en este caso es la versión 4 del mismo.
- Apache Cordova (mediante sus plugin) para acceder a características del
dispositivo móvil.
- Typescript incorporado junto AngularJS por defecto para sustituir a Javascript dado
que aporta funcionalidades para el desarrollo más útiles.
9.2.2. Apache Cordova
Como se ha descrito previamente, la aplicación está basada en Angular2+15, y por tanto,
está basado en tecnologías web. Para utilizar las funcionalidades del móvil por tanto, es
empleado Apache Cordova mediante el uso de plugins.
En este caso se han utilizado los siguientes plugins:
Tabla 33: Plugins para la cámara. Fuente: elaboración propia
"cordova-plugin-camera", "cordova-plugin-crop"
Utilización de la cámara del dispositivo y recortar imagen para no descuadrar a la hora de
ser impresa por pantalla.
Tabla 34: Plugins para la localización 1. Fuente: elaboración propia
"cordova-plugin-geolocation", "cordova-plugin-googlemaps"
Obtención de la ubicación del usuario y vista de mapas a través de Google Maps.
15 "Angular." https://angular.io/.
76
Tabla 35: Plugins para la localización 2. Fuente: elaboración propia
"cordova-plugin-request-location-accuracy"
Obtención de permisos al usuario para obtener su ubicación.
Tabla 36: Plugin para el almacenamiento de la sesión local. Fuente: elaboración propia
"cordova-sqlite-storage"
Guardar variables de sesión: Usuario y mostrar (o no) ayuda.
Tabla 37: Plugin para la transferencia de archivos. Fuente: elaboración propia
"cordova-plugin-file", "cordova-plugin-file-transfer"
Manipulación de ficheros y subir éstos a servidor FTP.
Tabla 38: Plugin para la integración de Facebook. Fuente: elaboración propia
"cordova-plugin-facebook4"
Inicio de sesión mediante Facebook16
Para instagram en este caso, la autenticación se realiza mediante una petición HTTP a su
API17.
16 "Integración con Facebook." https://github.com/bertus193/reciclaWeb/wiki/Integración-con-
Facebook. 17 "API Endpoints • Instagram Developer Documentation."
https://www.instagram.com/developer/endpoints/.
77
9.2.3. API Google Vision
A la hora de realizar la funcionalidad más importante de la aplicación, la búsqueda del
nombre del objeto a partir de una imágen, debe pensarse un modo de lograrlo utilizando
tecnologías externas. Aquí es donde entra en escena una nueva API cuya funcionalidad es
precisamente ésta, el API de Google Vision.
A diferencia de otras API de reconocimiento de imágenes abiertas y gratuitas, esta tiene un
mayor alto de precisión, como se puede apreciar en la siguiente imagen perteneciente a un
artículo comparativo de tecnologías similares (Oberoi, 2016):
Figura 40: Reconocimiento de objetos a través de una imagen, comparativa. Fuente: https://goberoi.com/
Como se puede observar en esta imagen o en otras imágenes del artículo, el API que tiene
más posibilidades de acertar es el de Google Vision al acercarse más desde el primer
resultado obtenido a la imagen utilizada.
El uso del API es muy sencillo, tan solo es requerido realizar una petición HTTP mediante un
JSON al API. Para ello, habrá que indicar en este JSON la imagen en formato base64 o url y
la clave de usuario como parámetro de la URL. El API devolverá los resultados obtenidos
también en formato JSON18. Ejemplo:
18 "Make a Vision API request | Cloud Vision API Documentation | Google ...." 8 mar.. 2018,
https://cloud.google.com/vision/docs/request.
78
{
"responses": [
{
"labelAnnotations": [
{
"mid": "/m/01lsmm",
"description":
"scissors",
"score": 0.950474,
"topicality": 0.950474
},
{
"mid": "/m/03qtgkw",
"description":
"hardware",
"score": 0.70176554,
"topicality": 0.70176554
},
{
"mid": "/m/02rdsp",
"description": "office supplies",
"score": 0.68955964,
"topicality": 0.68955964
},
{
"mid": "/m/07k1x",
"description": "tool",
"score": 0.6190788,
"topicality": 0.6190788
},
{
"mid": "/m/0mwc",
"description": "angle",
"score": 0.5667044,
"topicality": 0.5667044
}
]
}
]
}
Sin embargo, el API presenta el problema en cuanto a su exactitud, puesto que suele
acertar, sin embargo, si se trata de un objeto muy concreto suele fallar. Esto es un problema
cuando, por ejemplo, se quiere diferenciar un portaminas de un bolígrafo.
Figura 41: Ejemplo de reconocimiento de un objeto. Fuente: elaboración
propia
79
9.3. Administración
La administración del sitio, no menos importante, es muy importante puesto que evita el
acceso a los datos directamente desde la base de datos y resulta más cómodo para un
usuario que no entiende de programación, que es quién al fin de al cabo, administra la
aplicación cada día.
Se han planteado distintas alternativas para desarrollar el panel de administración:
Tabla 39: Alternativas para el desarrollo de la administración: LightAdmin. Fuente: elaboración propia
#1 LightAdmin19
Ventajas - Generar panel de administración en muy pocos pasos. - Panel directamente en el servidor.
Desventajas - No es compatible con las versiones actuales de Spring Boot.
Tabla 40: Alternativas para el desarrollo de la administración: JHipster. Fuente: elaboración propia
#2 JHipster20
Ventajas - Panel de administración completo. - Interfaz adaptable a los dispositivos móviles.
Desventajas - Requiere generar un nuevo servidor.
Tabla 41: Alternativas para el desarrollo de la administración: Admin-On-Rest. Fuente: elaboración propia
#3 Admin-On-Rest21 (Interfaz API Rest)
Ventajas
- Panel de administración completo. - Interfaz adaptable a los dispositivos móviles. - Reemplazable puesto que utiliza una interfaz que cualquier cliente
podría utilizar. - Permite crear definiciones además de las ya creadas.
Desventajas - Muy costoso de implementar, puesto que requiere añadir múltiples
acciones en el API Rest. (CRUD de cada entidad).
Finalmente, se ha decantado por una interfaz API Rest en el servidor utilizada por un cliente
de ésta, puesto que a largo plazo puede ser más versátil ante posibles cambios.
19 "LightAdmin” – Pluggable CRUD Administration Java Framework. Best ...." http://lightadmin.org/. 20 "JHipster." https://www.jhipster.tech/. 21 "GitHub - marmelab/admin-on-rest: A frontend framework for building ...."
https://github.com/marmelab/admin-on-rest.
80
9.3.1. React Native (admin-on-rest)
Admin-On-Rest se trata de un framework orientado al FrontEnd para construir aplicaciones,
en este caso, el panel de administración, utilizando un cliente API Rest. El framework está
basado en React y Material Design, además, puede adaptarse a interfaces móviles además
de soportar complementos.
A la hora de construir el API Rest debe consultarse la guía oficial, no obstante, el framework,
al estar basado en dicha arquitectura software, las peticiones siguen el patrón marcado por
ella. Para ello, han sido definidas peticiones PUT, POST, GET y DELETE, para editar, crear,
obtener y eliminar en dicho orden.
9.4. Control de versiones
El proyecto posee 3 subproyectos:
- Servidor: Spring Boot.
- Cliente: Ionic.
- Administración: React.
Este proyecto utiliza un único proyecto utilizando el control de versiones Git. Para el
almacenamiento del proyecto se ha optado por GitHub22.
Figura 42: Cambios realizados en el repositorio de GitHub. Fuente: elaboración propia
Una gran ventaja de utilizar esta plataforma para subir el código es la posibilidad de
detectar paquetes cuyas versiones no son seguras. GitHub se encarga a la hora de subir un
cambio de comprobar las dependencias y sus versiones, y en caso de comprobar en su
base de datos que una versión tiene problemas de seguridad, avisa de inmediato:
22 "GitHub." https://github.com/bertus193/reciclaWeb.
81
Figura 43: GitHub: Detección de paquetes por GitHub. Fuente: elaboración propia
Una vez detectado el problema, se pueden cambiar las versiones:
Figura 44: GitHub: Aviso de qué paquetes tienen un problema de seguridad. Fuente: elaboración propia
Para el desarrollo del proyecto, se han utilizado 2 ramas, aunque solo existe una rama
pública.
Esta decisión se ha basado a partir de los siguientes motivos:
- 1 único desarrollador, no hay problemas entre versiones de ficheros.
- No existe rama de producción, puesto que la aplicación es utilizada por público real.
Por tanto, la rama utilizada para el desarrollo del proyecto es la rama “master”. Sin embargo,
al ser un repositorio abierto y al existir un servidor donde hay alojado una demostración del
proyecto, se requiere de la configuración del mismo.
Entre las distintas posibilidades que se plantearon para afrontar este problema sin tener que
subir el archivo de configuración al proyecto, y por tanto, ser público, se ha decantado por
utilizar una rama privada, llamada “heroku”. Esta rama, por tanto, si posee una configuración
real y válida del proyecto.
82
El proyecto como se ha indicado anteriormente tiene 3 subproyectos, y cada subproyecto
posee un servidor en el que alojarse, por tanto, se utilizarán una rama por cada subproyecto.
Para crear una rama remota se utilizará el siguiente comando:
$ heroku create reciclaweb-server --remote reciclaweb-server
Dicho nombre proviene la máquina creada previamente en Heroku:
Figura 45: Aplicación de Heroku. Fuente: Heroku
Por último solo falta subir la carpeta en la que se encuentre el servidor (utilizado como
ejemplo):
$ git subtree push --prefix reciclaAdmin reciclaweb-admin master
// En caso de querer hacer push -force:
$ git push reciclaweb-server `git subtree split --prefix reciclaServer
master`:master --force
Sin embargo, es necesario utilizar distintas ramas, ya que no se quiere mostrar en público
las contraseñas de configuración del cliente. Para poder subir los cambios de una rama al
servidor de heroku-client (aplicación ionic en la nube) debe utilizarse el siguiente comando:
$ git push reciclaweb-client `git subtree split --prefix reciclaClient-
heroku heroku`:master --force
En este caso, la rama que se quiere utilizar es la rama “heroku”, y dónde se quiere subir es
a la rama master del repositorio reciclaweb-client.
9.5. Heroku
A la hora de desplegar el proyecto se ha decidido utilizar un servicio PaaS (Product as a
service). Para utilizar este servicio tan solo es necesario indicar un lenguaje de
programación (en este caso: Java y node) y un proyecto Git inicializado.
Heroku, a la hora de nombrar sus máquinas en las que se instala el proyecto que el
desarrollador escoge, lo llama “apps”. Una vez se crea la “app” con un simple comando se
puede subir los cambios del proyecto.
Este servicio en su modo gratuito ofrece:
83
1. Despliegues de distintas aplicaciones en un mismo repositorio23.
2. Base de datos gratuita (PostgreSQL).
3. Aplicación siempre disponible, aunque esta debe ser reactivada si no es utilizada
durante cierto periodo de tiempo (se activa automáticamente al hacer una llamada a
ésta).
9.6. Servidor de ficheros FTP
La aplicación requiere el uso de imágenes creadas por el usuario de la aplicación y su
correspondiente persistencia. Para afrontar este problema se discutieron las 2 posibilidades
existentes, el uso de un servidor mediante el protocolo de transferencia de datos (FTP) o
almacenar las imágenes en formato BASE64 en la base de datos.
Por tanto, se valoraron ventajas y desventajas de ambas posibilidades y se consultó sus
implicaciones a largo plazo de dicha decisión. A continuación se detalla las ventajas e
inconvenientes de utilizar la codificación base64 frente el fichero en formato binario:
Ventajas:
● Mayor facilidad de uso de las imágenes.
● Eliminar necesidad de utilizar un servidor de ficheros FTP.
● Almacenar fichero directamente en la base de datos.
Inconvenientes:
● Imagenes un 33% más grandes.
● Mayor consumo de datos por parte del usuario.
● Empleo de más recursos del sistema para codificar la imagen.
Como se demuestra en la siguiente imagen obtenida de un artículo comparativo24:
Figura 46: Comparativa del formato de almacenamiento de las imagenes. Fuente: www.davidbcalhoun.com
23 "Creación de diversas ramas mediante Heroku."
https://github.com/bertus193/reciclaWeb/wiki/Heroku. 24 "When to base64 encode images (and when not to) | David Calhoun." 28 ago.. 2011,
https://www.davidbcalhoun.com/2011/when-to-base64-encode-images-and-when-not-to/.
84
Se puede confirmar que en formato binario los ficheros siempre ocupan menos espacio, que
incluso comprimidos aún menos. Por tanto, se ha decidido utilizar el formato binario debido a
este decisivo problema.
Para ésto, se ha optado por un servidor de imagenes gratuito, para ello, se han comparado y
probado diferentes alternativas y se ha optado por 000webhost25, que aunque puede que no
sea el mejor del mercado, cumple con las necesidades planteadas de la aplicación. Puesto
que existen múltiples servidores gratuitos y de ellos solo se requiere poder ver y subir
imagenes, no ha sido requerido realizar completa comparación entre éstos.
Las imágenes son subidas mediante un script en PHP que a partir de una petición por parte
del cliente se encarga de subir los ficheros en el servidor, el cuál posee la siguiente
estructura.
public_html
│ upload_avatar.php
│ upload.php
│
└───uploads
│ 1_1.png
│ 1_2.png
│ ...
└───avatars
│ 1_1.png
│ 1_2.png
│ ...
El nombre de la imagen se compone del id del usuario seguido de la fecha actual en un
número entero en milisegundos.
var filename = this.user.id + "_" + date.getTime() + ".png";
10. Justificación de decisiones de implementación
10.1. Servidor
A la hora de crear el API Rest a partir del diseño arquitectural de este se han tenido que
tomar distintas decisiones de acuerdo a los problemas que presentan sus tecnologías.
25 "000Webhost." https://www.000webhost.com/.
85
Problema #1: Relaciones con múltiples atributos relacionados.
A la hora de obtener los datos de la base de datos mediante JPA, como el API ha sido
diseñado para ocultar el ID en caso de repetir un atributo se presenta un problema.
Suponiendo esta relación:
Figura 47: Compartir relaciones a la hora de devolver un JSON. Fuente: elaboración propia
A la hora de devolver un objeto de la clase A JPA es devuelto con la siguiente estructura:
A
| id_a
│ name_a
└───b
| | id_b
| │ name_b
| └───c
| | id_c
| │ name_c
| c = id_c
└─
Como se puede apreciar, como “b” está antes que “c”, primero es devuelto “b”, este a su vez
tiene un “c” que es impreso con normalidad.
El problema es cuando se quiere leer el atributo “c” de la clase A, este es devuelto mediante
el identificador de la clase C (“id_c”), por tanto no puede ser leido el objeto.
Para solucionar esto, existen varias posibilidades, la primera es ir almacenando los objetos
que se sepan pueden repetirse, la otra, es utilizar la etiqueta:
86
@JsonIdentityReference(alwaysAsId = true)
Por tanto, si se utiliza dicha etiqueta con el objeto “c” de la clase B se imprime en la clase
“A” el objeto “c” completo cómo debería.
Problema #2: Almacenar en la base de datos atributos cuando se guarda el objeto.
Cuando es almacenado mediante el método save(), JPA lee las relaciones de la clase a
almacenar, el problema viene con las listas formadas en relaciones @OneToMany. Cuando se
intenta almacenar dicha lista puede aparecer un error indicando que el atributo no es válido.
Para esto, como no es necesario almacenar dicha lista puesto que no es actualizada (tan
solo los principales atributos de la clase a actualizar) se puede utilizar la etiqueta
@Transient evitando la persistencia de dicha lista.
Problema #3: Fechas.
A la hora de crear una fecha hay que tener en cuenta el formato de entrada del JSON, el
problema se presenta cuando se crea una fecha automáticamente mediante la siguiente
instrucción desde el cliente:
new Date().toJSON()
Esta instrucción crea una fecha en el formato ISO 8601, por tanto, si se recibe una fecha en
dicho formato tal y como se indica en la documentación oficial26, debe leerse el parámetro
“X” correspondiente a la zona horaria. Por tanto el patrón utilizado en todas las fechas es el
siguiente:
@JsonFormat(pattern="yyyy-MM-dd'T'HH:mm:ss.SSSXXX") //new Date()
private Timestamp myTimestamp;
Para las fechas, se ha tenido en cuenta un posible problema futuro, las diferencias horarias.
Para ello, todas las fechas junto sus horas tienen asignado su zona horaria, que en este
caso es la zona horaria GMT. Con esto lo que se consigue es controlar que a la hora de
imprimir la hora al usuario imprima la hora de acuerdo a su zona horaria respecto a la zona
horaria que le devuelve el servidor.
26 "SimpleDateFormat (Java Platform SE 7 ) - Oracle Help Center." 1 ene.. 1997,
https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html. Se consultó el 22 abr..
2018.
87
Problema #4: Paginación para panel de administración.
Conforme indica la documentación oficial del framework admin-on-rest, se requiere utilizar
un tipo de paginación concreto a la hora de construir las listas de objetos27. Por tanto se
requiere utilizar este formato:
Figura 48: Paginación de acuerdo a Admin-On-Rest. Fuente: Github Admin-On-Rest
En este caso se han utilizado 3 campos:
● _sort: Orden por atributo de la clase.
● _order: Ascendente o descendente (1-9 / 9-1) - (a-z / z-a).
● _start: Para marcar inicio de la lista (_start / 10) → 10 elementos.
El resto de campos no son requeridos.
Por tanto, a la hora de recuperar los datos de la capa DAO se le pasa el siguiente elemento
(Pageable):
Sort sort = new Sort(new Sort.Order(Sort.Direction.ASC / Desc, _sort));
Pageable request = new PageRequest((_start / 10), 10, sort);
return this.currentDAO.findAll(request);
Se ha modificado el código para adaptarlo a las variables descritas anteriormente.
Por último la capa DAO se encarga de devolver un objeto con la lista ya paginada:
Page<Collective> findAll(Pageable pageable);
Problema #5: Códigos de recuperación de la cuenta.
A la hora de generar códigos para la recuperación de las la cuenta existía la restricción de
un periodo máximo de validez de 24 horas. Para solucionar esto, se ha decidido añadir un
segundo atributo complementario al código de recuperación, la fecha de su creación.
Por tanto, si la fecha actual tiene una diferencia horaria 24 horas superior a la indicada, debe
mostrar un error en el cliente.
Sin embargo, ese código no iba a estar almacenado en la base de datos siempre, por tanto:
- Cada vez que un usuario inicia sesión, comprueba si el código existe. En caso de
hacerlo elimina ambos atributos y guarda el usuario. (POST
/users/login)
27 "Admin-on-rest - REST Clients - Marmelab." https://marmelab.com/admin-on-rest/RestClients.html. Se consultó el 24 abr.. 2018.
88
- Si en el proceso de recuperación se envía un código y se comprueba que ha pasado
su periodo de validez se elimina. (POST
/users/recover)
- Al actualizar un usuario también comprueba su validez y es eliminado en caso de
que no lo sea.
(PUT /users/id)
10.2. Cliente
El cliente en este caso, es el grueso de la aplicación, puesto es el que posee múltiples
funcionalidades e interactúa directamente con el usuario, por ello, debe controlarse esta
interacción para tener la mejor experiencia de usuario posible.
Se ha tenido en cuenta una completa gestión de los errores, indicando al usuario en
palabras que pueda entender qué error ha pasado. Por ello, cualquier acción es controlada
en caso de generar un error. Para su visualización en la aplicación, en este caso, se ha
optado por mostrarlos mediante mensajes en la parte superior de la pantalla o mediante
alertas.
Problema #1: Actualización de campos repetidos en listas.
El lenguaje Typescript, como otros lenguajes, a la hora de copiar un atributo de un objeto a
través de una instancia creada de otro objeto copia por referencia, por tanto, al cambiar el
valor de un atributo de la clase cambia en todos los objetos en los que sea referenciado (o
inversamente). Esto puede ser aprovechado en la aplicación a la hora de crear arrays.
Por ejemplo, a la hora de crear una lista de últimos reciclajes, cada elemento de la lista
posee un usuario, por tanto existen 2 listas, una de objetos reciclados y otra de usuarios. A
la hora de asignar el usuario a un elemento de la lista de objetos reciclados se asigna por
referencia. Por tanto, cuando se modifique un usuario de la lista de usuarios, todas sus
referencias de la lista de objetos son modificados.
Este ejemplo puede suceder, por ejemplo, a la hora de editar el perfil, el cual debe ser
modificado en el resto de vistas, por tanto, en vez de buscar uno a uno en la lista de objetos
reciclados, tan solo es necesario modificar un elemento de la lista de usuarios.
recycleItemList[item].recycleUser = users.filter(x => x.id ==
recycleItemList[item].recycleUser)[0]
89
[...]
this.events.subscribe('update-user-info', (user) => {
if (user.id != null) {
var index = this.users.findIndex(u => u.id == user.id)
if (index != -1) { //not found
this.users[index].profilePicture = user.profilePicture
this.users[index].fullName = user.fullName
}
}
});
Problema #2: Obtención de resultados utilizando el API de Google Vision a través
de una imagen.
El empleo de servicios gratuitos siempre tienen sus ventajas, pero también sus desventajas.
A la hora de implementar y testear la obtención de definiciones a partir de una imagen
subida al FTP se presentó un problema importante, la disponibilidad de esta misma.
Se descubrió que cuando un fichero es subido al servidor de imágenes, este no está
disponible al instante, sino que tarda unos segundos, por tanto, cuando se requiere de
utilizar la URL en la cual será subido el API de Google Vision indica que no puede encontrar
nada puesto que no encuentra la imagen.
Para solucionar esto, se decidió utilizar la imagen en formato base64 para llamar al API
mientras la imagen es subida al servidor y comienza a estar disponible.
Problema #3: Tamaño de las imágenes y formato.
A la hora de implementar el proyecto siempre se ha tenido en cuenta las consecuencias en
el futuro de las decisiones a tomar, una de estas es el tamaño de los ficheros. Se ha
procurado que tengan la mejor calidad en un tamaño de fichero comprensible.
Al tratarse de una aplicación orientada a dispositivos móviles, no se requieren de imágenes
excesivamente grandes, por ello, indicando como opciones los siguientes parámetros:
Para '@ionic-native/camera' (camera.getPicture):
90
var options: CameraOptions = {
quality: 100,
sourceType: sourceType,
saveToPhotoAlbum: false,
correctOrientation: true,
targetWidth: 900,
targetHeight: 900,
encodingType: this.camera.EncodingType.PNG,
mediaType: this.camera.MediaType.PICTURE,
destinationType: this.camera.DestinationType.FILE_URI
};
Para '@ionic-native/crop (Crop.crop):
{ quality: 100, targetWidth: 650, targetHeight: 650 }
A la hora de tomar una foto (o ser obtenida de la biblioteca), se siguen dos pasos, el primero
ya comentado y tras éste, proporcionar la imagen mediante una herramienta de cortado. Por
tanto, el tamaño de la imagen para ambos plugins ha decidido ser los indicados puesto que
el tamaño de uno influye en el otro.
Finalmente a la hora de subir la imagen, la imagen subida tendrá las siguientes propiedades:
● Formato image/png.
● Tamaño alrededor de: 20-90 KB.
● Tamaño de la imagen: 540x540px.
Problema #4: Marcadores del mapa y su color.
Google Maps posee una biblioteca preestablecida de iconos para crear marcadores en el
mapa, por ejemplo en las opciones de marcador se pueden establecer las siguientes
opciones:
let markerOptions: MarkerOptions = {
position: location,
title: title,
icon: color,
animation: 'DROP'
}
this.map.addMarker(markerOptions);
Por tanto, indicando un color, “blue” por ejemplo, se añadirá un marcador de tipo azul. Sin
embargo, esto plantea un problema que es, la posibilidad de añadir nuevos colores que no
existan.
91
Una posibilidad sería crear los iconos a mano, pero se traduciría en un mayor coste, por
tanto una solución es utilizar el API de Google de iconos dinámicos28. Por tanto, mediante la
modificación de la URL:
http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=•|ffff00
Por tanto, indicando el color al final de la URL en formato HTML se puede generar un icono
del color que se desee.
Problema #5: Actualizar campos tras cambios en la sesión.
Ionic por defecto no actualiza campos de otras vistas cuando se actualiza, por ejemplo, un
campo del perfil. Una vez carga una vista, no es actualizada, a no ser que el usuario decida
bajar la ventana para que vuelvan a cargar los cambios.
Para solucionar esto, se ha decidido utilizar eventos de usuario. Cuando es actualizado el
usuario por ejemplo, se lanza un evento con un nombre y automáticamente, las otras vistas
adscritas a dicho evento leen los datos y actualizan los datos que sean necesarios.
Para ello, la vista a actualizar debe primero suscribirse al evento, en el constructor o en
métodos que se cargan al cargar la vista por primera vez.
this.events.subscribe('update-user-info', (user) => {
if (user.id != null) {
var index = this.users.findIndex(u => u.id == user.id)
if (index != -1) { //not found
this.users[index].profilePicture = user.profilePicture
this.users[index].fullName = user.fullName
}
}
});
El usuario, por tanto, al actualizar su perfil, actualizando los campos de foto del perfil o
nombre completo, lanza el evento y la vista ya se encarga de leer el dato que se le pasa
como parámetro, en este caso, el usuario.
this.events.publish('update-user-info', this.user)
Problema #6: Tamaño de las vistas al activar el teclado.
28 "Dynamic Icons | Image Charts | Google Developers." 26 mar.. 2012,
https://developers.google.com/chart/image/docs/gallery/dynamic_icons#pins. Se consultó el 5 may..
2018.
92
Las vistas por defecto se alinean verticalmente en el centro, sin embargo, cuando se activa
el teclado surge un problema con la altitud de la vista que se reduce considerablemente.
Este problema se puede solucionar con la reducción del alto de las vistas. Esta solución se
aplica en la edición del usuario, separando en 3 vistas la modificación del perfil.
Además, surge otro problema, la barra de menú que tampoco se oculta por defecto, para
solucionar este problema debe añadirse el plugin ionic-plugin-keyboard29:
Una vez añadido, se puede aplicar la siguiente solución. Finalmente, los campos no son
ocultados al abrir el teclado:
Figura 49: Ocultación menú inferior al mostrar el teclado. Fuente: elaboración propia
Problema #7: Tiempo de espera de las peticiones.
Dado que el servidor puede no estar disponible por diversos motivos o que el cliente no
tenga conexión a internet, puede originar que una llamada al servidor llegue a ser infinita, ya
que por defecto, las peticiones HTTP no tienen un límite de tiempo.
Para solucionar este problema, se ha decidido añadir un tiempo de espera configurado en el
archivo de configuración del cliente /app/app-config.ts a todas las peticiones HTTP.
Sin embargo, el plugin de ionic (cordova) utilizado para subir la imagen no dispone de un
modo de indicar un tiempo tope a la hora de realizar la petición30.
29 "Ionic Native - Keyboard - Ionic Framework." https://ionicframework.com/docs/native/keyboard/.
93
Por tanto, se ha tenido que plantear una solución alternativa. En este caso, se ha optado por
introducir la petición dentro de una promesa con caducidad.
uploadFileWithTimeout(fileTransfer: TransferObject, targetPath, urlUpload, options):
Promise<boolean> {
return this.timeoutPromise(this.config.defaultTimeoutTime * 2,
fileTransfer.upload(targetPath, urlUpload, options).then(data => {
return true
}, error => {
return false
})
)
}
public timeoutPromise(timeout, promise) {
var wrapPromise = new Promise(function (resolve, reject) {
setTimeout(function () {
reject(new TimeoutError());
}, timeout);
});
return Promise.race([promise, wrapPromise]);
}
Por tanto, la promesa (con el doble de tiempo que una petición normal puesto que tiene que
subir la imagen) ignora la petición interna de transferencia una vez pasado el tiempo de
espera consiguiendo de este modo, asignar de un modo indirecto un tiempo de espera
máximo a la hora de subir la imagen.
En algunos dispositivos de gama baja antiguos ha aparecido un problema respecto el tiempo
de carga de la aplicación. Por defecto, Apache Cordova tiene un tiempo de carga límite, por
tanto, si tarda más de lo que debería la aplicación se cierra.
Por tanto, se ha configurado el archivo de configuración de las plataformas31 se ha añadido
la siguiente línea:
//File: config.xml
<preference name="loadUrlTimeoutValue" value="700000" />
Una vez realizado este cambio, la aplicación cargará correctamente sin cerrarse
inesperadamente.
30 "Ionic Native - File Transfer - Ionic Framework." https://ionicframework.com/docs/native/file-
transfer/. 31 "El archivo config.xml - Apache Cordova." https://cordova.apache.org/docs/es/latest/config_ref/.
94
10.3. Administración
La administración, al igual que el cliente utiliza localStorage para almacenar el token
generado cada vez que se inicia sesión. A partir de dicho token, se puede acceder a todas
las funcionalidades internas.
A la hora de implementar la administración se presentaron los siguientes problemas:
Problema #1: No está adaptado a respuestas generadas mediante Jackson.
El servidor API Rest, al utilizar Jackson, puede configurarse para no repetir entidades ya
definidas en una misma respuesta, reemplazandolas por su identificador.
A la hora de ser impresas en el panel de administración, siempre busca el elemento “id”
dentro de un objeto, sin embargo, al ser el propio objeto el id no lo encuentra, surgiendo el
problema.
Para arreglar este problema se ha decidido redefinir la definición de referencia, para
devolver el entero que reemplaza el propio objeto:
// File: /reciclaAdmin/src/fieldsAndInputs/MyReferenceField.js
var sourceObj = get(record, source);
var sourceName = source
if (sourceObj != null && !Number.isInteger(sourceObj)) {
if (sourceObj.id != null) {
sourceName += ".id"
}
}
Este problema se ha repetido al hacer referencia a un usuario. El usuario puede estar
representado por su correo o su nombre de usuario, sin embargo, un usuario puede tener un
nombre de usuario y no un correo y viceversa.
Para arreglar este problema se ha requerido utilizar nuevas definiciones para las URL y
textos en claro:
import React from 'react';
import PropTypes from 'prop-types';
import get from 'lodash.get';
const MyTextField = ({ source, source2, record = {}, elStyle }) => {
var output = null
if (source != null) {
95
output = get(record, source)
}
if ((output === null || output === '') && source2 != null) {
output = get(record, source2)
}
return <span style={elStyle}>{
output
}</span>;
};
MyTextField.propTypes = {
record: PropTypes.object,
source: PropTypes.string.isRequired,
};
export default MyTextField;
//Uso:
<MyTextField source="email" source2="username" />
Por tanto, al intentar obtener del array el correo, en caso de no existir o ser vacío, buscará el
nombre del usuario.
Sin embargo, el framework en otras definiciones si soporta la selección de un atributo de la
clase en caso de no existir el otro. Tal y como indica el código de la definición de
SelectInput32, se puede pasar como parámetro una función:
const optionRenderer = choice => `${choice.email} ${choice.username}`;
[...]
<SelectInput optionText={optionRenderer} />
Por tanto, el framework sí soporta este tipo de casos en ciertas definiciones predefinidas.
Problema #2: No existe soporte a la introducción de la hora junto la fecha.
A la hora de utilizar una fecha junto su hora, surgió el problema de que no existía un método
de introducción de la hora, tan solo de la fecha. Esto supuso un problema, sin embargo, se
encontró un complemento que podía solventarlo, llamado aor-datetime-input33.
Para ello, dicho complemento deberá instalarse mediante Node e importarlo en la entidad
que lo necesite.
32 "selectInput.js" https://github.com/marmelab/admin-on-
rest/blob/893a01dedba77bf543b769ce9923028302ea3a95/src/mui/input/SelectInput.js. 33 "aor-datetime-input - GitHub." https://github.com/iamsimakov/aor-datetime-input.
96
11. Conclusiones
La app ReciclaUA pretende permitir que los usuarios de la UA incrementen su conocimiento
y su grado de concienciación con el reciclaje en general y con el reciclaje de tapones y
botellas en particular. Dicho proyecto se ha definido en base a una investigación de producto
que ha incluido tanto el análisis de las principales aplicaciones competidoras como
encuestas realizadas a alumnos de la UA sobre sus expectativas acerca de una app de
estas características.
El proyecto realizado abarca un número importante de tecnologías que no había utilizado
hasta el momento, como es el caso de Ionic o React. Por ello, ha sido un proyecto con una
alta curva de aprendizaje. Dicha curva se ha acentuado aún más por el hecho de haber
desarrollado el proyecto desde cero. No obstante, eso me ha permitido adquirir una visión
global del desarrollo de este tipo de aplicaciones, e ir aumentando mi nivel de confianza con
mi trabajo a medida que iba resolviendo cada problema que se iba presentando. Uno de
esos problemas ha sido el uso de herramientas gratuitas, cuyo nivel de servicio a veces no
ha sido el esperado.
Considero que el proyecto ha cubierto los objetivos planteados en un principio, a pesar de
pequeñas demoras que se hayan podido producir en momentos puntuales precisamente por
esos problemas técnicos que surgían fruto del desconocimiento de las tecnologías.
Estamos ante un proyecto ambicioso, cuyo desarrollo no podemos decir que esté terminado
ni mucho menos. En primer lugar, el tiempo nos ha impedido realizar un test de rendimiento
sumativo para comprobar que efectivamente el producto desarrollado cumple los criterios de
eficiencia, eficacia y satisfacción de su público objetivo. Sí queremos destacar que se han
realizados tests formativos para distintas decisiones de diseño, buscando siempre la
solución más intuitiva para el usuario final. Por otro lado, necesitamos que el proyecto se
ponga a disposición de la comunidad universitaria para poder realizar un seguimiento que
nos permita evaluar su impacto real. En este sentido, hemos definido un conjunto de
medidas y unos métodos de medición que sin duda nos van a guiar en este objetivo.
Por último, aunque se han incluido todas las funcionalidades clave previstas en un principio,
somos conscientes de las posibilidades de mejora de un producto como este. A continuación
detallamos algunas de las mejoras que proponemos de cara a seguir desarrollando esta app
en el futuro.
97
11.1. Mejoras
A continuación presentamos un resumen de las principales mejoras que pretendemos
abordar en un futuro, divididas en mejoras técnicas y mejoras funcionales.
11.1.1. Mejoras técnicas
- Mejorar el sistema de regeneración de tokens, creando tokens que se invaliden
transcurrido un tiempo, en vez de ser renovados constantemente (que es como
funciona actualmente).
- Mejorar la sincronización entre el panel de administración y la app para que no sea
necesario reiniciar sesión para que los datos cambiados por el administrador se
reflejen en la app.
11.1.2. Mejoras funcionales
- Implementar un panel de administración más completo, donde se puedan ver los
últimos cambios de forma clara, junto gráficas que puedan demostrar la evolución de
la aplicación en el tiempo.
- Mejorar el sistema de propuesta de contenedores de reciclaje de la aplicación
mediante técnicas de Machine Learning. El API de Google Vision, dada la imagen de
un objeto, devuelve una serie de términos ordenados en función de su probabilidad.
Actualmente la app busca en todos los términos el primero que esté en la BD
asociado a un tipo de objeto. Si no encuentra ningún término, coge el primero (el
más probable) y pide al usuario que introduzca el tipo correspondiente. La mejora
consistiría en almacenar tanto la lista de términos que devuelve la API de Google
Vision como la selección de tipo de objeto que introduce el usuario. Con esa
información, y con un número suficiente de observaciones en la BD, sería posible
aplicar técnicas de Machine Learning para que la app ‘aprendiese’ y sugiriese
automáticamente tipo de objeto incluso cuando los términos exactos no se
encuentran en la BD.
- Controlar la trazabilidad de los residuos tras haber sido reciclados a través de la
plataforma. Esta trazabilidad es una de las necesidades que actualmente no cubre,
hasta lo que alcanza nuestro conocimiento, ninguna aplicación en el mercado
(Ecoembes, 2018).
- Controlar el momento en que un usuario puede registrar que ha realizado una acción
de reciclaje. Actualmente la app no comprueba la ubicación del usuario para
98
asegurarse de que se encuentra lo suficientemente cerca del contenedor como para
poder asumir que dicha acción se ha producido.
- Permitir indicar durante el proceso de reciclaje la cantidad del objeto que se va a
reciclar, para así poder controlar el volumen reciclado y no sólo el número de
acciones de reciclado realizadas. Dicho volumen podría servir para refinar rankings
de recicladores.
- Añadir más mecanismos de gamificación. Como ejemplo, añadir un juego de
reciclaje que, dado una imagen, pida al usuario que elija el contenedor en el que
debe ser reciclado. Añadir tb un ranking de jugadores.
- Alojar la plataforma en un servidor profesional, disponible cualquier hora del día.
- Permitir la ocultación de usuarios deshabilitados de cualquier listado.
- Publicar la aplicación en la App Store y Play Store.
99
Bibliografía
La UE tira el plástico a la basura [En línea] / aut. Ye Susana y Sarabia Virginia // Business
Insider (España). - 28 de May de 2018. - Jun de 2018. - https://www.businessinsider.es/ue-
tira-plastico-basura-255524.
Consumo y medio ambiente: Marketing del Reciclado [Publicación periódica] / aut.
Puelles J. y González L. // Distribución y Consumo. - 1993. - Vol. 2. - págs. 116-123.
Agile software development with Scrum [Libro] / aut. Schwaber Ken y Beedle Mike. -
Upper Saddle River : Prentice Hall, 2002.
BBVA [En línea] / aut. BBVA // BBVA. - 23 de 3 de 2016. - 5 de 4 de 2018. -
https://bbvaopen4u.com/es/actualidad/api-rest-que-es-y-cuales-son-sus-ventajas-en-el-
desarrollo-de-proyectos.
El comportamiento de reciclaje del universitario. Propuesta de un instrumento de
medida. [Conferencia] / aut. De-Juan-Vigaray M. D., González-Gascón E y Lorenzo-Álvarez
C. // XV Jornadas de Redes de Investigación en Docencia Universitaria. - Alicante : ICE,
2017. - págs. 100-110.
Ecoembes [En línea] / aut. Ecoembes // Ecoembes. - 1 de 6 de 2018. - 1 de 6 de 2018. -
https://www.ecoembes.com/es/recicladores/trazabilidad.
From game design elements to gamefulness: defining "gamification" [Conferencia] /
aut. Deterding Sebastian [y otros] // International Academic MindTrek conference:
Envisioning future media environments. - [s.l.] : ACM, 2011. - págs. 9-15.
Goberoi [En línea] / aut. Oberoi Gaurav // Goberoi. - 11 de 7 de 2016. - 12 de 3 de 2018. -
https://goberoi.com/comparing-the-top-five-computer-vision-apis-98e3e3d7c647.
iRecycle: find Local Recycling Fast [En línea] / aut. Earth911 // iRecycle. - 20 de 10 de
2017. - 20 de 10 de 2017. - https://earth911.com/irecycle/.
OLIO: Join the food sharing revolution [En línea] / aut. OLIO // OLIO. - 20 de 10 de
2017. - 20 de 10 de 2017. - https://olioex.com/.
Presentación de la red [En línea] / aut. Red IDoI // Red docente en Investigación +
Docencia + Innovación. - 28 de 5 de 2018. - 28 de 5 de 2018. - https://web.ua.es/es/idoi/.
Presentación de resultados 2017 [En línea] / aut. Ecoembes // Ecoembes. - 17 de 5 de
2018. - 28 de 5 de 2018. - https://www.ecoembes.com/es/ciudadanos/sala-de-prensa/notas-
de-prensa/envases-domesticos-se-situan-un-ano-mas-como-los-residuos-urbanos-mas-
reciclados-en-espana.
Programa de Reciclaje de Instrumentos de Escritura [En línea] / aut. TerraCycle //
Terracycle: Recicla tu basura. - 10 de 5 de 2018. - 10 de 5 de 2018. -
https://www.terracycle.es/es-ES/brigades/brigada-de-instrumentos-de-escritura.
100
Quora [En línea] / aut. Rocca Andrea // Quora. - 27 de 10 de 2017. - 14 de 4 de 2018. -
https://www.quora.com/Which-language-is-best-for-backend-web-development-now-future.
RecycleNation [En línea] / aut. RecycleNation // RecycleNation. - 18 de 10 de 2017. - 18 de
10 de 2017. - https://recyclenation.com.
TapIt Metro D.C. [En línea] / aut. TapIt Metro D.C. // TapIt Metro D.C.. - 20 de 10 de 2017. -
20 de 10 de 2017. - https://freetapwater.wordpress.com/.
Total Engagement: Using Games and Virtual Worlds to Change the Way People Work
and Businesses Compete. [Libro] / aut. Reeves B y Read L. J. - Boston : Harvard Business
School Press, 2009.
101
13. Apéndices
13.1. Wiki del proyecto y puesta en marcha
Desde el proyecto GitHub se ha creado una wiki donde poder consultar aspectos menos
concretos de la aplicación, una demo, además de una guía de instalación del mismo:
Wiki ReciclaWeb
13.2. Resultados Encuesta concepto producto
29 participantes.
¿Qué significa para ti 'reciclar'?
Significa coger las partes útiles (materia prima) de un producto con el fin de reutilizarlas para
formar otro nuevo.
Utilizar un objeto para convertirlo en otro y seguir dándole uso, en lugar de tirarlo tras darle el
uso para el que fue creado.
Dar un nuevo uso a todos aquellos materiales que son posible regenerar, ayudando a reducir el
efecto del cambio climático.
Ayudar al medioambiente mediante la reutilización de materiales.
Separar los residuos generados para que estos puedan ser transformados en nuevas cosas.
Someter un producto a su reutilización.
Ayudar al medio ambiente. Sin esfuerzo extra.
Reutilizar los materiales de un objeto/producto para utilizarlos de nuevo para construir/fabricar
un producto que utilice dichos materiales.
Reutilizar cualquier recurso
Transformar desechos en nuevos recursos mediante procesos químicos que son menos
costosos que la extracción de los recursos.
Significa separar los deshechos en una serie de categorías para que luego sea mas fácil
procesarlos para crear nuevos productos a partir de ellos.
102
Utilizar algo que ya se ha usado, en un nuevo producto.
Es la reutilización de cualquier producto manufacturado en cualquier uso distinto para el que fue
ideado.
Volver a darle uso a productos/materiales que ya han sido utilizados antes
Reusar un producto.
Volver a utilizar algo que ya está usado, o darle otro uso distinto.
Reutilizar objetos ya usados con el fin de consumir menos
Recuperar y utilizar un producto descartado por otra persona
Reciclar lo entiendo como reutilizar componentes implementados de forma genérica en un
software
Dar una nueva vida (ciclo) a un objeto.
Utilizar de nuevo algo que ya ha sido usado, de la misma forma u otra distinta, directamente o
tras un proceso de "adaptación"
Tratar los productos para no generar tantos residuos.
Significa reutilizar materiales que ya han sido usados de forma que se contribuya de una forma
activa y favorable al medioambiente. Por ejemplo, yo puedo reciclar en mi casa dividiendo los
desperdicios (ya sean de comida o materiales) en distintas basuras para su posterior reciclaje.
Reutilizar materiales para evitar la fabricación de más
El hecho de ayudar al planeta a tratar los desechos que los humanos tiramos, usando
materiales más fáciles de limpiar, que contaminen menos.
Reutilizar materiales para volverlos a usar y no tener que malgastar materiales.
Dar objetos que ya no te aportan nada otra utilidad.
Conservar el medio ambiente.
Para mí reciclar es separar la basura para que así puedan ser transformados y reutilizados.
¿Cómo te sientes cuando reciclas?
103
Me siento normal, ya que es algo que siempre he hecho de manera habitual y forma parte de mi
rutina.
Bien.
Que, en el ámbito de la naturaleza, ayudo a tener un mundo mejor.
Cuando se recicla, se reduce el tiempo de desarrollo y hace que de un software de obtenga más
beneficio.
Bien, porque estamos ahorrando materiales.
Me siento bien
En los ámbitos en los que reciclo, es una costumbre tan habitual que no me supone ningún
sentimiento en especial.
Normal, cada vez estás más normalizado.
Bien.
Bien
bien
Bien, sabiendo que estoy ayudando a conversar nuestro planeta.
Igual
siento que ayudo a una buena causa.
Satisfecho con no malgastar recursos
Que aunque no sea lo más fácil, tendrá una recompensa y será útil en un futuro.
Bien, porque haces algo útil para el medio ambiente.
Ningún sentimiento en particular. Aunque tengo la sensación de que la mayoría no lo hace.
Me siento bien
Normal, es un deber que tendríamos que tener todos.
104
Reciclar, es muy útil para todos.
Bien.
Satisfecho. Sobretodo por el ahorro en costes y la ayuda al medio ambiente.
Bien porque sabes que estas haciendo un hecho bueno con el medioambiente.
Bien
Principalmente siento que contribuyo en el cuidado del planeta y del medio ambiente.
Me siendo contento sabiendo que estoy ayudando al medioambiente
No siento que haga nada especial, puesto que realmente, sólo ayudas a que las instituciones
ganen más dinero, ya que al reciclar, pueden prescindir de operarios y de maquinaria para dicho
uso y siguen cobrando los mismos impuestos.
Bien ayudando al medio ambiente.
¿Qué impedimentos encuentras actualmente a la hora de reciclar?
No está muy difundido y a veces cuesta encontrar lugares para el reciclaje según la zona donde
vivas
No tener en casa medios para separar la basura.
Existen pocos sitios donde dispongan de contenedores/papeleras para realizar un correcto
separado de los residuos.
Pereza
Ninguno
Qué no siempre se puede hacer debido a la falta de los medios necesarios y que no hay
suficiente concienciación al respecto.
No se le da importancia en la educación al reciclar
No encuentro ninguno, más que el desplazamiento al contenedor
La dificultad a la hora de hacerlo, sobre todo de conocimiento.
105
Hay casos cuando no sabes donde tienes que depositar o qué tienes que depositar.
Ahora mismo, que el ayuntamiento no ponga más contenedores de reciclaje cerca de donde
vivo, y tenga que desplazarme lejos.
Al deshacerme de productos que no estén clasificados en los típicos contenedores. En
ocasiones es difícil encontrar un punto limpio que se encargue de ellos.
No tengo espacio en casa para tener un cubo de basura diferente para cada uno de los posibles
materiales. Deshacerme de las pilas me supone un esfuerzo que podría evitarse.
Generalmente, la escasez de contenedores de reciclaje en mi población.
No hay contenedores cercanos.
Cuando me encuentro con producto formado por materiales muchas veces no tengo claro a que
contenedor va
Hay cosas que es difícil de situar en los distintos contenedores.
Desconocimiento de las zonas de reciclaje.
<br />Dudar al decidir en que lugar va un tipo de producto concreto.
<br />Que hacer cuando quiero reciclar un producto que necesita ayuda para ser transportado.
La falta de controles a la hora del post-tratamiento y el favorecimiento de empresas privadas a
costa del gasto publico en reciclaje
Separar las cosas, o saber en que contenedor va cada cosa.
El tener que estar separando en varias bolsas/papeleras/etc. la basura según el tipo, cuando en
un uso doméstico (al menos en mi caso) no era lo habitual ni la rutina.
No siempre hay contenedores de todos los tipos necesarios.
Necesidad de un mayor espacio para separar entre orgánico, cartón, plásticos y vidrio.
No siempre se han implementado de forma genérica los componentes.
Cercania de los contenedores y espacio en casa para poder reciclar correctamente.
Carencia de facilidades que ayuden a perseguir este modelo. Desconocimiento de los puntos de
reciclaje, o de qué se echa en cada papelera,...
Que, según dicen, aunque reciclemos, las plantas de reciclaje no hacen su labor correctamente,
y por lo tanto la gente deja de reciclar.
106
Que no tengo contenedores de reciclaje cerca de casa
Pocos, es más la gestión del reciclaje en casa que la posibilidad de reciclar.
Aunque las pilas y elementos electrónicos es complicado de reciclar.
¿Qué funcionalidades te gustaría que tuviese una app que te ayudara a reciclar?
- Mapa que permita búsqueda de contenedores de reciclaje
En el mismo mapa indicar un basurero en el que, si no hay zona de reciclaje, poder sugerir
añadir una
Saber de qué está compuesto un producto mediante su código de barras y saber como
procesarlo.
Que pudiera ver realmente cuánto he ayudado y cómo, y que sea intuitiva y cómoda de usar
Ayudarme a encontrar los puntos de reciclaje.
Ayudarme a dividir todo lo que tiro en categorías.
La localización de todos los contenedores y de qué tipo son, además de tal vez, alguna manera
de controlar cuanto reciclas al mes y de manera relativa, mostrar tu aporte al reciclar.
Quizá una guía de qué tipo de reciclaje son algunos productos, por ejemplo vasos de café y
cosas medio plásticas-cartón.
Backoffice
Localización de los contenedores
Mostrarme la ubicación de los diferentes tipos de contenedores disponibles cerca de mí.
Decirme de qué tipo de material está hecho un objeto del que no estoy seguro y cómo reciclarlo.
En primer lugar, una lista de beneficios que concencie a la gente a dar el paso y empezar a
reciclar, y luego, ayuda a saber dónde introducir un tipo de material u otro si se tienen dudas.
Me gustaría una aplicación que tuviese información detallada sobre donde se tira cada objeto.
Un mapa donde pudiésemos ver donde se encuentran localizadas las papeleras.
Poder ver en directo que se hace en la planta de reciclaje en mi localidad.
Localizar puntos de reciclaje.
Ayuda a decidir en que lugar se debe depositar un tipo producto que queremos reciclar.
Que me dijese dónde puedo deshacerme de las pilas. Pero como con muchos otros aspectos en
las que se materializa el boom de las apps, no creo que mucha gente se descargue, y mucho
menos mantenga instalada una app con un uso y beneficio para el usuario tan restringido como
107
una de reciclaje.
Poder consultar en que contenedor va cada material, etc
Me gustaría que tuviese un mapa con puntos limpios en los que deshechar productos como
aceite de coche u otros que no se puedan reciclar de forma normal.
Que informe sobre puntos de reciclaje
Información del proceso, ayuda a la hora de reciclar, etc...
Podría formar a los usuarios, enseñándoles donde depositar cada tipo de residuo. Se podría
hacer especial hincapié en aquellos donde la gente tiene más dudas de dónde van.
Además, podría ofrecer una serie de estadísticas impactantes para conseguir concienciar a más
gente.
Que te muestre los puntos de reciclaje cercanos
Consejos para reciclar bien, donde va cada desecho.
No veo de qué forma puede una app ayudarme a reciclar. Tal vez, mostrándome la localización
y horario de los puntos de reciclaje (para pilas, etc.)
La ubicación de los contenedores y la posibilidad de solicitar que se ponga un contenedor en
cierta posición
Una clasificación de los objetos habituales para no confundirse.
Listado de productos comunes con los que la gente se confunde y clasificación de contenedor
en el que deben retirarse
Que me indicara como separar adecuadamente la basura y localizaciones de contenedores de
reciclaje.
La localización de los diversos puntos de reciclaje más próximos a mi.
Seria de ayuda
Información de la localización de los contenedores.
Información de en que contenedor va cada artículo.
Información sobre todo el concepto sobre reciclar y artículos sobre esto.
Localización de los contenedores cercanos y una guía para saber que producto en que
contenedor tiene que ir.
¿Cómo te gustaría verte a ti mismo con respecto al reciclaje en un futuro?
108
Muy implicada.
.
Mucho más involucrado con el reciclaje.
Intentar reciclar más
que reciclar fuera lo normal
Reciclando todo lo posible de una forma que no me supusiera un esfuerzo extra considerable.
Pudiendo realizar las mismas tareas que realizo actualmente en la vida cotidiana sin
preocuparme demasiado por tener que hacer ciertas tareas extras para el reciclaje. La
automatización del mismo sería una tarea realmente importante también para que la gente que
actualmente no recicla, pueda hacerlo sin tener siquiera que pensar en ello.
No lo se
Reciclando todo los productos que consumo
Más reciclador.
Igual. No estar obsesionado con tener que separar hasta el más mínimo producto en su
correspondiente reciclaje, pero sí reciclar la mayor parte de desechos que se generan.
Siendo más activo y más concienciado.
Me gustaría reciclar más, pero eso depende totalmente de los ayuntamientos de cada ciudad,
puesto que en mi caso, no tengo contenedores a menos de 900 metros, por tanto, el coste de ir
hasta el lugar con la satisfacción de reciclar, no compensa.
<br />
<br />Además, en un futuro, espero que además de reciclar más por mi parte, que los gobiernos
pongan más énfasis en dichas prácticas, incluso pudiendo llegar a sancionar de alguna manera
(siempre y cuando pongan más contenedores).
ns/nc
Pues seguir haciéndolo, ayudando a conservar el medio ambiente y concienciando a mi entorno
en que también reciclen, cosa que también hago actualmente.
Reciclando por un medio ambiente mejor
109
Reciclar mas.
Pudiendo reciclar más materiales de los que reciclo actualmente, etc.
Es suficiente con saber que he aportado
Me gustaría que no fuese necesario reciclar como lo hacemos hoy en día gracias a que la
mayoría de productos que utilizamos de forma cotidiana sean biodegradables (por ejemplo las
bolsas de plástico de la compra).
Más comprometido. Espero que el reciclaje se convierta en rutina en mi dia a dia.
Reciclando y reutilizando todos los materiales posibles
Reciclando todo lo posible
Me gustaría verme reciclando la gran mayoría de mis residuos, por no decir todos.
Me gustaría verme implicado, disponiendo del mayor número de lugares donde poder separar
los residuos. Me gustaría tener un entorno donde todo el mundo estuviera concienciado con el
reciclaje.
Cuanto más sea capaz de reciclar, mucho mejor.
Todos tendríamos que ser parte activa en el proceso de reciclaje.
Reciclando.
Me gustaría adaptarme de tal manera que recicle sin pensar, de forma automática.