Índice de contenidos
- 1. Introducción
- 2. Entorno
- 3. Instalación de Clojure con Leiningen
- 4. Ejecutando los tests de Clojure
- 5. Tests más legibles con Midje
- 6. Conclusiones
- 7. Sobre el autor
1. Introducción
Clojure es un lenguaje funcional dinámico que corre en la JVM (Máquina Virtual de Java). Podemos destacar las siguientes características:
- Al ser un lenguaje funcional potencia al idea de inmutabilidad, de forma que todos los valores son constantes (no existe el concepto de variable).
- Derivado de lo anterior se potencia el multi-hilo ya que al trabajar con constantes se minimizan los conflictos de la concurrencia. De hecho Clojure está pensado desde su inicio para sacarle el mayor partido al procesamiento multi-core.
- Al correr en la JVM, se saca toda la potencia de esta máquina virtual.
- Al correr en la JVM se puede aprovechar todo el ecosistema/librerías que existe de Java, siendo muy fácil llamar de Clojure a Java o viceversa.
Todas estas características y muchas más (recomiendo echar un vistazo a su página oficial) hacen de este lenguaje una opción sería a la hora de hacer nuestros desarrollos.
En este tutorial vamos a ver como dar los primeros pasos para empezar a escribir tests y código de producción.
2. Entorno
El tutorial está escrito usando el siguiente entorno:
- Hardware: Portátil MacBook Pro 15’’ (2.3 GHz Intel i7, 16GB 1600 Mhz DDR3, 500GB Flash Storage).
- NVIDIA GeForce G7 750M
- Sistema Operativo: Mac OS X Lion 10.9.4
- Clojure 1.6.0
- Leiningen 2.4.3
- Midje 1.6.3
- JVM 1.8.0_11
3. Instalación de Clojure con Leiningen
Leiningen es la herramienta que nos va a permitir gestionar el ciclo de compilación, dependencias, ejecución de los test, empaquetado, … Sería como el Maven o Gradle de Java, o el Grunt de JavaScript.
Otra característica que tiene Leiningen es que nos permite gestionar la versión de Clojure que estamos usando en el proyecto, encargándose él mismo de descargarla e instalarla si es necesario (como Clojure es una app Java, la descarga de los repositorios de Maven y la guardará en nuestro ~/.m2/repository
)
3.1. Instalación de Leiningen
Para instalar Leiningen es tan sencillo como hacer:
- Descargar el script lein
- Colocarlo en en el $PATH para que lo podamos ejecutar desde la línea de comando (ej.
/usr/local/bin
) - Hacerlo ejecutable (
chmod a+x /usr/local/bin/lein
) - Ejecutarlo (
lein
) y en este primera ejecución se descargará e instalará a si mismo
3.2. Creación de un proyecto
Lein tiene plantillas de proyectos al estilo de los arquetipos de Maven. Para crear un proyecto de tipo aplicación, es decir que será ejecutable por si mismo, basta con ejecutar en la línea de comando:
$ lein new app mis-cositas
Donde:
new
– es el comando lein que queremos ejecutar.app
– es el nombre de la plantilla. Si lo omitimos usará la plantilla por defecto que es para crear una librería (un .jar).mis-cositas
– es el nombre que le quiero dar a mi aplicación.
Esto debería haber generado la siguiente estructura:
mis-cositas/ .gitignore /doc intro.md LICENSE project.clj README.md /resources /src /mis_cositas core.clj /test /mis_cositas core_test.clj
Donde podemos destacar
- el fichero
project.clj
– que es el que gestiona la compilación (como elpom.xml
de Maven), - el fichero
core.clj
– donde podemos empezar a desarrollar nuestra lógica de negocio, - el fichero
core_test.clj
– donde podemos empezar a escribir nuestros tests.
3.3. Inspeccionando el fichero de proyecto: project.clj
Lo primero que puede llamar la atención de este fichero es que es un fichero de Clojure como otro cualquiera.
(defproject mis-cositas "0.1.0-SNAPSHOT" :description "FIXME: write description" :url "http://example.com/FIXME" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} :dependencies [[org.clojure/clojure "1.6.0"]] :main ^:skip-aot mis-cositas.core :target-path "target/%s" :profiles {:uberjar {:aot :all}})
Por ahora sólo destacaremos la línea 6 donde se especifican las dependencias, y vemos como la única que hay ahora mismo es la propia versión de Clojure que queremos usar. Una ventaja de esto es que resulta muy sencillo tener distintos proyectos con distintas versiones de Clojure, ya que sólo habrá que indicar la que nos interesa en el fichero de proyecto, sin necesidad de hacer ninguna instalación previa.
4. Ejecutando los tests de Clojure
Clojure ya viene con una sintaxis de tests, y vimos como lein
nos había generado uno de prueba. Para ejecutarlo basta con hacer:
lein test
Deberíamos ver algo como:
El tests a fallado, esto es lo normal cuando el test ha sido generado por una plantilla. Vamos a echar un ojo al código del test:
(ns mis-cositas.core-test (:require [clojure.test :refer :all] [mis-cositas.core :refer :all])) (deftest a-test (testing "FIXME, I fail." (is (= 0 1))))
Vemos como importa el código de producción en la línea 2 con el require
y luego como define un test donde compara si el 0 y el 1 son iguales (=
).
Para ver que más aserciones podemos hacer recomiendo visitar la documentación oficial del API de testing de Clojure
5. Tests más legibles con Midje
El sistema de tests que viene con Clojure sirve más que de sobra para probar cualquier cosa, pero se queda más bien escaso en cuanto a legibilidad. Además para lanzarlos tenemos que invocar o lein
o el REPL, con lo que puede ser un poco incómodo.
Para solventar estos dos problemas le podemos dar las gracias a @marik, el creador de Midje, un estupendo framework de test para Clojure, de forma que sea más sencilla la tarea de escribir los tests. Además soporta tanto el desarrollo de arriba-a-bajo, como de abajo-a-arriba.
La idea de Midje es que estos tests queden como si fuera la documentación de nuestro proyecto.
5.1. Instalación de Midje
Para poder empezar a usar Midje tenemos que hacer dos sencillas cosas. La primera a nivel global nos permitirá integrar Midje dentro del ciclo de vida de Lein, de forma que encontremos el comando midje
dentro de la herramienta lein
(ya antes hemos visto otros comandos como new
o test
).
Para ello tenemos que añadir la siguiente línea al fichero ~/.lein/profiles
(si no existe todavía lo creamos):
{:user {:plugins [[lein-midje "3.1.3"]]}}
Como segundo paso tenemos que indicar a nuestro proyecto que queremos usar Midje, para ello modificamos el fichero project.clj que hemos visto antes, para que quede de la siguiente manera:
(defproject mis-cositas "0.1.0-SNAPSHOT" :description "FIXME: write description" :url "http://example.com/FIXME" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} :dependencies [[org.clojure/clojure "1.6.0"]] :main ^:skip-aot mis-cositas.core :target-path "target/%s" :profiles {:dev {:dependencies [[midje "1.6.3"]]} :uberjar {:aot :all}})
Nótese que sólo hemos cambiado las líneas 9 y 10, para añadir la dependencia de midje sólo en el profile
de desarrollo (:dev
). Así esta dependencia no se “arrastrará” cuando preparemos el ejecutable de la aplicación.
Ahora deberíamos poder ejecutar en la línea de comando:
$ lein midje
y veremos un resultado del estilo:
En la imagen podemos ver como Midje también ejecuta los test de Clojure que tengamos en el proyecto, y además colorea la salida para facilitar su lectura. ¡Sólo con eso ya es todo un acierto!
5.2. Escribiendo un test de Midje
Vamos a añadir el fichero test/mis_cositas/core_midje_test.clj
, con el siguiente contenido:
(ns mis-cositas.core-midje-test (:use midje.sweet) (:require [clojure.string :as str] [mis-cositas.core :refer :all])) (fact "`split` splits strings on regular expressions and returns a vector" (str/split "a/b/c" #"/") => ["a" "b" "c"] (str/split "" #"irrelevant") => [""] (str/split "no regexp matches" #"a+\s+[ab]") => ["no regexp matches"])
Se aprecia en el código que en al izquierda de la flecha =>
está la expresión que queremos probar, y a la derecha el valor del assert que debe ser el resultado.
Esto no es más que un pequeño ejemplo, e igual que antes recomiendo visitar la documentación de Midje.
5.3. Hágase la magia: ejecución automática de los tests
Si hemos ejecutado un par de veces los tests, habremos visto que tarda en arrancar. Esto se debe a que Clojure se ejecuta en la JVM, así que para ejecutar cualquier cosa tiene que levantarla, y esto no es rápido.
Evidentemente esto no se puede quedar así porque sino el desarrollo sería imposible con esos tiempos de espera. Podemos paliarlo abriendo un REPL (esto carga una sola JVM que mantenemos mientras dure la sesión) y ejecutando los tests desde aquí, pero esto es más bien incómodo porque hay que forzar el refresco de los fuentes que cambien, así que tampoco es muy viable.
La mejor opción es ejecutar:
$ lein midje :autotest
Esto hace que al consola se quede “escuchando” cualquier cambio en los ficheros, y en cuanto esto sucede, Midje se encarga de refrescar los fuentes y ejecutar los tests. Todo en un abrir y cerrar de ojos. Así, sí!
6. Conclusiones
Clojure es un lenguaje muy potente, con unas características más que interesantes. De hecho muchos piensan que es el lenguaje del futuro. Yo no se si esto será cierto, pero si creo que es muy interesante aprenderlo sobre todo para todos aquellos como yo que estamos acostumbrados al paradigma de la Orientación a Objetos, cambiar al paradigma funcional nos fuerza a ver las cosas de otra manera y siempre se pueden aplicar buenas ideas de uno a otro (como lo de intentar que todo sea inmutable).
Espero que con este tutorial la barrera de entrada para montar el entorno sea mínima y podáis centraros en aprender el lenguaje, que es lo importante.
Si me preguntáis por editor, la verdad es que por ahora estoy usando simplemente Vim con el plugin Vim Clojure Static. Si alguien conoce algo mejor que me lo diga 😉
7. Sobre el autor
Alejandro Pérez García, Ingeniero en Informática (especialidad de Ingeniería del Software) y Certified ScrumMaster
Socio fundador de Autentia (Desarrollo de software, Consultoría, Formación)
mailto:alejandropg@autentia.com
Autentia Real Business Solutions S.L. – “Soporte a Desarrollo”