Logo Studenta

Desarrollo de Librería Utilitaria

¡Este material tiene más páginas!

Vista previa del material en texto

ESCUELA POLITÉCNICA NACIONAL
FACULTAD DE INGENIERÍA DE SISTEMAS
DESARROLLO DE UNA LIBRERÍA UTILITARIA FUNCIONAL
SOBRE UN LENGUAJE ORIENTADO A OBJETOS, APLICADA A
UN CASO DE ESTUDIO
PROYECTO PREVIO A LA OBTENCIÓN DEL TÍTULO DE INGENIERO EN
SISTEMAS INFORMÁTICOS Y DE COMPUTACIÓN
SEBASTIÁN ESTRELLA HEREDIA
sebas007estrella@gmail.com
DIRECTOR: ING. ENRIQUE ANDRÉS LARCO AMPUDIA, MSc.
andres.larco@epn.edu.ec
Quito, abril 2016
DECLARACIÓN
Yo, Sebastián Estrella Heredia, declaro bajo juramento que el trabajo aquı́ descri-
to es de mi autorı́a; que no ha sido previamente presentada para ningún grado o
calificación profesional; y, que he consultado las referencias bibliográficas que se
incluyen en este documento.
A través de la presente declaración cedo mis derechos de propiedad intelectual
correspondientes a este trabajo, a la Escuela Politécnica Nacional, según lo esta-
blecido por la Ley de Propiedad Intelectual, por su Reglamento y por la normatividad
institucional vigente.
Sebastián Estrella Heredia
I
CERTIFICACIÓN
Certifico que el presente trabajo fue desarrollado por Sebastián Estrella Heredia,
bajo mi supervisión.
Ing. Enrique Andrés Larco Ampudia, MSc.
Director del Proyecto
II
AGRADECIMIENTOS
A mi esposa, por su amor y apoyo incondicional durante todo este largo camino
recorrido juntos, no habrı́a podido superar todos los obstáculos sin su apoyo y com-
prensión.
A mi madre, por su ejemplo de fortaleza y voluntad a lo largo de toda su vida, lo
cual me a servido de ejemplo para superar todos los desafı́os.
A mis hermanas, por su alegrı́a cariño, gracias por siempre llenarme de alegrı́a y
saber escucharme en aquellos momentos que lo necesitaba.
A mis tı́os y tı́as, por cuidarme como uno más de sus hijos y saber darme sus
mejores consejos y guiarme por el camino correcto.
A mis primos y primas, por ser mis compañeros de travesuras y ser la nueva gene-
ración que nos llena de alegrı́a.
A mis suegros, por abrirme las puertas de su hogar y corazón, como uno más de
sus hijos.
A mis cuñados y cuñada, por su alegrı́a y coraje para siempre seguir adelante y
saber luchar las batallas más difı́ciles.
III
DEDICATORÍA
En memoria de mis abuelos, gracias por todo su amor y cariño incondicional.
IV
CONTENIDO
Resumen 1
Presentación 2
1. Marco Teórico 3
1.1. Definición del Paradigma de Programación Funcional . . . . . . . . . 3
1.1.1. Caracterı́sticas Generales . . . . . . . . . . . . . . . . . . . . . 3
1.1.2. Lenguaje de Programación Haskell . . . . . . . . . . . . . . . . 7
1.2. Definición del Paradigma de Programación Orientado a Objetos . . . 8
1.2.1. Caracterı́sticas Generales . . . . . . . . . . . . . . . . . . . . . 8
1.2.2. Lenguaje de Programación Java . . . . . . . . . . . . . . . . . 12
1.3. Comparación entre Paradigmas Funcional y Orientado a Objetos . . . 13
1.3.1. Comparación entre Paradigmas . . . . . . . . . . . . . . . . . 13
1.3.2. Comparación entre Lenguajes . . . . . . . . . . . . . . . . . . 15
1.3.3. Análisis de Resultados . . . . . . . . . . . . . . . . . . . . . . . 17
1.4. Estilo de Programación Funcional sobre un Lenguaje Orientado a Ob-
jetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
V
VI
1.4.1. Patrones de Diseño Funcionales . . . . . . . . . . . . . . . . . 18
1.4.2. Estado del Arte . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2. Desarrollo de la Librerı́a Utilitaria Funcional 50
2.1. Análisis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
2.1.1. Retrocompatibilidad . . . . . . . . . . . . . . . . . . . . . . . . 55
2.1.2. Limitaciones del Lenguaje de Programación Java . . . . . . . . 56
2.1.3. Análisis de Portabilidad . . . . . . . . . . . . . . . . . . . . . . 62
2.2. Diseño . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
2.2.1. Estructura de Código . . . . . . . . . . . . . . . . . . . . . . . 68
2.2.2. Comportamiento . . . . . . . . . . . . . . . . . . . . . . . . . . 71
2.2.3. Documentación del Código . . . . . . . . . . . . . . . . . . . . 74
2.3. Desarrollo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
2.3.1. Desarrollo Guiado por Pruebas . . . . . . . . . . . . . . . . . . 76
2.3.2. Integración Continua . . . . . . . . . . . . . . . . . . . . . . . . 79
2.3.3. Técnicas Empleadas . . . . . . . . . . . . . . . . . . . . . . . . 81
2.4. Pruebas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
2.4.1. Niveles de Pruebas . . . . . . . . . . . . . . . . . . . . . . . . 86
2.4.2. Tipos de Pruebas . . . . . . . . . . . . . . . . . . . . . . . . . 88
2.4.3. Planificación de Pruebas . . . . . . . . . . . . . . . . . . . . . 90
2.4.4. Cobertura de Pruebas . . . . . . . . . . . . . . . . . . . . . . . 94
VII
2.4.5. Pruebas de Mutación . . . . . . . . . . . . . . . . . . . . . . . 95
2.4.6. Ejemplos de Pruebas . . . . . . . . . . . . . . . . . . . . . . . 97
2.4.7. Reporte de Pruebas . . . . . . . . . . . . . . . . . . . . . . . . 101
3. Aplicación de la Librerı́a Funcional a un Caso de Estudio 103
3.1. Refactorización Funcional de una Aplicación Orientada a Objetos . . 103
3.1.1. Selección del Caso de Estudio . . . . . . . . . . . . . . . . . . 103
3.1.2. Refactorización del Caso de Estudio . . . . . . . . . . . . . . . 112
3.2. Análisis de Resultados . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
3.2.1. Complejidad Ciclomática (CC) . . . . . . . . . . . . . . . . . . 119
3.2.2. Comparación de Resultados . . . . . . . . . . . . . . . . . . . 120
4. Conclusiones y Recomendaciones 123
4.1. Conclusiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
4.2. Recomendaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
Siglas 126
Glosario 126
Biblografı́a 129
Anexos 133
.1. Capturas de Pantalla de GitHub . . . . . . . . . . . . . . . . . . . . . . 133
.2. Capturas de Pantalla de JIRA . . . . . . . . . . . . . . . . . . . . . . . 134
LISTADO DE TABLAS
1.1. Caracterı́sticas Principales de Haskell . . . . . . . . . . . . . . . . . . 8
1.2. Caracterı́sticas de Java . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.3. Comparación entre Paradigmas . . . . . . . . . . . . . . . . . . . . . . 15
1.4. Comparación entre Lenguajes . . . . . . . . . . . . . . . . . . . . . . 17
1.5. Estilos de Programación Funcional en OOP . . . . . . . . . . . . . . . 18
1.6. Caracterı́sticas de Rust . . . . . . . . . . . . . . . . . . . . . . . . . . 32
1.7. Caracterı́sticas de Clojure . . . . . . . . . . . . . . . . . . . . . . . . . 35
1.8. Caracterı́stica de Elixir . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
1.9. Caracterı́sticas de Scala . . . . . . . . . . . . . . . . . . . . . . . . . . 39
1.10.Caracterı́sticas de Erlang . . . . . . . . . . . . . . . . . . . . . . . . . 41
1.11.Caracterı́sticas de OCaml . . . . . . . . . . . . . . . . . . . . . . . . . 43
1.12.Caracterı́sticas de functional.js . . . . . . . . . . . . . . . . . . . . . . 44
1.13.Caracterı́sticas de Javaslang . . . . . . . . . . . . . . . . . . . . . . . 45
1.14.Caracterı́sticas de functional-ruby . . . . . . . . . . . . . . . . . . . . 46
1.15.Caracterı́sticas de functional-php . . . . . . . . . . . . . . . . . . . . . 47
VIII
IX
1.16.Caracterı́sticas de Underscore.js . . . . . . . . . . . . . . . . . . . . . 48
2.1. Product Backlog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
2.2. Sprint #1 - Spring Backlog . . . . . . . . . . . . . . . . . . . . . . . . . 53
2.3. Sprint #2 - Spring Backlog . . . . . . . . . . . . . . . . . . . . . . . . . 54
2.4. Sprint #3 - Spring Backlog . . . . . . . . . . . . . . . . . . . . . . . . . 54
2.5. Proceso de Ejecución - Función Suma . . . . . . . . . . . . . . . . . . 61
2.6. Análisis de Portabilidad . . . . . . . . . . . . . . . . . . . . . . . . . . 67
2.7. Nivelesde Pruebas Utilizados . . . . . . . . . . . . . . . . . . . . . . . 88
2.8. Tipos de Pruebas Utilizados . . . . . . . . . . . . . . . . . . . . . . . . 90
2.9. Categorı́as de Pruebas - Pruebas de Compatibilidad . . . . . . . . . . 98
2.10.Categorı́as de Pruebas - Cobertura de Pruebas . . . . . . . . . . . . . 99
2.11.Categorı́as de Pruebas - Pruebas de Mutación . . . . . . . . . . . . . 100
2.12.Categorı́as de Pruebas - Pruebas de Unitarias . . . . . . . . . . . . . 101
3.1. Interpretación de Métricas . . . . . . . . . . . . . . . . . . . . . . . . . 105
3.2. Número de Lı́neas de Código por Clase . . . . . . . . . . . . . . . . . 113
3.3. Comparación de la Complejidad Ciclomática . . . . . . . . . . . . . . 121
3.4. Comparación de Resultados . . . . . . . . . . . . . . . . . . . . . . . 122
LISTADO DE FIGURAS
1.1. Curso Universidad de Edinburgh . . . . . . . . . . . . . . . . . . . . . 24
1.2. Curso Universidad de Nottingham . . . . . . . . . . . . . . . . . . . . 25
1.3. Curso Universidad de Oxford . . . . . . . . . . . . . . . . . . . . . . . 25
1.4. Curso Universidad Tecnológica Nacional . . . . . . . . . . . . . . . . . 26
1.5. Curso Universidad de los Andes . . . . . . . . . . . . . . . . . . . . . 26
1.6. Curso Universidad de Oklahoma . . . . . . . . . . . . . . . . . . . . . 27
1.7. Haxl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
1.8. Swift . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
1.9. F# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
1.10.Intel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
1.11.Whatsapp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
1.12.SumAll . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.1. Release Burndown . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
2.2. Uso de las Versiones de JDK . . . . . . . . . . . . . . . . . . . . . . . 56
2.3. Número de Módulos Importados . . . . . . . . . . . . . . . . . . . . . 68
X
XI
2.4. Estructura de Paquetes . . . . . . . . . . . . . . . . . . . . . . . . . . 71
2.5. Diagrama de Actividad - Maybe.maybe . . . . . . . . . . . . . . . . . . 72
2.6. Diagrama de Actividad - Maybe.isNothing . . . . . . . . . . . . . . . . 73
2.7. Diagrama de Actividad - Maybe.isJust . . . . . . . . . . . . . . . . . . 74
2.8. Ejemplo de Javadoc . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
2.9. Captura de Pantalla de Hackage . . . . . . . . . . . . . . . . . . . . . 75
2.10.Ciclo de Vida - TDD . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
2.11.Diagrama de Actividad - Maybe.isNothing . . . . . . . . . . . . . . . . 77
2.12.Captura de Pantalla de Bitbucket . . . . . . . . . . . . . . . . . . . . . 80
2.13.Captura de Pantalla de Shippable . . . . . . . . . . . . . . . . . . . . 81
2.14.Diagrama de Flujo - Planificación de Pruebas . . . . . . . . . . . . . . 94
2.15.Flujo de Trabajo Pruebas de Mutación . . . . . . . . . . . . . . . . . . 96
2.16.Pruebas de Compatibilidad . . . . . . . . . . . . . . . . . . . . . . . . 98
2.17.Resumen de Cobertura de Pruebas . . . . . . . . . . . . . . . . . . . 99
2.18.Resumen de Cobertura de Pruebas . . . . . . . . . . . . . . . . . . . 99
2.19.Mutantes Activos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
2.20.Reporte de Pruebas . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
3.1. Repositorio de JUnit en GitHub . . . . . . . . . . . . . . . . . . . . . . 104
3.2. Top 5 Librerı́as de Java más Utilizadas . . . . . . . . . . . . . . . . . . 106
3.3. Posibles Casos de Estudio (Datos Obtenidos) . . . . . . . . . . . . . . 107
XII
3.4. Posibles Casos de Estudio (Datos Normalizados) . . . . . . . . . . . . 109
3.5. Posibles Casos de Estudio (Datos Ajustados) . . . . . . . . . . . . . . 111
3.6. Criterio de Selección . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
1. Repositorio de Google Guava . . . . . . . . . . . . . . . . . . . . . . . 133
2. Repositorio de JUnit . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
3. Repositorio de Log4j . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
4. Repositorio de SLF4J . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
5. Seguimiento de Incidentes de Commons BCEL . . . . . . . . . . . . . 134
6. Seguimiento de Incidentes de Commons BeanUtils . . . . . . . . . . . 134
7. Seguimiento de Incidentes de Commons BSF . . . . . . . . . . . . . . 135
8. Seguimiento de Incidentes de Commons Chain . . . . . . . . . . . . . 135
9. Seguimiento de Incidentes de Commons CLI . . . . . . . . . . . . . . 135
10. Seguimiento de Incidentes de Commons Codec . . . . . . . . . . . . 136
11. Seguimiento de Incidentes de Commons Collections . . . . . . . . . . 136
12. Seguimiento de Incidentes de Commons Compress . . . . . . . . . . 136
13. Seguimiento de Incidentes de Commons Configuration . . . . . . . . 137
14. Seguimiento de Incidentes de Commons CSV . . . . . . . . . . . . . 137
15. Seguimiento de Incidentes de Commons Daemon . . . . . . . . . . . 137
16. Seguimiento de Incidentes de Commons Dbcp . . . . . . . . . . . . . 138
17. Seguimiento de Incidentes de Commons Dbutils . . . . . . . . . . . . 138
XIII
18. Seguimiento de Incidentes de Commons Digester . . . . . . . . . . . 138
19. Seguimiento de Incidentes de Commons Discovery . . . . . . . . . . 139
20. Seguimiento de Incidentes de Commons EL . . . . . . . . . . . . . . . 139
21. Seguimiento de Incidentes de Commons Email . . . . . . . . . . . . . 139
22. Seguimiento de Incidentes de Commons Exec . . . . . . . . . . . . . 140
23. Seguimiento de Incidentes de Commons FileUpload . . . . . . . . . . 140
24. Seguimiento de Incidentes de Commons Functor . . . . . . . . . . . . 140
25. Seguimiento de Incidentes de Commons Imaging . . . . . . . . . . . . 141
26. Seguimiento de Incidentes de Commons IO . . . . . . . . . . . . . . . 141
27. Seguimiento de Incidentes de Commons JCI . . . . . . . . . . . . . . 141
28. Seguimiento de Incidentes de Commons JCS . . . . . . . . . . . . . . 142
29. Seguimiento de Incidentes de Commons Jelly . . . . . . . . . . . . . . 142
30. Seguimiento de Incidentes de Commons JEXL . . . . . . . . . . . . . 142
31. Seguimiento de Incidentes de Commons JXPath . . . . . . . . . . . . 143
32. Seguimiento de Incidentes de Commons JXPath . . . . . . . . . . . . 143
33. Seguimiento de Incidentes de Commons Lang . . . . . . . . . . . . . 143
34. Seguimiento de Incidentes de Commons Launcher . . . . . . . . . . . 144
35. Seguimiento de Incidentes de Commons Log4j . . . . . . . . . . . . . 144
36. Seguimiento de Incidentes de Commons Logging . . . . . . . . . . . . 144
37. Seguimiento de Incidentes de Commons Math . . . . . . . . . . . . . 145
38. Seguimiento de Incidentes de Commons Modeler . . . . . . . . . . . 145
XIV
39. Seguimiento de Incidentes de Commons Net . . . . . . . . . . . . . . 145
40. Seguimiento de Incidentes de Commons OGNL . . . . . . . . . . . . 146
41. Seguimiento de Incidentes de Commons Pool . . . . . . . . . . . . . . 146
42. Seguimiento de Incidentes de Commons Primitives . . . . . . . . . . . 146
43. Seguimiento de Incidentes de Commons Proxy . . . . . . . . . . . . . 147
44. Seguimiento de Incidentes de Commons SCXML . . . . . . . . . . . . 147
45. Seguimiento de Incidentes de Commons Validator . . . . . . . . . . . 147
46. Seguimiento de Incidentes de Commons VFS . . . . . . . . . . . . . . 148
47. Seguimiento de Incidentes de Commons VFS . . . . . . . . . . . . . . 148
48. Seguimiento de Incidentes de Commons Weaver . . . . . . . . . . . . 148
LISTADO DE FRAGMENTOS DE CÓDIGO
1.1. Ejemplo de Función de Orden Superior . . . . . . . . . . . . . . . . . 4
1.2. Ejemplo de Función Pura . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3. Ejemplo de Función Impura . . . . . . . . . . . . . .. . . . . . . . . . 5
1.4. Ejemplo de Datos Inmutables . . . . . . . . . . . . . . . . . . . . . . . 5
1.5. Ejemplo de Datos Mutables . . . . . . . . . . . . . . . . . . . . . . . . 6
1.6. Ejemplo de Referencia Transparencial . . . . . . . . . . . . . . . . . . 6
1.7. Ejemplo Contrario de Referencia Transparencial . . . . . . . . . . . . 7
1.8. Ejemplo de Encapsulamiento . . . . . . . . . . . . . . . . . . . . . . . 9
1.9. Ejemplo de Herencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.10.Ejemplo de Polimorfismo . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.11.Ejemplo de Composición . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.12.Ejemplo de Encapsulamiento Estático . . . . . . . . . . . . . . . . . . 19
1.13.Extracción de Código (Encapsulamiento Estático) . . . . . . . . . . . 20
1.14.Refactorización utilizando Encapsulamiento Estático . . . . . . . . . . 21
1.15.Ejemplo de Objeto como Contenedor . . . . . . . . . . . . . . . . . . 22
1.16.Ejemplo de Código como Datos . . . . . . . . . . . . . . . . . . . . . . 23
1.17.Ejemplo de Lı́nea de Comandos . . . . . . . . . . . . . . . . . . . . . 23
1.18.Ejemplo de Rust . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
1.19.Ejemplo de Clojure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
1.20.Ejemplo de Elixir . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
1.21.Ejemplo de Scala . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
1.22.Ejemplo de Erlang . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
1.23.Ejemplo de OCaml . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
1.24.Ejemplo de functional.js . . . . . . . . . . . . . . . . . . . . . . . . . . 44
XV
XVI
1.25.Ejemplo de Javaslang . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
1.26.Ejemplo de functional-ruby . . . . . . . . . . . . . . . . . . . . . . . . 47
1.27.Ejemplo de functional-php . . . . . . . . . . . . . . . . . . . . . . . . . 48
1.28.Ejemplo de Underscore.js . . . . . . . . . . . . . . . . . . . . . . . . . 49
2.1. Efecto Secundario Explı́cito . . . . . . . . . . . . . . . . . . . . . . . . 57
2.2. Efecto Secundario Implı́cito . . . . . . . . . . . . . . . . . . . . . . . . 57
2.3. Evaluación Perezosa - Haskell . . . . . . . . . . . . . . . . . . . . . . 58
2.4. Evaluación Perezosa - Java . . . . . . . . . . . . . . . . . . . . . . . . 58
2.5. Ejemplo de Función de Orden Superior . . . . . . . . . . . . . . . . . 59
2.6. Función Suma en Haskell . . . . . . . . . . . . . . . . . . . . . . . . . 59
2.7. Función Suma en Java . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
2.8. Ejemplo de Uso Función Suma en Haskell . . . . . . . . . . . . . . . . 60
2.9. Ejemplo de Uso Función Suma en Java . . . . . . . . . . . . . . . . . 60
2.10.Ejemplo de Aplicación Parcial de Funciones . . . . . . . . . . . . . . . 62
2.11.Módulo Maybe en Haskell . . . . . . . . . . . . . . . . . . . . . . . . . 69
2.12.Interfaz Maybe en Java . . . . . . . . . . . . . . . . . . . . . . . . . . 69
2.13.Módulo Maybe en Java . . . . . . . . . . . . . . . . . . . . . . . . . . 70
2.14.Ejemplo de Uso - Maybe.maybe . . . . . . . . . . . . . . . . . . . . . 71
2.15.Ejemplo de Uso - Maybe.isNothing . . . . . . . . . . . . . . . . . . . . 72
2.16.Ejemplo de Uso - Maybe.isJust . . . . . . . . . . . . . . . . . . . . . . 73
2.17.Prueba isNothingReturnsTrue . . . . . . . . . . . . . . . . . . . . . . . 78
2.18.Primera Iteración isNothing . . . . . . . . . . . . . . . . . . . . . . . . 78
2.19.Prueba isNothingReturnsFalse . . . . . . . . . . . . . . . . . . . . . . 79
2.20.Segunda Iteración isNothing . . . . . . . . . . . . . . . . . . . . . . . 79
2.21.Estructura de Datos Función . . . . . . . . . . . . . . . . . . . . . . . 82
2.22.Ejemplo de Función de Orden Superior . . . . . . . . . . . . . . . . . 82
2.23.Función Parcialmente Aplicada . . . . . . . . . . . . . . . . . . . . . . 83
2.24.Ejemplo de Uso Función de Orden Superior . . . . . . . . . . . . . . . 83
2.25.Ejemplo de Currying . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
2.26.Ejemplo de Uso de Currying . . . . . . . . . . . . . . . . . . . . . . . . 84
2.27.Ejemplo de Aplicación Parcial de Funciones . . . . . . . . . . . . . . . 85
2.28.Proceso de Construcción de Gradle . . . . . . . . . . . . . . . . . . . 91
XVII
2.29.Ejemplo de Prueba Unitaria . . . . . . . . . . . . . . . . . . . . . . . . 101
3.1. Método fail Antes de la Refactorización . . . . . . . . . . . . . . . . . 113
3.2. Método fail Después de la Refactorización . . . . . . . . . . . . . . . 114
3.3. Método equalsRegardingNull Antes de la Refactorización . . . . . . . 115
3.4. Método equalsRegardingNull Después de la Refactorización . . . . . 115
3.5. Método doubleIsDifferent Antes de la Refactorización . . . . . . . . . 116
3.6. Método floatIsDifferent Antes de la Refactorización . . . . . . . . . . . 116
3.7. Método doubleIsDifferent Después de la Refactorización . . . . . . . 117
3.8. Método floatIsDifferent Después de la Refactorización . . . . . . . . . 117
3.9. Método isDifferent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
3.10.Método formatClassAndValue Antes de la Refactorización . . . . . . . 118
3.11.Método formatClassAndValue Déspues de la Refactorización . . . . . 118
3.12.Método doubleIsDifferent . . . . . . . . . . . . . . . . . . . . . . . . . 120
RESUMEN
En el capı́tulo 1, se presenta una breve introducción sobre los paradigmas de pro-
gramación funcionales y orientados a objetos, al igual que una introducción sobre
los lenguajes de programación Haskell y Java. Una vez definidos dichos paradig-
mas y lenguajes de programación, se procedió a realizar una comparación entre
ellos.
En el capı́tulo 2, se definió el alcance de la librerı́a desarrollada, basándose en
algunos criterios, como son las limitaciones del lenguaje y la compatibilidad con
versiones anteriores de la JVM (desde la versión 1.6 en adelante). Una vez definido
el alcance de la librerı́a se procedió a la implementación utilizando la técnica de
desarrollo guiado por pruebas (TDD).
En el capı́tulo 3, se seleccionó a JUnit como caso de estudio utilizando criterios de
selección previamente definidos: porcentaje de uso, número de problemas reporta-
dos y número de solicitudes de cambio. Una vez seleccionado el caso de estudio,
se refactorizó el código utilizando la librerı́a desarrollada en el capı́tulo 2, y se midió
los resultados obtenidos en término de la complejidad ciclomática, encontrando una
mejora mayor al 50 %.
Finalmente el capı́tulo 4, contiene las conclusiones y recomendaciones encontradas
durante la realización del proyecto.
1
PRESENTACIÓN
La naturaleza del software es evolutiva, ya que se debe ajustar a las necesidades
definidas por los usuarios. Dichos ajustes deben ser realizado con frecuencia, lo
cual depende directamente del diseño del software. Un software altamente acopla-
do será difı́cil de mantener, ya que cualquier cambio causarı́a una serie de efectos
en cascada, volviendo las tareas de mantenimiento y corrección de errores compli-
cadas.
El paradigma funcional realiza una clara separación entre datos y funcionalidad lo
cual permite desarrollar aplicaciones bajamente acopladas, estos conceptos fueron
aplicados dentro de una librerı́a funcional para desarrollar aplicaciones fáciles de
mantener, lo cual justificarı́a el desarrollo del proyecto.
Con el fin de cuantificar las mejoras obtenidas al utilizar la librerı́a desarrollada,
se procedió a refactorizar un caso de estudio, el cual fue seleccionado bajo un
conjunto de métricas de selección. Una vez seleccionado el caso de estudio, se
procedió a evaluar la complejidad ciclomática de la librerı́a antes y después de la
refactorización. Los resultados obtenidos indicaron la reducción de la complejidadciclomática en un 50 %.
2
CAPÍTULO 1. MARCO TEÓRICO
1.1 DEFINICIÓN DEL PARADIGMA DE PROGRAMACIÓN FUNCIO-
NAL
La programación funcional inicia con LISP, sin embargo el nombre de paradigma no
fue introducido sino hasta 1.977 por John Backus en su paper ganador del Premio
Turing llamado Can Programming Be Liberated From the von Neumann Style? A
Functional Style and Its Algebra of Programs [5]. Backus menciona múltiples pun-
tos de vista acerca de construir aplicaciones como combinaciones de ecuaciones
algebraicas.
En la programación funcional los programas son ejecutados mediante la evaluación
de expresiones, en contraste con la programación imperativa en donde los progra-
mas están compuestos de instrucciones que cambian el estado global cuando se
ejecutan. Tı́picamente, la programación funcional evita utilizar estados mutables [7].
1.1.1 CARACTERÍSTICAS GENERALES
A continuación un listado de algunas de las caracterı́sticas principales de la progra-
mación funcional:
3
4
Funciones de Orden Superior
Son funciones que toman como argumentos a otras funciones. Las funciones de or-
den superior son útiles para refactorizar código y reducir el número de repeticiones
dentro del código [33].
1 > map (+1) [ 1 , 2 , 3 ]
2 [2 , 3 , 4 ]
Fragmento de Código 1.1: Ejemplo de Función de Orden Superior
En el fragmento de código 1.1 anterior la función map toma como argumento a la
función (+1), la cual es aplicada a cada uno de los elementos de la lista [1, 2, 3]
obteniendo como resultado [2, 3, 4].
Puridad
Algunos lenguajes de programación permiten expresiones que lanzan acciones adi-
cionalmente a retornar valores, este tipo de acciones se lo conoce como efectos
secundarios. Los lenguajes que prohı́ben los efectos secundarios son conocidos
como lenguajes puros [18].
A continuación dos fragmentos de código 1.2 y 1.3, los cuales retornan el mismo
resultado, sin embargo uno de ellos tiene un efecto secundario:
1 sum : : I n t −> I n t −> I n t
2 sum x y = x + y
Fragmento de Código 1.2: Ejemplo de Función Pura
5
1 public i n t sum( i n t x , i n t y ) {
2 System . out . p r i n t l n ( ” Running . . . ” ) ;
3 return x + y ;
4 }
Fragmento de Código 1.3: Ejemplo de Función Impura
Como se puede observar en el fragmento de código 1.3, la función sum no solo
retorna el resultado de la suma; en la lı́nea de código 2 se imprime un mensaje
de texto en la pantalla, lo cual es considerado un efecto secundario debido a que
cambia el estado inicial de la pantalla, a diferencia del fragmento de código 1.2 en
donde sólo se retorna el resultado de la suma.
Datos Inmutables
Un dato inmutable por definición es aquel que no puede ser modificado, en la pro-
gramación funcional al trabajar con valores inmutables cada modificación crea una
copia del valor original dejando intacto el valor original [14].
A continuación dos fragmentos de código 1.4 y 1.5, en los cuales se puede apreciar
la diferencia entre eliminar un elemento de una lista inmutable en Haskell y una
mutable en Java:
1 > l e t xs = [1 , 2 , 3 ]
2 [1 , 2 , 3 ]
3 > delete 1 xs
4 [2 , 3 ]
5 > xs
6 [1 , 2 , 3 ]
Fragmento de Código 1.4: Ejemplo de Datos Inmutables
6
1 > L i s t <In teger> xs = [1 , 2 , 3 ] ;
2 [ 1 , 2 , 3 ]
3 > xs . remove ( 1 ) ;
4 [2 , 3 ]
5 > xs ;
6 [2 , 3 ]
Fragmento de Código 1.5: Ejemplo de Datos Mutables
Como se puede observar en el fragmento de código 1.5, la lista original definida en
la lı́nea de código 1, después de eliminar el elemento 1 ha sido modificada, esto se
puede evidenciar en la lı́nea de código 7.
Referencia Transparencial
Las operaciones puras siempre retornan el mismo resultado cada vez que son in-
vocadas, a está propiedad se la conoce como referencia transparencial [20].
A continuación dos fragmentos código 1.6 y 1.7 en donde se puede observar la di-
ferencia entre una función con referencia transparencial y una sin referencia trans-
parencial:
1 > 1 + 2
2 3
3 > 1 + 2
4 3
Fragmento de Código 1.6: Ejemplo de Referencia Transparencial
7
1 > System . c u r r e n t T i m e M i l l i s ( ) ;
2 1375025861
3 > System . c u r r e n t T i m e M i l l i s ( ) ;
4 1375025862
Fragmento de Código 1.7: Ejemplo Contrario de Referencia Transparencial
Como se puede observar en el fragmento de código 1.7, la función currentTimeMillis
siempre retorna un resultado diferente, esto se considera una violación al principio
de referencia transparencial.
1.1.2 LENGUAJE DE PROGRAMACIÓN HASKELL
Haskell es un avanzado lenguaje de programación puramente funcional. Un pro-
ducto vanguardista Open-Source con más de 20 años de investigación, permite un
desarrollo de software rápido robusto, conciso, y correcto. Posee un alto soporte
de integración con otros lenguajes, construido con concurrencia y paralelismo, de-
buggers, perfiles, grandes librerı́as y una comunidad muy activa. Haskell permite
fácilmente producir software flexible, mantenible y de alta calidad [21].
Caracterı́sticas Principales
La tabla 1.1 a continuación lista las principales caracterı́sticas del lenguaje de pro-
gramación Haskell:
Caracterı́stica Descripción
Tipado Estático Cuando se compila un programa, el compilador cono-
ce que parte del código es un número, cual es una ca-
dena de texto y ası́ sucesivamente. Esto significa que
muchos posibles errores son capturados al momento
de compilación.
8
Caracterı́stica Descripción
Evaluación Perezosa Significa que al menos que no se indique explı́cita-
mente, Haskell no ejecutará funciones y calculará va-
lores hasta que sea forzado a mostrar un resultado.
Tabla 1.1: Caracterı́sticas Principales de Haskell
1.2 DEFINICIÓN DEL PARADIGMA DE PROGRAMACIÓN ORIEN-
TADO A OBJETOS
El paradigma orientado a objetos no es sólo un estilo de programación, también es
un método de diseño para la construcción de sistemas.
Los lenguajes orientados a objetos permiten al programador especificar unidades
autónomas en forma de objetos, los cuales son construidos de datos y los métodos
u operaciones que pueden ser ejecutados sobre el objeto.
En la programación orientada a objetos un objeto contiene datos y provee operacio-
nes (o métodos) para acceder a los datos. Los datos en un objeto no son visibles
directamente, sólo a través de operaciones. En otras palabras las operaciones son
la interfaz de un objeto para los usuarios del objeto.
1.2.1 CARACTERÍSTICAS GENERALES
A continuación una breve recopilación, sobre las principales caracterı́sticas de la
programación orientado a objetos encontrados en la mayorı́a de lenguajes de pro-
gramación pertenecientes a este paradigma:
9
Encapsulamiento
Procedimiento utilizado para ocultar detalles de implementación de una clase hacia
el exterior, también es utilizado para restringir el acceso de otras clases a ciertos
atributos y métodos definidos [22].
A continuación un fragmento de código 1.8 en donde la clase User solo expone
métodos de lectura:
1 public class User {
2 private S t r i n g f i rs tName ;
3 private S t r i n g lastName ;
4
5 public User ( S t r i n g f i rstName , S t r i n g lastName ) {
6 th is . f i rs tName = f i rs tName ;
7 th is . lastName = lastName ;
8 }
9
10 public S t r i n g getFirstName ( ) {
11 return f i rs tName ;
12 }
13
14 public S t r i n g getLastName ( ) {
15 return lastName ;
16 }
17 }
Fragmento de Código 1.8: Ejemplo de Encapsulamiento
Como se puede observar en el fragmento de código 1.8, la clase User solo expone
métodos a otras clases para poder acceder a sus atributos firstName y lastName,
impidiendo que estos atributos sean modificados desde fuera de la clase.
10
Herencia
La herencia de clases puede es utilizada para reutilizar atributos y métodos defini-
dos en una clase padre, por lo general cuando se tiene una relación del tipo is-a es
una buena opción usar herencia de clases [22].
1 public class Bicyc le { .. . }
2
3 public class MountainBike extends Bicyc le { . . . }
Fragmento de Código 1.9: Ejemplo de Herencia
Como se puede observar en el fragmento de código 1.9, la clase MountainBike
es una especialización de la clase Bicycle, por lo tanto se utiliza herencia para
representar está relación.
Polimorfismo
Dos clases se consideran polimórficas, si por lo menos unos de sus métodos define
la misma interfaz, es decir tanto el nombre del método como los tipos de datos
recibidos como argumentos y el tipo de dato de retorno son los mismos [22].
El polimorfismo es utilizado para definir métodos los cuales se comporten diferente
dependiendo el contexto de ejecución. A continuación un fragmento de código 1.10:
11
1 public inter face Shape {
2 void draw ( ) ;
3 }
4
5 public class C i r c l e implements Shape {
6 public void draw ( ) { . . . }
7 }
8
9 public class Square implements Shape {
10 public void draw ( ) { . . . }
11 }
Fragmento de Código 1.10: Ejemplo de Polimorfismo
Como se puede observar en el fragmento de código 1.10, las clases Circle y Square
pueden ser dibujadas mediante la implementación del método draw, sin embargo
cada una de las clases será dibujado de manera diferente dependiendo la figura a
la cual representan.
Composición
La composición de clases, consiste en construir una clase compleja a partir de
pequeñas clases, con el fin de poder separar responsabilidades en diferentes cla-
ses [22].
A continuación un fragmento de código 1.11 de ejemplo:
12
1 public class Engine { . . . }
2
3 public class Car {
4 private Engine engine ;
5
6 public Car ( Engine engine ) {
7 th is . engine = engine ;
8 }
9 }
Fragmento de Código 1.11: Ejemplo de Composición
Como se puede observar en el fragmento de código 1.11, la clase Car se encuen-
tra compuesta de un atributo engine del tipo Engine, es decir la clase Car conoce
sobre la existencia de un motor, sin embargo no conoce sobre los detalles de su
implementación.
1.2.2 LENGUAJE DE PROGRAMACIÓN JAVA
Es un lenguaje orientado a objetos multipropósito utilizado para el desarrollo de
diversas aplicaciones, desde aplicaciones de escritorio hasta aplicaciones móvi-
les [32].
Caracterı́sticas Generales
La tabla 1.2 a continuación lista las caracterı́sticas más destacadas encontradas
dentro del lenguaje de programación Java:
13
Caracterı́stica Descripción
Independencia de Plataforma Java provee un middleware de software, el cual permi-
te que el código escrito en este lenguaje sea portable
a través de diferentes infraestructuras de hardware.
Portabilidad El bytecode generado por el compilador de Java pue-
de ser importado a cualquier plataforma.
Multihilos En Java se pueden escribir programas que manejen
múltiples tareas al mismo tiempo definiendo varios hi-
los. La principal ventaja de utilizar múltiples hilos es
que la memoria es compartida.
Distribuido Las tecnologı́as de Java Remote Method Invocation
(RMI) y Enterprise Java Beans (EJB) son utilizados
para la creación de aplicaciones distribuidas, permi-
tiendo acceder archivos llamando a métodos de otra
máquina a través de la red.
Tabla 1.2: Caracterı́sticas de Java
1.3 COMPARACIÓN ENTRE PARADIGMAS FUNCIONAL Y ORIEN-
TADO A OBJETOS
Una vez descritas tanto las caracterı́sticas del paradigma funcional en la sección 1.1,
como las caracterı́sticas del paradigma orientado a objectos en la sección 1.2, se
procederá a realizar un análisis comparativo de dichos paradigmas al igual que sus
lenguajes Haskell y Java respectivamente.
1.3.1 COMPARACIÓN ENTRE PARADIGMAS
La tabla 1.3 a continuación realiza un análisis comparativo entre los diferentes pa-
radigmas de programación expuestos anteriormente en las secciones 1.1 y 1.2:
14
Caracterı́stica FP OOP Análisis Comparativo
Funciones de
Orden Superior
Sı́ cumple No cumple No todos los lenguajes orientados a obje-
tos soportan esta caracterı́stica, sólo aque-
llos que incluyen funciones de primer or-
den.
Puridad Sı́ cumple No cumple En los lenguajes orientados a objetos no
existe ninguna restricción referente a tener
efectos secundarios.
Datos Inmuta-
bles
Sı́ cumple No cumple La programación orientada a objetos se ba-
sa en el cambio de estado de un objeto por
lo cual al menos que los datos sean defi-
nidos explı́citamente como inmutables está
caracterı́stica no está disponible.
Referencia
Transparencial
Sı́ cumple No cumple Una misma función pura retorna siempre
un mismo valor, sin embargo en lenguajes
orientados a objetos debido a los efectos
secundarios una función puede verse in-
fluenciada por efectos externos que cam-
bien su resultado.
Encapsulamiento Sı́ cumple Sı́ cumple En lenguajes funcionales se puede realizar
tanto encapsulamiento de funciones como
de estructura de datos, mientras que en los
lenguajes orientados a objetos se pueden
realizar a nivel de clase, métodos y atribu-
tos.
Herencia No cumple Sı́ cumple En los lenguajes funcionales no existe he-
rencia de objetos ya que se trabaja con es-
tructuras de datos.
15
Caracterı́stica FP OOP Análisis Comparativo
Polimorfismo Sı́ cumple Sı́ cumple En lenguajes orientados a objetos existe
polimorfismo a nivel de clases, mientras
que en lenguajes funcionales existen poli-
morfismos de estructuras de datos.
Composición Sı́ cumple Sı́ cumple En los lenguajes funcionales no solo se
puede componer estructuras de datos,
también es posible realizar composición de
funciones.
Tabla 1.3: Comparación entre Paradigmas
1.3.2 COMPARACIÓN ENTRE LENGUAJES
Una vez realizada la comparación entre los paradigmas de programación Functional
Programming (FP) (1.1) y Object Oriented Programming (OOP) (1.2), se procederá
a realizar la comparación entre los lenguajes de programación Haskell (1.1.2) y Java
(1.2.2):
16
Caracterı́stica Haskell Java Análisis Comparativo
Puramente
Funcional
Sı́ cumple No cumple Haskell es un lenguaje puramente funcio-
nal, es decir el desarrollador mediante pro-
gramación declarativa indica al computador
cómo realizar una acción en lugar de escri-
bir instrucciones secuenciales. En Java los
programas deben describir detalladamente
los pasos que el computador debe realizar
para cumplir el objetivo.
Tipado Estático Sı́ cumple Sı́ cumple Ambos lenguajes son fuertemente tipados,
el compilador analiza el código fuente com-
probando que los tipos definidos sean co-
rrectos, además no existe colisión de tipos,
es decir, la conversión de un tipo de dato a
otro debe ser explı́cita.
Evaluación Pe-
rezosa
Sı́ cumple No cumple En Java cualquier expresión es evaluada
explı́citamente, es decir si se tiene una lista
de 20 elementos y se desea imprimir los 10
primeros elementos, Java necesita evaluar
la lista completa primero, antes de imprimir
los deseados. En Haskell esto no sucede
solo se evaluarán los 10 primeros elemen-
tos a ser impresos.
Independencia
de Plataforma
Sı́ cumple Sı́ cumple Tanto Haskell como Java son independien-
tes de plataforma.
17
Caracterı́stica Haskell Java Análisis Comparativo
Multihilos Sı́ cumple Sı́ cumple Los dos lenguajes soportan procesamiento
multihilos.
Distribuidos Sı́ cumple Sı́ cumple Ambos lenguajes son de propósito general
y funcionan en ambientes distribuidos.
Tabla 1.4: Comparación entre Lenguajes
1.3.3 ANÁLISIS DE RESULTADOS
Una vez realizada la comparación entre paradigmas y lenguajes de programación
en las secciones 1.3.1 y 1.3.2, se procederá con el análisis de los resultados obte-
nidos:
La inmutabilidad de datos provista por defecto en lenguajes funcionales como
Haskell, permite construir aplicaciones concurrentes de manera natural sin
considerar la concurrencia de datos como parte del diseño ya que no existen
cambios de estado.
La evaluación perezosa de expresiones permite gestionar los recursos de una
manera efectiva, ya que cualquier evaluación se realiza bajo demanda mejo-
rando la velocidadde ejecución y disminuyendo el consumo de recursos.
Tanto la puridad como la referencia transparencial explı́cita definida en lengua-
jes como Haskell, permite tener una clara separación entre funciones puras y
aquellas con efectos secundarios, esto mejora tanto la lectura como la escri-
tura de pruebas.
18
1.4 ESTILO DE PROGRAMACIÓN FUNCIONAL SOBRE UN LEN-
GUAJE ORIENTADO A OBJETOS
En la actualidad existen varios lenguajes de programación los cuales incluyen ca-
racterı́sticas de la programación funcional, la tabla 1.5 a continuación lista algunos
de estos lenguajes y sus caracterı́sticas:
Lenguaje Caracterı́sticas
Ruby Las listas en Ruby proveen funciones de orden su-
perior para la transformación de listas como map y
reduce.
JavaScript En JavaScript las funciones son objetos de primer or-
den, es decir una función puede ser asignada a una
variable, o utilizada como argumentos de otra función.
Java (versión 8 en adelante) Incluye funciones de orden superior y métodos para
transformar colecciones de una manera funcional, co-
mo por ejemplo map y reduce.
C# / Visual Basic (LINQ [29]) Es un lenguaje integrado de consulta, incluye carac-
terı́sticas para la consulta de listas y se extiende a
bases de datos.
Tabla 1.5: Estilos de Programación Funcional en OOP
1.4.1 PATRONES DE DISEÑO FUNCIONALES
A pesar que el paradigma funcional es diferente del orientado a objetos, es posible
programar en lenguajes orientados a objetos utilizando un estilo de programación
funcional. Los patrones de diseño a continuación han sido tomados del libro Beco-
ming Functional [4].
19
Encapsulamiento Estático
Con el fin de explicar de una manera práctica el patrón de diseño, se utilizará el
siguiente fragmento de código 1.12:
1 public class Contact {
2 private S t r i n g f i rs tName ;
3 private S t r i n g lastName ;
4 private S t r i n g emai l ;
5
6 public void sendEmail ( ) {
7 sendEmail ( ” To : ” + emai l + ” \nSubject : My Subject \
nBody : . . . ” ) ;
8 }
9
10 private void sendEmail ( S t r i n g content ) { . . . }
11 }
Fragmento de Código 1.12: Ejemplo de Encapsulamiento Estático
Como se puede observar en el fragmento de código 1.12, la clase Contact posee
las siguientes responsabilidades:
Contiene los datos referentes al usuario.
Es encargado de enviar correos electrónicos al usuario.
A simple vista parece no existir ninguna violación al principio de responsabilidad
simple ya que ambas responsabilidades están relacionadas al usuario, sin embargo
la manera en la cual se envı́e un correo electrónico debe ser transparente a la clase
Contact.
20
La clase Contact necesita enviar un correo electrónico sin conocer sobre detalles
de su implementación; es por ello que toda lógica relacionada a enviar un correo
electrónico será extraı́da a otra clase.
El fragmento de código 1.13, a continuación emplea la técnica de encapsulamiento
estático para extraer toda la lógica referente a enviar un correo electrónico a la clase
Email:
1 public class Email {
2 private S t r i n g address ;
3 private S t r i n g sub jec t ;
4 private S t r i n g body ;
5
6 public s t a t i c void send ( Email emai l ) {
7 . . .
8 }
9 }
Fragmento de Código 1.13: Extracción de Código (Encapsulamiento Estático)
Una vez encapsulada la lógica relacionada a enviar correos electrónicos en la clase
Email, se puede proceder a refactorizar la clase Contact de la siguiente manera:
21
1 public class Contact {
2 private S t r i n g f i rs tName ;
3 private S t r i n g lastName ;
4 private S t r i n g emai l ;
5
6 public void sendEmail ( ) {
7 Email . send (new Email ( email , ”My Subject ” , ”My Body ” ) )
;
8 }
9 }
Fragmento de Código 1.14: Refactorización utilizando Encapsulamiento Estático
Como se puede observar en el fragmento de código 1.14 la clase Contact des-
conoce sobre los detalles de la implementación relacionados a enviar un correo
electrónico, ya que toda está responsabilidad ha sido delegada a la clase Email.
Objeto como Contenedor
Este patrón de diseño es utilizado para encapsular el comportamiento de una fun-
ción dentro de atributos de una clase, permitiendo ası́ modificar el comportamiento
de la función [4].
Tomando como referencia la clase Email definida anteriormente 1.13, se puede
modificar el comportamiento del método send agregando un nuevo atributo a la
clase Email como se muestra en el fragmento de código 1.15 a continuación:
22
1 public class Email {
2 private boolean dearReader ;
3
4 public s t a t i c void send ( Email emai l ) {
5 i f ( emai l . isDearReader ( ) ) {
6 sendDearEmail ( emai l ) ;
7 } else {
8 sendEmail ( emai l ) ;
9 }
10 }
11
12 private s t a t i c void sendDearEmail ( Email emai l ) { . . . }
13
14 private s t a t i c void sendEmail ( Email emai l ) { . . . }
15 }
Fragmento de Código 1.15: Ejemplo de Objeto como Contenedor
Como se puede observar en el fragmento de código 1.15 todos los atributos rela-
cionados a enviar un correo electrónico han sido encapsulados dentro de la clase
Email.
Código como Datos
Uno de los puntos claves dentro de la programación funcional es tratar a las fun-
ciones como datos, es decir una función puede ser asignada a una variable o ser
pasada como argumento a otra función, está caracterı́stica permite reutilizar código
a un nivel granular [4].
Tomando como punto de partida el siguiente fragmento de código 1.16:
23
1 public class CommandLineOption {
2 private S t r i n g d e s c r i p t i o n ;
3 private Runnable f u n c t i o n ;
4 }
Fragmento de Código 1.16: Ejemplo de Código como Datos
Como se puede observar en el fragmento de código 1.16, la clase CommandLineOption
tiene como atributos description el cual describe la opción de la lı́nea de comando,
y atributo function el cual representa la acción realizada por la opción de la lı́nea de
comandos.
Utilizando la clase CommandLineOption definida anteriormente se puede construir
una lı́nea de comandos de la siguiente manera:
1 public class CommandLine {
2 public Map<St r ing , CommandLineOption> opt ions ( ) {
3 Map<St r ing , CommandLineOption> opt ions = new HashMap
<>() ;
4 op t ions . put ( ” c ” , createUser ( ) ) ;
5 op t ions . put ( ” d ” , deleteUser ( ) ) ;
6 return opt ions ;
7 }
8
9 private CommandLineOption createUser ( ) { . . . }
10 private CommandLineOption deleteUser ( ) { . . . }
11 }
Fragmento de Código 1.17: Ejemplo de Lı́nea de Comandos
Como se puede observar en fragmento de código 1.17, se crea una instancia de la
clase CommandLineOption para representar cada una de las acciones disponibles
24
en la lı́nea de comandos.
1.4.2 ESTADO DEL ARTE
La presente sección es una breve recopilación sobre el estado actual de la progra-
mación funcional en diversos campos:
Universidad
Empresa
Al igual que un listado de lenguajes y librerı́as funcionales, utilizados en la actuali-
dad.
Universidad
Durante las últimos años, las universidades han ido incorporando en su pénsum de
estudios cursos referentes a la programación funcional.
A continuación un listado de algunos de los cursos de programación funcional, dic-
tados alrededor del mundo:
Paı́s Reino Unido
Universidad Universidad de Edinburgh
Instructor Philip Wadler
Curso Informatics 1 - Functional Programming
Año 2015
Figura 1.1: Curso Universidad de Edinburgh
Fuente: http://www.inf.ed.ac.uk/teaching/courses/inf1/fp
25
Paı́s Estado Unidos
Universidad Universidad de Nottingham
Instructor Neil Ghani
Curso Functional Programming
Año 2015
Figura 1.2: Curso Universidad de Nottingham
Fuente: http://www.cs.nott.ac.uk/ gmh/afp.html
Paı́s Reino Unido
Universidad Universidad de Oxford
Instructor Jonathan Hill
Curso Functional Programming for the Integrated Graduate Development Pro-
gramme in Software Engineering at Oxford University
Año 2015
Figura 1.3: Curso Universidad de Oxford
Fuente: http://www.comlab.ox.ac.uk/igdp/text/course06.html26
Paı́s Argentina
Universidad Universidad Tecnológica Nacional
Instructor Estudiantes
Curso Paradigmas de Programación
Año 2015
Figura 1.4: Curso Universidad Tecnológica Nacional
Fuente: http://www.pdep.com.ar
Paı́s Colombia
Universidad Universidad de los Andes
Instructor Jorge Ricardo Cuellar
Curso Programación Funcional y sus Aplicaciones
Año 2015
Figura 1.5: Curso Universidad de los Andes
Fuente: http://matematicas.uniandes.edu.co/eventos/2015/haskell
27
Paı́s Estados Unidos
Universidad Universidad de Oklahoma
Instructor Rex Page
Curso Introduction to Computer Programming
Año 1997
Figura 1.6: Curso Universidad de Oklahoma
Fuente: http://www.cs.ou.edu/ rlpage/fpclassSpring97
Empresa
Empresas alrededor del mundo como Facebook y Apple, han empezado a utilizar
lenguajes funcionales tanto para el desarrollo de nuevos productos, como para la
creación de herramientas de desarrollo.
Empresa Facebook
Proyecto Haxl
Descripción Es una librerı́a que simplifica el acceso remoto a datos. Entre las
principales caracterı́sticas se encuentran: batch de múltiples peticiones a
una misma fuente de datos, solicitar datos de múltiples fuentes de datos
de manera concurrente y cache de solicitudes anteriores.
Año 2014
Figura 1.7: Haxl
Fuente: https://code.facebook.com/projects/854888367872565/haxl
28
Empresa Apple
Proyecto Swift
Descripción Es un lenguaje de programación desarrollado por Apple, a pesar
de no ser puramente funcional como Haskell, posee algunos conceptos de
la programación funcional como son: funciones de orden, funciones como
ciudadanos de primer orden y funciones anónimas.
Año 2015
Figura 1.8: Swift
Fuente: https://developer.apple.com/swift
Empresa Microsoft
Proyecto F#
Descripción Es un lenguaje de programación desarrollado por Microsoft como
parte de .NET framework, entre las principales caracterı́sticas se encuen-
tran: inmutabilidad de datos, aplicación parcial de funciones, expresiones
de objetos, entre otros.
Año 2005
Figura 1.9: F#
Fuente: http://fsharp.org
29
Empresa Intel
Proyecto Compilador de Haskell
Descripción Intel ha desarrollado un compilador en Haskell, como parte de su
investigación en paralelismo multinúcleo a escala.
Año 2013
Figura 1.10: Intel
Fuente: http://www.leafpetersen.com/leaf/publications/hs2013/hrc-paper.pdf
Empresa Whatsapp
Proyecto Servicio de Mensajerı́a
Descripción Whatsapp tiene un promedio de 8 billones de mensajes entrantes
y 12 billones de mensajes de salida por dı́a, esto es posible gracias al uso
de Erlang y FreeBSD.
Año 2013
Figura 1.11: Whatsapp
Fuente: https://www.erlang-solutions.com/about/news/erlang-powered-whatsapp-
exceeds-200-million-monthly-users
30
Empresa SumAll
Proyecto Procesamiento de Datos
Descripción Agrega varios flujos de datos de redes sociales. Se encuentran el
proceso de reescribir su backend en Haskell. Lo que nos atrajo sobre el
lenguaje es la disciplina y su aproximación para resolver problemas difı́ci-
les y complejos de manejar.
Año 2014
Figura 1.12: SumAll
Fuente: https://sumall.com
Lenguajes de Programación
La presente sección contiene un listado de lenguajes de programación funcionales,
utilizados tanto en la academia como en la construcción de aplicaciones.
Rust
Rust es un lenguaje de programación de sistemas rápido el cual garantiza segu-
ridad en la memoria y ofrece concurrencia sin complicaciones (sin condiciones de
carrera). No utiliza un recolector de basura y tiene un costo mı́nimo en tiempo de
ejecución [37].
Caracterı́sticas Descripción
Hilos sin Condiciones de Carrera La caracterı́stica de seguridad de memoria
de Rust se aplica a la historia de concu-
rrencia. Los programas en Rust deben ser
seguros de memoria, y no tener condicio-
nes de carrera, el sistema de tipos de Rust
se encuentra listo para está tarea.
31
Caracterı́sticas Descripción
Genéricos Basados en Traits Un trait es una caracterı́stica del lenguaje
la cual notifica al compilador de Rust que
el tipo debe ser provisto, por el contexto en
donde se ejecute la función.
Búsqueda de Patrones Al igual que otros lenguajes funcionales,
Rust posee la capacidad de comprobar si
una determinada secuencia de datos coin-
cide con algún patrón definido.
Inferencia de Tipos Rust posee la capacidad de deducir au-
tomáticamente el tipo de un dato a partir
de una expresión.
32
Caracterı́sticas Descripción
Bindings Eficientes en C Los Foreign Function Interface (FFI) flexi-
bles de Rust proveen bindings de C eficien-
tes los cuales permiten exponer e invocar
código de Rust sin ningún costo extra. Esto
permite reescribir una aplicación módulo a
módulo, una transición paulatina hacia una
mejor experiencia de desarrollo.
Tabla 1.6: Caracterı́sticas de Rust
A continuación un ejemplo de código 1.18 escrito en Rust tomado de la página
oficial [37]:
1 for token i n program . chars ( ) {
2 match token {
3 ’+ ’ => accumulator += 1 ,
4 ’− ’ => accumulator −= 1 ,
5 ’ ∗ ’ => accumulator ∗= 2 ,
6 ’ / ’ => accumulator /= 2 ,
7 => { /∗ i gnore every th ing e lse ∗ / }
8 }
9 }
Fragmento de Código 1.18: Ejemplo de Rust
Clojure
Clojure es un dialecto de Lisp, comparte con Lisp la filosofı́a de código como datos y
un sistema poderoso de macros. Clojure es un lenguaje de programación funcional
predominante, y cuenta con basto conjunto de estructuras de datos persistentes
inmutables. Cuando datos mutables son necesitados, Clojure ofrece un sistema de
33
software transaccional y un agente de sistema reactivo el cual asegura diseños
multihilos limpios y correctos [10].
Caracterı́stica Descripción
Desarrollo Dinámico Clojure es dinámico, lo cual significa que
solo ejecuta código compilado, también
permite la interacción con el lenguaje a par-
tir de su REPL. Dicha interacción, permite
evaluar código y variables de una manera
rápida.
Programación Funcional Clojure es un lenguaje de programación
funcional. Este provee herramientas para
impedir la mutación de estado, provee fun-
ciones como objetos de primera clase, y
enfatiza la recursión iterativa en lugar de
bucles con efectos secundarios.
Lisp Clojure es un miembro de la familia de Lisp,
sin embargo Clojure extiende el enfoque de
código como datos mucho más allá de las
listas entre paréntesis expresiones-s, hasta
vectores y mapas. Estos vectores y mapas
pueden ser utilizados en el sistema de ma-
cros.
34
Caracterı́stica Descripción
Polimorfismo en tiempo de Ejecución Los sistemas que utilizan polimorfismo en
tiempo de ejecución son fáciles de cambiar
y de extender. Clojure soporta polimorfis-
mo de muchas maneras diferentes:
Muchas de las estructuras de datos
principales en tiempo de ejecución de
Clojure, son definidas mediante inter-
faces de Java.
Clojure soporta la generación de im-
plementaciones de interfaces en Java
utilizando proxies proxy.
El lenguaje Clojure soporta polimor-
fismo tanto a lo largo de clases como
de herencia con múltiples métodos.
El lenguaje Clojure también soporta
un polimorfismo más rápido mediante
el uso de protocolos (sin embargo se
encuentra limitado solo a polimorfis-
mo a nivel de clases para tomar ven-
taja de las capacidades existentes en
la JVM).
Programación Concurrente Clojure, es un lenguaje practico, permite
cambiar el estado sin embargo provee me-
canismos para asegurar la consistencia,
mientras elimina la responsabilidad a los
desarrolladores de lidiar manualmente con
bloqueos y resolver conflictos.
35
Caracterı́stica Descripción
Funciona sobre la JVM Clojure está diseñado para ser un lenguaje
anfitrión, compartiendo el sistema de tipos
de la JVM. Compila todas las funciones a
bytecode de la JVM.
Tabla 1.7: Caracterı́sticas de Clojure
A continuación un ejemplo de código 1.19 escrito en Clojure tomado de GitHub [27]:
1 ( use ’ korma . db )
2
3 ( s e l e c t users
4 ( where ( or (= : username ” c h ri s ” )
5 (= : emai l ” chr is@chr is . com ” ) ) ) )
Fragmento de Código 1.19: Ejemplo de Clojure
Elixir
Elixir es un lenguaje de programación funcional dinámico, diseñado para la cons-
trucción de aplicaciones escalables y mantenibles [11].
Caracterı́stica Descripción
Escalabilidad Todo código se ejecuta sobre un pequeño hilo de pro-
ceso, el cual es aislado e intercambia información me-
diante mensajes.
Tolerancia a Fallos Elixir provee supervisores, los cuales describen como
reiniciar un parte del sistema cuando algún error se
presenta.
Programación Funcional Promueve un estilo de programación que ayuda al
desarrollador a escribir código pequeño, rápido y
mantenible.
36
Caracterı́stica Descripción
Ecosistema Creciente Elixir está construido con un gran conjunto de herra-
mientas para su fácil desarrollo. Mix es una herra-
mienta la cual facilita la creación de proyectos, manejo
de tareas, ejecutar pruebas y más.
Desarrollo Interactivo Herramientas como IEx (shell interactivo de Elixir) per-
miten interactuar con el lenguaje de manera practica,
mediante herramientas como auto-completar, debug-
ging, recarga de código.
Compatible con Erlang Elixir se ejecuta sobre la máquina virtual de Erlang, lo
cual permite ejecutar funciones Erlang directamente.
Tabla 1.8: Caracterı́stica de Elixir
A continuación un ejemplo de código 1.20 escrito en Elixir tomado de la página
oficial [11]:
37
1 def sum( a , b ) when i s i n t e g e r ( a ) and i s i n t e g e r ( b ) do
2 a + b
3 end
4
5 def sum( a , b ) when i s l i s t ( a ) and i s l i s t ( b ) do
6 a ++ b
7 end
8
9 def sum( a , b ) when i s b i n a r y ( a ) and i s b i n a r y ( b ) do
10 a <> b
11 end
12
13 sum 1 , 2
14 #=> 3
15
16 sum [ 1 ] , [ 2 ]
17 #=> [ 1 , 2 ]
18
19 sum ” a ” , ” b ”
20 #=> ” ab ”
Fragmento de Código 1.20: Ejemplo de Elixir
Scala
Scala es un lenguaje de programación multiparadigma, diseñado para expresar pa-
trones comunes de una manera concisa, elegante y con seguridad de tipos. De una
manera fácil integra caracterı́sticas de orientación a objectos y lenguajes funciona-
les [38].
38
Caracterı́sticas Descripción
Orientación a Objetos Scala es un lenguaje puro orientado a objetos en el
sentido que cada valor es un objeto. Los tipos y el
comportamiento de los objetos son descritos por la
clases y traits Trait. Las clases extienden a través de
subclases y una composición flexible basada en mi-
xins Mixin.
Funcional Scala es un lenguaje funcional en el sentido que cada
función es un valor. Scala provee una sintaxis lige-
ra para la definición de funciones anónimas, soporta
funciones de orden superior, permite que las funcio-
nes sean anidadas, y soporta Currying.
Tipado Estático Scala se encuentra equipado con un sistema de tipos
expresivo el cual se encarga de garantizar que las
abstracciones sean utilizadas de una manera cohe-
rente. En particular el sistema de tipos soporta:
Clases genéricas
Anotaciones de variantes
Lı́mites de tipos superior e inferior
Clases internas y tipos abstractos como miem-
bros de objetos
Tipos compuestos
Vistas
Métodos polimórficos
39
Caracterı́sticas Descripción
Extensible En practica, el desarrollo de aplicaciones de dominio
especı́fico por lo general requiere extensiones. Sca-
la provee una única combinación de mecanismos del
lenguaje la cual permite añadir nuevas caracterı́sticas
al lenguaje mediante librerı́as.
Tabla 1.9: Caracterı́sticas de Scala
A continuación un ejemplo de código 1.21 escrito en el lenguaje Scala [38]:
1 def max( x : I n t , y : I n t ) : I n t = {
2 return x > y ? x : y
3 }
4
5 max(1 , 2) / / => 2
Fragmento de Código 1.21: Ejemplo de Scala
Erlang
Erlang es un lenguaje de programación utilizado para la construcción masiva de
software escalable el cual requiera de alta disponibilidad. Algunos de ellos se en-
cuentran en uso dentro de las telecomunicaciones, banca, comercio electrónico, y
mensajerı́a instantánea [12].
40
Caracterı́sticas Descripción
Concurrencia Los procesos son bastante ligeros, con un
tamaño de alrededor de 500 bytes por pro-
ceso. Esto significa que millones de pro-
cesos pueden ser creados, incluso con
computadoras antiguas.
Debido a que los procesos de Erlang son
completamente independientes de sistema
operativo, el programa se comportará de
igual manera en Linux, FreeBSD, Windows
y otros sistemas sobre los cuales corre Er-
lang.
Reemplazo de Código en Caliente En un sistema de tiempo real usualmente
no se quiere detener el sistema para reali-
zar una actualización de código. En algu-
nos sistemas de tiempo real nunca serı́a
posible apagar el sistema para realizar una
actualización, este tipo de sistemas deben
ser diseñados con código dinámico actuali-
zable. Un ejemplo de este tipo de sistemas
es el sistema de control X2000 desplegado
por la NASA.
Multiplataforma Erlang corre sobre Linux, FreeBSD, Win-
dows, Solaris, Mac OS X, e incluso sobre
plataformas embebidas como VxWorks.
41
Caracterı́sticas Descripción
Soporte Un equipo dedicado de empleados de
Ericsson trabajan en Erlang. Soporte co-
mercial y servicios están disponibles pa-
ra Erlang. También existe una comunidad
bastante activa alrededor del mundo, cen-
trada alrededor de la lista de correo de
Erlang y su canal de Internet Relay Chat
(IRC).
Juega bien con el Mundo Exterior Provee integración con Java, .NET, C, Pyt-
hon y Ruby. Existe una interfaz de acuerdo
al sistema operativo deseado.
HiPE El compilador de Erlang puede compilar a
código nativo de Windows, Linux o Mac OS
X y forma parte de la distribución estándar
de Erlang.
Tipado Estático, cuando sea necesario Se puede anotar el código con información
sobre tipos y utilizar Dialyzer, un podero-
so verificador de tipos, el cual asegura la
validez del código y mejora el rendimiento.
Dialyzer forma parte de Erlang, y soporta
tipado gradual el cual ofrece máxima flexi-
bilidad.
Tabla 1.10: Caracterı́sticas de Erlang
A continuación un código de ejemplo 1.22 escrito en Erlang tomado de la página
oficial [12]:
42
1 connect ( Host , User , Password ) −>
2 { f t p s e r v e r , Host} ! {connect , s e l f ( ) , User , Password } ,
3 rece ive
4 { f t p s e r v e r , Reply} −> Reply ;
5 Other −> Other
6 a f t e r 10000 −> t imeout
7 end
Fragmento de Código 1.22: Ejemplo de Erlang
OCaml
El gestor de paquetes de OCaml (OPAM) soporta la instalación de múltiples com-
piladores, restricciones de paquetes flexibles, y un flujo de trabajo familiar con Git.
Los paquetes son automáticamente probados, cualquier notificación es enviada a
los mantenedores [31].
Caracterı́sticas Descripción
Sistema de Tipos Estático OCaml provee un colección de reglas asignadas a un
tipo, las cuales permiten construir variables, expresio-
nes, funciones o módulos.
Inferencia de Tipos Es la capacidad del compilador de deducir un tipo de-
pendiendo del contexto sobre el cual se evalúe.
Polimorfismo Paramétrico OCaml no soporta la sobrecarga de funciones debido
a que es demasiado complicado tener inferencia de
tipos y sobrecarga de funciones al mismo tiempo. Sin
embargo OCaml soporta polimorfismo paramétrico y
subtipos.
En OCaml, el polimorfismo paramétrico está introdu-
cido solo por el uso del constructor let, el cual es lla-
mado restricción de valores.
43
Caracterı́sticas Descripción
Funtores Los funtores son funciones de módulos a módulos,
pueden ser utilizadas para resolver una variedad de
problemas de estructura de código:
Inyección de dependencias.
Autoextensión de módulos.
Instanciación de módulos con estado.
Tabla 1.11: Caracterı́sticas de OCaml
A continuación un ejemplo de código 1.23 escrito en el lenguaje OCaml [31]:
1 l e t rec f a c t x = i f x <= 1 then 1 else x ∗ f a c t ( x − 1) ; ;
2 f a c t 5 ; ; − : i n t = 120
Fragmento de Código 1.23: Ejemplo de OCaml
Librerı́asde Programación
La presente sección es una breve recopilación, sobre el estado actual de la progra-
mación funcional aplicada a lenguajes orientados a objetos.
functional.js - 2015
Es una librerı́a funcional de JavaScript. Facilita la programación por medio de Currying
y point-free, está metodologı́a ha sido utilizada desde los inicios de la construcción
de la librerı́a [16].
44
Caracterı́stica Descripción
Currying fjs.curry permite facilita la creación de funciones de
orden superior mediante la invocación parcial de una
función existente, sin proveer todos los argumentos de
la función original.
Aridad La aridad de una función en JavaScript es el núme-
ro de argumentos esperados por una función. Con
fjs.curry es posible extender la aridad de una función
más allá de su longitud esperada.
Expresiones Lambda fjs permite especificar expresiones lambda de manera
opcional, en lugar de las funciones de JavaScript para
cualquiera de sus funciones que permitan currying.
fjs.each fjs.each permite iterar sobre elementos de una colec-
ción, aplicando una función iterador a cada elemento.
Esto es muy similar a la función nativa forEach dispo-
nible en navegadores modernos, sin embargo facilita
la implemetación de fjs.curry.
Tabla 1.12: Caracterı́sticas de functional.js
El ejemplo 1.24 a continuación ha sido tomado de GitHub [16]:
1 var add = f j s . cu r ry ( f u n c t i o n ( arg1 , arg2 ) {
2 return arg1 + arg2 ;
3 } ) ;
4
5 var add3 = add ( 3 ) ;
6 add (1 , 2 , 3) ; / / => 6
7 add3 (1 , 2 , 3 , 4 , 5) ; / / => 18
Fragmento de Código 1.24: Ejemplo de functional.js
45
Javaslang - 2014
Javaslang es una librerı́a funcional para Java 8 y versiones superiores. Javaslang
añade un API y algunas mejores practicas tomadas de lenguajes como Scala, para
tomar ventaja sobre las Lambdas en al programación diaria [24].
Caracterı́stica Descripción
Núcleo Javaslang viene con una representación de los tipos
básicos faltantes o son rudimentarios en Java.
Funciones La programación funcional es sobre valores y trans-
formaciones de valores utilizando funciones.
Colecciones Con Javaslang se ha puesto mucho esfuerzo en el di-
seño de la librerı́a de colecciones para Java, la cual
cumpla con los requerimientos de la programación
funcional, como la inmutabilidad.
Tabla 1.13: Caracterı́sticas de Javaslang
El ejemplo de código 1.25 a continuación, ha sido tomado de la página oficial de
Javaslang [24]:
1 f i n a l Tuple2<St r ing , In teger> java8 = Tuple . o f ( ” Java ” , 8)
;
2
3 f i n a l Tuple2<St r ing , In teger> guessWhat = java8 .map(
4 ( s , i ) −> Tuple . o f ( s + ” slang ” , i / 4)
5 ) ; / / => ( ” Javaslang ” , 2)
Fragmento de Código 1.25: Ejemplo de Javaslang
functional-ruby - 2013
La librerı́a funcional-ruby se encuentra inspirada en algunos lenguajes de progra-
46
mación y herramientas como Erlang, Clojure y Functional Java.
Caracterı́stica Descripción
Especificación de protocolo Especificación de protocolos inspirada por
los protocolos de Clojure, el comporta-
miento de Erlang, y los protocolos de
Objective-C.
Sobrecarga de Funciones La sobrecarga de funciones con un estilo
de Erlang permite la búsqueda de patro-
nes.
Threads Seguros Simple, seguridad de threads, estructuras
de datos inmutables, como son registros,
uniones, y tuplas, inspiradas por Clojure,
Erlang, y otros lenguajes funcionales.
Ejecución Perezosa La ejecución perezosa con una clase Delay
basada en Clojure delay.
Estructuras de Valor Estructuras de valor, simples, seguridad de
thread, una variación inmutable de las es-
tructuras abiertas de Ruby.
Tabla 1.14: Caracterı́sticas de functional-ruby
El ejemplo de código 1.26 a continuación ha sido tomado de GitHub [3]:
47
1 Name = Func t iona l : : Record .new ( : f i r s t , : middle , : l a s t , :
s u f f i x ) do
2 mandatory : f i r s t , : l a s t
3 defaul t : f i r s t , ’ J . ’
4 defaul t : l a s t , ’Doe ’
5 end
6
7 anon = Name.new
8 #=> #<record Name : f i r s t =>” J . ” , . . . >
9 matz = Name.new( f i r s t : ’ Yuk ih i ro ’ , l a s t : ’ Matsumoto ’ )
10 #=> #<record Name : f i r s t =>” Yuk ih i ro ” , . . . >
Fragmento de Código 1.26: Ejemplo de functional-ruby
functional-php - 2011
Es un conjunto de primitivos funcionales para PHP, principalmente inspirado por
Scala traversable collection, los arreglos en Dojo y Underscore.js [15].
Caracterı́stica Descripción
Arrays Trabaja con arrays y cualquier implementación de Tra-
versable
Interfaz consistente Provee una interfaz consistente para funciones las
cuales toman colecciones y callback, el primer
parámetro es siempre una colección, y el segundo el
callback. Los Callbacks siempre reciben los paráme-
tros $value, $index, $collection.
Soporta Closures Es posible utilizar tanto callbacks como closures.
Espacio de Nombres Todas las funciones residen en un mismo espacio de
nombres ”Functional”para evitar cualquier tipo de con-
flictos con cualquier otra extensión o librerı́a.
Tabla 1.15: Caracterı́sticas de functional-php
48
El ejemplo de código 1.27 a continuación ha sido tomado de GitHub [15]:
1 use f u n c t i o n Func t iona l \map;
2
3 map( range (0 , 100) , f u n c t i o n (\ $v ) { return \$v + 1 ;} ) ;
Fragmento de Código 1.27: Ejemplo de functional-php
Underscore.js - 2008
Underscore es una librerı́a de JavaScript la cual provee un completo conjunto de
utilitarios funcionales sin la extensión de cualquier objeto incorporado en el lengua-
je [39].
Caracterı́stica Descripción
Colecciones Underscore provee algunos métodos los cuales ope-
ran sobre colecciones.
Arreglos Underscore provee algunas funciones las cuales tra-
bajan exclusivamente sobre arerglos.
Objetos Underscore provee varios métodos para clonar obje-
tos, para extenderlos y manipular objetos.
Funciones Underscore provee funciones las cuales trabajan so-
bre funciones, este permite construir funciones de or-
den superior.
Tabla 1.16: Caracterı́sticas de Underscore.js
El ejemplo de código 1.28 a continuación ha sido tomado de la página oficial:
49
1 .map( [ 1 , 2 , 3 ] , f u n c t i o n (num) { return num ∗ 3; } ) ;
2 / / => [ 3 , 6 , 9 ]
3
4 .map({one : 1 , two : 2 , th ree : 3} , f u n c t i o n (num, key ) {
5 return num ∗ 3;
6 } ) ;
7 / / => [ 3 , 6 , 9 ]
8
9 .map ( [ [ 1 , 2 ] , [ 3 , 4 ] ] , . f i r s t ) ;
10 / / => [ 1 , 3 ]
Fragmento de Código 1.28: Ejemplo de Underscore.js
CAPÍTULO 2. DESARROLLO DE LA LIBRERÍA UTILI-
TARIA FUNCIONAL
Descripción del Problema
La naturaleza del software es evolutiva, se debe ajustar a las necesidades definidas
por los usuarios. Dichos ajustes deben ser realizado con frecuencia, el esfuerzo
involucrado se encuentra directamente relacionado al diseño del software.
Un sistema altamente acoplado es difı́cil de mantener, cualquier cambio realizado
causarı́a una serie de modificaciones en cadena, incrementando la posibilidad de
introducir nuevos errores o defectos en el sistema.
Dentro de sistemas distribuidos, el manejo de la concurrencia resulta un desafı́o. El
cambio constante de estado dentro de la programación orientada a objetos, puede
causar algunas problemas dentro de la concurrencia como: deadlocks y condiciones
de carrera [34].
La mayorı́a de lenguajes orientados a objetos como Java, poseen mecanismos para
el manejo de la concurrencia, sin embargo es el desarrollador quien es responsable
de emplear dichos mecanismos durante el desarrollo.
El presente proyecto se enfocará en dos problemas puntuales, la escalabilidad cau-
sada por sistemas altamente acoplados, y la concurrencia causada por el uso de
objetos mutables.
Descripción de la Solución
El presente capı́tulo, describe el análisis, diseño, desarrollo y pruebas de la librerı́a
50
51
funcional construida sobre el lenguaje orientado a objetos Java. Dentro de las sec-
ciones a continuación se describe tanto las limitaciones dellenguaje Java sobre
Haskell, ası́ como algunas de las técnicas empleadas durante el desarrollo para
superar algunas de estás limitaciones.
Algunos de los objetivos claves del presente capı́tulo son:
Identificar los módulos de Haskell a ser importados.
Identificar las limitaciones encontradas al tratar de importar ciertos módulos a
Java.
Describir las convenciones tanto de documentación, como de estructura de
código de la librerı́a.
Describir las técnicas empleadas para superar algunas de las limitaciones en-
contradas en Java.
Describir el proceso de pruebas utilizado durante el desarrollo de la librerı́a.
Metodologı́a de Desarrollo
Para el desarrollo de la librerı́a funcional se ha seleccionado Scrum como metodo-
logı́a. La naturaleza iterativa e incremental de Scrum sigue la misma filosofı́a del
desarrollo guiado por pruebas, lo cual hace que se integren bien durante las dife-
rentes fases del desarrollo.
La tabla 2.1 a continuación, lista las historias de usuario dentro del Product Backlog
del proyecto:
52
Fase Historia de Usuario Prioridad Estimación Estado
Análisis Como un usuario de la librerı́a,
yo quiero que la librerı́a sea
compatible con diferentes ver-
siones de Java, para que no
existan conflictos en mis proyec-
tos durante la actualización de
versiones del lenguaje.
1 8 Hecho
Diseño Como un usuario de la librerı́a,
yo quiero tener acceso a la do-
cumentación, para tener una re-
ferencia del modo de uso de los
métodos y clases definidos den-
tro de la librerı́a.
2 8 Hecho
Diseño Como un contribuidor de la li-
brerı́a, yo quiero tener acceso al
código fuente, para poder reali-
zar contribuciones al proyecto.
3 3 Hecho
Desarrollo Como un contribuidor de la li-
brerı́a, yo quiero que el proyec-
to utilice un servicio de integra-
ción continua, para poder detec-
tar defectos y errores introduci-
dos por cambios de una manera
temprana.
4 5 Hecho
53
Fase Historia de Usuario Prioridad Estimación Estado
Pruebas Como un usuario de la librerı́a,
yo quiero utilizar un producto de
software con un alto nivel de co-
bertura de pruebas, para que el
uso de la librerı́a no introduzca
errores o defectos dentro de mis
sistemas.
5 8 Hecho
Tabla 2.1: Product Backlog
Las historias de usuario presentadas en el Product Backlog fueron desarrolladas a
lo largo de 3 Sprints, los cuales se describe a continuación:
Historia de Usuario Estimación Tareas
Como un usuario de la librerı́a,
yo quiero que la librerı́a sea
compatible con diferentes ver-
siones de Java, para que no
existan conflictos en mis proyec-
tos durante la actualización de
versiones del lenguaje.
8 Evaluar las versiones de Java
más utilizadas en la industrı́a.
Identificar las limitaciones del
lenguaje Java comparado con
Haskell.
Analizar la portabilidad de los
módulos de Haskell a Java.
Como un usuario de la librerı́a,
yo quiero tener acceso a la do-
cumentación, para tener una re-
ferencia del modo de uso de los
métodos y clases definidos den-
tro de la librerı́a.
5 Documentar el código fuente.
Generar la documentación.
Subir la documentación a un re-
positorio público.
Tabla 2.2: Sprint #1 - Spring Backlog
54
Historia de Usuario Estimación Tareas
Como un contribuidor de la li-
brerı́a, yo quiero tener acceso al
código fuente, para poder reali-
zar contribuciones al proyecto.
3 Instalar y configurar un sistema
de versionamiento.
Subir el código fuente a un repo-
sitorio en la nube.
Como un contribuidor de la li-
brerı́a, yo quiero que el proyec-
to utilice un servicio de integra-
ción continua, para poder detec-
tar defectos y errores introduci-
dos por cambios de una manera
temprana.
5 Ejecutar las pruebas como parte
del proceso de integración con-
tinua.
Ejecutar las pruebas utilizando
diferentes versiones de la JVM.
Generar la documentación co-
mo parte de la integración con-
tinua.
Tabla 2.3: Sprint #2 - Spring Backlog
Historia de Usuario Estimación Tareas
Como un usuario de la librerı́a,
yo quiero utilizar un producto de
software con un alto nivel de co-
bertura de pruebas, para que el
uso de la librerı́a no introduzca
errores o defectos dentro de mis
sistemas.
8 Instalar y configurar JUnit en el
proyecto.
Configurar la librerı́a PiTest para
la ejecucción de pruebas de mu-
tación.
Automatizar la ejecucción de
pruebas.
Generar el reporte de pruebas
como parte de la integración
continua.
Tabla 2.4: Sprint #3 - Spring Backlog
Finalmente la figura a continuación 2.1, muestra el progreso realizado a lo largo de
55
todo el desarrollo del proyecto:
Figura 2.1: Release Burndown
2.1 ANÁLISIS
Antes de proceder con el diseño de la librerı́a funcional, se debe evaluar cada uno
de los módulos escritos en Haskell, con el fin de analizar su portabilidad a Java.
Adicionalmente se tomarán en cuenta las siguientes consideraciones:
Compatibilidad con versiones anteriores de Java Development Kit (JDK).
Limitaciones del lenguaje de programación Java.
2.1.1 RETROCOMPATIBILIDAD
Uno de los principales objetivos del presente proyecto, es extender el uso de la
librerı́a desarrollada, para lo cual se evaluará el porcentaje de uso de las diferentes
versiones de Java.
La figura 2.2 a continuación muestra el uso de las diferentes versiones de Java en
la actualidad:
56
0.1 %
29 %
70 %
0.9 %
JDK 8
JDK 7
JDK 6
JDK 5
Figura 2.2: Uso de las Versiones de JDK
Fuente: https://plumbr.eu/blog/java/most-popular-java-environments
Como se puede observar en la figura 2.2, a pesar de existir hoy en dı́a nuevas
versiones de Java las cuales introducen algunas caracterı́sticas de la programación
funcional, todavı́a existe un alto porcentaje de uso de la versión 6 de Java.
La librerı́a desarrollada será compatible con las siguientes versiones de Java:
Java 6
Java 7
Java 8
Cualquier análisis realizado en las secciones a continuación, tomará en cuenta que
la librerı́a debe ser compatible con versiones anteriores de Java a partir de la versión
6.
2.1.2 LIMITACIONES DEL LENGUAJE DE PROGRAMACIÓN JAVA
Al comparar dos lenguajes de programación, pueden existir ventajas y desventa-
jas de un lenguaje sobre otro, sin embargo debido a que se procederá a importar
57
módulos escritos en Haskell a Java, la presente sección se enfocará en describir
las limitaciones de Java sobre Haskell las cuales serán consideradas en la fase de
diseño 2.2 más adelante.
Efectos Secundarios
En Java no existe restricción para limitar efectos secundarios en un método a dife-
rencia de Haskell, en donde una función debe especificar explı́citamente la presen-
cia de efectos secundarios.
1 printMessage : : String −> IO ( )
2 printMessage m = putStrLn m
Fragmento de Código 2.1: Efecto Secundario Explı́cito
1 public void printMessage ( S t r i n g message ) {
2 System . out . p r i n t l n ( message ) ;
3 }
Fragmento de Código 2.2: Efecto Secundario Implı́cito
Como se puede observar en el fragmento de código 2.2, no existe ningún indicio
en la firma del método printMessage de que tenga algún efecto secundario, a dife-
rencia del fragmento de código 2.1 en donde el tipo del retorno de la función IO ()
indica que la función printMessage tiene algún efecto sobre la entrada y salida de
información.
Evaluación Perezosa
Haskell es perezoso por defecto, es decir, no evalúa una expresión hasta que sea
necesario, a continuación un ejemplo:
58
1 > take 3 [ 1 . . ]
2 [ 1 , 2 , 3 ]
Fragmento de Código 2.3: Evaluación Perezosa - Haskell
Como se puede observar en el fragmento de código 2.3, la función take toma co-
mo argumento una lista infinita [1..] , sin embargo para mostrar el resultado en la
pantalla, Haskell solo evaluará los 3 primeros elementos de la lista.
Analizando el mismo ejemplo en Java, dado que el proceso de evaluación del len-
guaje es estricto, evaluar una lista infinita resultarı́a en un error de memoria, como
se puede observar