Primeros pasos con Clojure: Leiningen y Midje

0
10226

Índice de contenidos

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:

  1. Descargar el script lein
  2. Colocarlo en en el $PATH para que lo podamos ejecutar desde la línea de comando (ej. /usr/local/bin)
  3. Hacerlo ejecutable (chmod a+x /usr/local/bin/lein)
  4. 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 el pom.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:

Ejecutar tests de Clojure con Lein
Ejecutar tests de Clojure con Lein

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:

Ejecutar tests de Midje con Lein
Ejecutar tests de Midje con Lein

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”

http://www.autentia.com

Alejandro es socio fundador de Autentia y nuestro experto en Java EE, Linux y optimización de aplicaciones empresariales. Ingeniero en Informática y Certified ScrumMaster. Seguir @alejandropgarci Si te gusta lo que ves, puedes contratarle para darte ayuda con soporte experto, impartir cursos presenciales en tu empresa o para que realicemos tus proyectos como factoría (Madrid). Puedes encontrarme en Autentia: Ofrecemos servicios de soporte a desarrollo, factoría y formación.

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad