Archivo de la categoría: JavaScript

Mocks… o el TDD y yo

… segunda Parte de TDD is dead? … o yo y el TDD

[Mock y test]Este es el segundo y último artículo de la serie que completa el anterior post TDD is dead? … o yo y el TDD.

Trataré de explicar como defino y codifico mis propios objetos ‘mock‘, y de como los uso tanto para pruebas unitarias, como también en pruebas de integración entre clases.

Y siendo más especifico mostrar como se pueden codificar tres tipos de mock utilizados habitualmente:

  •  Simular la capa de persistencia a base de datos.
  •  El que se utiliza para comprobar que se ha llamado a la interfaz que representa desde el objeto que nos interesa probar.
  • El utilizado simplemente para poder pasar las pruebas y que no nos interesa su comportamiento.

Y como dijo el maestro:

“… hablar es barato, vamos a ver un poco de código…”

Demo

Para ilustrar el ejemplo utilizaré una aplicación web que mediante un formulario html sencillo llamará con ajax a un servicio REST. Consiste en dar de alta códigos de promoción de una web.

[Pantallazo de la Demo Ejemplo Mock]

[Pantallado de la demo]

Los datos que se piden son la promoción, el nombre, el correo electrónico y el código de promoción. Se validará que el correo electrónico no esté ya utilizado y si todo es correcto se enviará el correo a la persona y se mostrarán los datos de los códigos ya dados de alta.

La demo es completamente operativa y se puede usar. Se puede descargar el código aquí:

[Logo GitHub]MoksExample en GitHub

Los detalles de como funciona y como se puede probar están en el archivo README.md

La parte de servicios REST es Java, montada sobre Spring. En el ecosistema de Spring, Spring-Data es el mediador con la capa de persistencia de datos. En el ejemplo se usará como interfaz con la base de datos. Como framework de tests unitarios usaré Junit. Maven será la herramienta de compilación, ejecución de test y construcción del proyecto. Como es una demo para estos fines se usa Hsqldb, base de datos en memoria.

Simular la capa de persistencia de BBDD

En la demo existen dos entidades PROMOTION y PROMOTION_CODE. La primera es el maestro de promociones y en la segunda se almacenarán todos los códigos de promoción relacionados con las primeras. Los objetos de negocio que las definen son los beans: Promotion y PromotionCode

Spring-Data se basa en el patrón repositorio. A grandes rasgos y simplificando, Spring-Data implementa la interfaz de las operaciones CRUD y el resto de consultas que se pueden realizar para cada entidad de la capa de persistencia (usualmente una tabla de una base de datos).

Existen por tanto dos interfaces definidos en el pakage com.logicaalternativa.ejemplomock.repository cuya misión es definir las operaciones CRUD de las entidades

En este caso los dos extienden del interfaz de Spring-Data JpaRepository.

Con Spring-Data sólo tienes que definir la interfaz con las diferentes operaciones de consulta, inserción y modificación que se van a realizar de la entidad y este se encarga de implementar la interfaz. Esto hace que resulte muy fácil codificar tus propios mocks. Después para los test se inyectarán por inversión de control al objeto de negocio.

Para los test he implementado los dos mock de cada uno de los interfaces. Están en el package com.logicaalternativa.ejemplomock.repository.mock .

Las dos clases son muy similares y siguen la misma línea. Sólo se ha implementado las operaciones necesarias para realizar los test. La idea es esa codificar sólo lo estrictamente necesario. Se añadirá o se modificará código cuando toque, si para un futuro test es necesario implementar algún otro método más.

Centrándome por ejemplo en el mock PromotionCodeRepositoryMock, el ‘quid de la cuestión‘ está en que he definido un atributo lista de tipo PromotionCode.

1
public class PromotionCodeRepositoryMock implements PromotionCodeRepository {
2
   private List<PromotionCode> promotionCode;
3
...
4
}

Este es accesible mediante los métodos públicos:

1
public class PromotionCodeRepositoryMock implements PromotionCodeRepository {
2
...
3
   public List<PromotionCode> getPromotionCode()
4
...
5
   public void setPromotionCode(PromotionCode...promotionCode)
6
...
7
}

He codificado los métodos CRUD para que operen con esta lista. Por ejemplo, así he codificado el método que sirve para obtener un código de promoción a través de su clave primaria.

01
public class PromotionCodeRepositoryMock implements PromotionCodeRepository {
02
...
03
  public PromotionCode findOne( final String email ) {		
04
    int index = findIndex( email );		
05
    if ( index != -1 ) {
06
      return clone( getPromotionCode().get( index ) ); 
07
    }	
08
    return null;
09
  }
10
...
11
}

Que lo que hace es encontrar el índice de la lista de códigos de promoción con el mismo email. Si lo encuentra devuelve una copia de ese objeto. Para entrar más en detalle te invito a revisar los métodos findIndex, clone y el resto de métodos que he implementado de PromotionCodeRepositoryMock

Otro ejemplo es el método saveAndFlush:

01
public class PromotionCodeRepositoryMock implements PromotionCodeRepository {
02
...
03
  public <S extends PromotionCode> S saveAndFlush(S promotionCode ) {
04
    if ( getPromotionCode() == null ) {
05
     this.promotionCode = new ArrayList<PromotionCode>();
06
     getPromotionCode().add( promotionCode );
07
     return promotionCode ;
08
    }
09
    final String email = promotionCode != null ? promotionCode.getEmail() : null;
10
    int index = findIndex( email ) ; 
11
    if ( index == -1 ) {
12
     getPromotionCode().add( promotionCode );
13
    } else {
14
     getPromotionCode().set( index, promotionCode );
15
    }
16
    return promotionCode;
17
  }
18
...
19
}

Que busca en la lista el objeto con el mismo email. Si lo encuentra actualiza el objeto de la lista y sino, lo añade a la lista.

¿Cómo se usa?

El test AddCodeBusinessImpTest prueba el objeto de negocio AddCodeBusinessImp.

La clase de negocio (AddCodeBusinessImp) comprueba que existe el código de promoción en la BBDD y utiliza para ello PromotionRepository. En el método setUp() del test se inicializa un objeto PromotionRepositoryMock con el objeto Promotion deseado y este mock se inserta por inversión de control a la instancia de AddCodeBussinessImp.

01
public class AddCodeBusinessImpTest {
02
  ...
03
  private AddCodeBusinessImp addCodeBusinessImp;
04
  ...
05
  private PromotionRepositoryMock promotionRepositoryMock;
06
  private PromotionCodeRepositoryMock promotionCodeRepositoryMock;	
07
  private Promotion promotion;
08
  ...
09
  @Before
10
  public void setUp() throws Exception {
11
    promotion = new Promotion();
12
    promotion.setIdPromotion( 1 );
13
    ...    
14
    promotionRepositoryMock = new PromotionRepositoryMock();
15
    promotionRepositoryMock.setPromotions( promotion );
16
    ...  
17
    addCodeBusinessImp = new AddCodeBusinessImp();
18
    addCodeBusinessImp.setPromotionRepository( promotionRepositoryMock );
19
    ...
20
  }
21
  ...
22
}

promotion, promotionRepositoryMock, addCodeBusinessImp son atributos privados de AddCodeBusinessImpTest.

Internamente AddCodeBusinessImp llama al método findOne de PromotionRepository con el identificador de la promoción (el del maestro de promociones) del nuevo código que se quiere insertar.

Si queremos testear que ocurre si no encuentra la promoción en la BBDD, simplemente se hace lo que en el método testPromotionNotBbDd de AddCodeBusinessImpTest:

01
public class AddCodeBusinessImpTest {
02
  ...
03
  @Test
04
  public void testPromotionNotBbDd() {
05
    try {
06
      promotionRepositoryMock.setPromotions( ( Promotion[] ) null ); 
07
      addCodeBusinessImp.validateAndAdd( promotionCode );
08
      ...
09
  }
10
  ...
11
}

Si la lista de promociones en PromotionRepositoryMock es nula no se podrá encontrar la promoción (El método findOne devolverá nulo).

En este mismo test también se utiliza PromotionCodeRepositoryMock. Inyectado también por inversión de control a la instancia de AddCodeBusinessImp, en este caso, sirve para comprobar que se ha insertado el código de promoción. Se hace en el test testOk

01
public class AddCodeBusinessImpTest {
02
  ...
03
  @Test
04
  public void testOk() {
05
    try {
06
      addCodeBusinessImp.validateAndAdd( promotionCode );
07
      final List<PromotionCode> promotionCodeBbDCodes = promotionCodeRepositoryMock.getPromotionCode();
08
      boolean result = promotionCodeBbDCodes != null
09
                && promotionCodeBbDCodes.size() == 1
10
                && promotionCode.equals( promotionCodeBbDCodes.get( 0 ) )
11
               ;
12
      ...
13
  }
14
  ...
15
}

Para tener una visión más clara de cual es la idea, lo mejor es revisar cada uno de los test Junit de AddCodeBusinessImpTest Creo que puede ser de gran ayuda para tener una visión global de lo que quiero plantear . He intentado que sean claros y autoexplicativos.

Mock de comprobación de llamada a interfaz y datos correctos.

Lo que interesa en este caso es comprobar que un objeto de negocio hace la llamada a un interfaz con los datos correctos. Lo que se hace es ‘mockear‘ esa interfaz capturando los datos de la llamada para comprobar después de que estos son correctos.

En la demo existe un objeto de negocio, SendMailCodePromotionImp, que a partir de una dirección de correo manda el código de promoción por email. Este objeto de negocio realiza internamente una llamada a la interfaz JavaMailSender que implementa Spring (JavaMailSenderImpl) para enviar el correo electrónico.

JavaMailServerMock, que implementa también el interfaz JavaMailServer, es el mock que va a recoger los datos de la llamada. En este caso sólo me interesaba saber la dirección de correo a la que se envía el correo electrónico. Para ello he implementado el método send:

01
public class JavaMailServerMock implements JavaMailSender {
02
  ...
03
  private String sendTo;
04
  ...
05
  @Override
06
  public void send( MimeMessage mimeMessage ) throws MailException {
07
    String[] to = null;
08
    try {
09
      to = mimeMessage.getHeader("To");
10
    } catch (MessagingException e) {
11
      logger.error( "[send] ".concat( e.getMessage() ), e );  
12
      to = null;      
13
    }
14
    setSendTo( to != null && to.length > 0 ? to[0] : null );
15
  }
16
  ...
17
  public String getSendTo() {
18
    return sendTo;
19
  }
20
  public void setSendTo(String sendTo) {
21
    this.sendTo = sendTo;
22
  }
23
}

Se recoge del argumento de entrada la cabecera “To” para almacenarla en un atributo de la clase.

¿Cómo se usa?

En el test SendMailCodePromotionImpTest se utiliza este Mock. En el método setUp(), se instancia y se inserta por inversión de control al objeto SendMailCodePromotionImp.

01
public class SendMailCodePromotionImpTest {
02
  ...
03
  private SendMailCodePromotionImp sendMailCodePromotionImp;
04
  ...
05
  private JavaMailServerMock javaMailServerMock;
06
  ...
07
  @Before
08
  public void setUp() throws Exception {
09
    ...
10
    javaMailServerMock = new JavaMailServerMock();
11
    ...    
12
    sendMailCodePromotionImp = new SendMailCodePromotionImp();
13
    ...
14
    sendMailCodePromotionImp.setJavaMailSender( javaMailServerMock );
15
    ...
16
  }
17
  ...
18
}

El test testOk de SendMailCodePromotionImpTest sirve como ejemplo para comprobar si se ha realizado correctamente la llamada:

01
public class SendMailCodePromotionImpTest {
02
  ...
03
  public void testOk() {
04
    try {
05
      sendMailCodePromotionImp.sendMailCodePromotion( email, locale );
06
      final String sendTo = javaMailServerMock.getSendTo();
07
      boolean res = sendTo != null
08
              && sendTo.equals( nameUser.toUpperCase() + " <" + email +">"  );
09
    ...
10
  }
11
  ...
12
}

Donde después de hacer la llamada al método sendMailCodePromotion del objeto de negocio se obtiene el atributo de sendTo del mock para comprobar que se envía a la misma dirección de correo electrónico.

En este mock sólo se comprueba la cabecera ‘To‘. También se podría comprobar el texto del mensaje o cualquier otro dato enviado desde el objeto de negocio.

Mock para pasar las pruebas

En la demo he codificado MessageSourceMock que implementa el interfaz MessageSource, utilidad que tiene Spring para la internacionalización. Este mock sólo me interesa para poder probar otras funcionalidades. Ha sido necesario codificado porque el objeto de negocio lo necesitaba, pero, en este caso, el resultado de su llamada era irrelevante. Solamente se ha codificado el método getMessage :

1
public class MessageSourceMock implements MessageSource {
2
  ...
3
  @Test
4
  public String getMessage(String arg0, Object[] arg1, Locale arg2) throws NoSuchMessageException {
5
    return arg0;
6
  }
7
  ...
8
}

Que como puedes comprobar, devuelve directamente la entrada.

¿Cómo se usa?

En el test SendMailCodePromotionImpTest se utiliza este Mock. En el método setUp()Se instancia y se inserta por inversión de control al objeto
SendMailCodePromotionImp.

01
public class SendMailCodePromotionImpTest {
02
  ...
03
  private SendMailCodePromotionImp sendMailCodePromotionImp;
04
  ...
05
  private MessageSourceMock messageSourceMock;
06
  ...
07
    @Before
08
  public void setUp() throws Exception {
09
    ...
10
    messageSourceMock = new MessageSourceMock();
11
    sendMailCodePromotionImp = new SendMailCodePromotionImp();
12
    ...
13
    sendMailCodePromotionImp.setMessageSource( messageSourceMock );
14
  }
15
  ...
16
}

Ya ahora al hacer la llamada getSendTo del objeto de negocio no aparece la tan temida NullPointerException 😉

Conclusiones

Como se puede ver, con un poco de ingenio es relativamente sencillo crearte tus propios objetos mock sin tener que recurrir a Frameworks. La creación de los mock me ayudan a comprender mejor como funciona la aplicación y ver las clases involucradas como verdaderas cajas negras. Esta es la gracia del paradigma de la orientación a objetos.

No necesariamente tiene que llevar demasiado tiempo el codificarlos. Sólo se debería ‘picar’ lo que necesitas cuando lo necesitas y mucho es reaprobechable. Al final del proyecto seguro que tienes un buen juego de objetos mock para pruebas.

Otra ventaja, es que no hay reflexión, no existe bbdd en memoria para los test, ni ha sido necesario levantar un entorno para pruebas… el resultado es que los test van ‘volaos‘.

M.E.

P.D.: Para esta demo, de esto que te vas liando y liando… y poco a poco me ‘currado’ un framework MVC hecho en JavaScript. Cuando lo organice un poco será material para próximos post.

Aprendiendo Grunt a partir de Ant

Prólogo

Hace unos años, unos 8 ya …

[Grunt logo]En un proyecto me tocó realizar una ‘builtool‘. Era una herramienta común que utilizarían todos los demás proyectos no importando su tecnología, PHP,.Net, Java, etc. Obtenía el código del sistema de control de versiones compilaba, paquetizaba y subía la build compilada a otra rama del control de versiones. En realidad era un pre-Maven porque obligaba a una cierta estructura de directorios en los proyectos pero no tenía ni su control de dependencias, ni sus arquetipos para nuevos proyectos. La herramienta estaba hecha en Ant.

Realmente nunca me llegó a apasionar ese proyecto, siempre me ha gustado más programar. Pero me ayudó a tener conciencia de la importancia de saber montar el ‘Control de la configuración‘ de un proyecto y también, como podéis imaginar, a tener bastante soltura con Ant.

Capitulo I

… en la actualidad

Para el Front del nuevo proyecto, con mucha carga de JavaScript, teníamos que generar la build  y realizar el despliegue. Para hacer menos pesada y más rápida la descarga necesitamos comprimir html, jasvascript y css y en el caso de estos dos últimos unificarlos en un sólo fichero.  Este proceso también lo  utilizaríamos para hacer despliegue continuo en nuestro entorno de preproducción, utilizando Jenkins.

Grunt se ajustaba perfectamente a nuestras necesidades y además se unificaba las tecnologías. La elección de Grunt en vez de Gulp, otra herramienta similar, fue porque el primero está incluido en Yeoman, que viene a ser en Javascript lo que Maven es a Java. Una herramienta de gestión de dependencias, arquetipos, generación de buidls, test, etc.., que al igual que Maven permite gestionar todo el ciclo de vida de las builds. Elegí Grunt como un primer paso del camino que muy probablemente nos lleve a Yeoman.

Me enfrente al reto aprendiendo algo nuevo desde la perspectiva de algo conocido. Utilizando como punto de apoyo, sin que lo conocido conllevara  a perjuicios iniciales. Estas son las semejanzas, las diferencias y las conclusiones a las que he llegado.

En que se parecen…

Ant tiene ya mucho recorrido, o dicho de otra manera ya es bastante ‘viejuno‘. En cierta forma fue la respuesta de Java al Make de C. Surgió de la necesidad de crear una herramienta que pudiera compilar, generar ejecutables y que no dependiera del sistema operativo donde se ejecutara. Permite también la generación de test, despliegue, generación de documentación, etc.

Grunt está dentro del ecosistema Javascript, es un ‘ejecutor de tareas‘ y se usa fundamentalmente para realización de builds, su testeo y su despliegue.

Arquitectura y configuración

Para utilizar Ant es necesario primero tener instalado Java y después la distribución de Ant. Algo similar ocurre con Grunt para poder usarlo es requisito tener instalado node.js y el cliente de Grunt.

Tanto en Ant como en Grunt la configuración de la build del proyecto se hace a través de un archivo. Su nombre por defecto en ‘build.xml‘ en Ant y ‘Gruntfile.js‘ en Grunt

Tareas y objetivos

En esencia tanto en Ant como en Grunt se utilizan las tareas disponibles (‘tasks‘) para definir objetivos (‘target‘). Los objetivos contienen la configuración de nuestro proyecto utilizando estas tareas… ‘Copia estos ficheros‘, ‘borra los ficheros de este tipo‘, etc..

En Ant un target pueden depender de otros. Se ejecutarán los targets de los que depende antes que él y lo harán en el orden indicado. Esto permite crear un flujo de ejecución de tareas.

1
<project name="Ejemplo de build" default="ejecutar">
2
...
3
 <target name="ejecutar" depends="clean,crearDistro,crearWar"/>
4
...
5
</project>

En este caso ‘ejecutar‘ sería el target por defecto.

En Grunt se definen ‘alias‘ para el mismo resultado.

1
...
2
grunt.registerTask('default', ['clean', 'copy','uglify', 'concat','cssmin']);
3
..

Eso no significa que no puedas ejecutar targets individuales. Por ejemplo en Ant para lanzar el target clean sería, ejecutando en el directorio donde está el ‘build.xml

1
$ ant clean

o en Grunt, ejecutado en el directorio donde está el ‘Gruntfile.js

1
$ grunt clean

Variables externas

Tanto en Ant como en Grunt se pueden pasar variables al archivo de configuración desde línea de comandos, lo que resulta muy útil a la hora de configurar varios entornos del mismo proyecto en el Jenkins.

En Ant

1
$ ant −DdirEntorno=prepro

Usando así la variable en el buid.xml

1
<target name="clean">	
2
 <delete dir="${dirEntorno}"/>
3
</target>

En Grunt:

1
$ grunt −−dirEntorno=prepro

Y el Gruntfile.js

1
clean: {
2
 main: {
3
  src: ['<%= dirEntorno %>']
4
 }
5
}

… y en que se diferencian

Xml o Json/Javascript

Ant utiliza xml para definir la configuración. Esto hace que, sobre todo al principio, y con archivos de build complejos, que sea bastante rígido y engorroso.

Grunt en este aspecto utiliza json, un formato mucho más liviano. Además está embebido en un archivo javascript permitiendo utilizar este lenguaje con toda su potencia. Este aspecto le da mucho más flexibilidad que Ant. Aquí es donde se le notan los años a Ant y como muestra Gant,una alternativa en el mundo Groovy que ‘pasa’ del xml

Gestión de dependencias de las tareas

La filosofía de las dependencias de las tareas es completamente diferente. Ant ,de serie, trae diferentes tareas que ya se pueden usar. Esto no significa que se puedan utilizar otras tareas de terceros. Para esto se usa la tarea ‘typedef‘.

La gestión de dependencias de las librerías que son necesarias para ejecutar estar tareas es completamente ‘a mano’. No te queda otra que bajarte la librería he incluirla, o bien en tu distribución de ant (en el directorio ‘lib’) o bien dentro de tu home (en el directorio ‘.ant/lib‘)

En esto Grunt si que gana por goleada. Por defecto no viene con ninguna tarea predefinida, por lo que eres el que elige cual vas a utilizar, seleccionandola de su página de plugins. Probablemente existan varias posibilidades a la tarea que estás buscando. Después, para poder utilizarla, Grunt utiliza la potencia del gestor de paquetes de node.js, npm.

Por ejemplo, para instalar la tarea ‘uglify‘ que se utiliza para comprimir archivos js, se ejecuta el siguiente comando en el directorio donde este el Grutfile.js

1
$ npm install grunt−contrib−uglify −−save−dev

Esto incluye las dependencias en el ‘package.json‘ (Este fichero se crea al iniciar el proyecto ejecutando ‘npm init’)

Y para pode usar la tarea hay que añadir al Gruntfile.js:

1
...
2
grunt.loadNpmTasks('grunt−contrib−uglify');
3
...

Fácil y cómodo, aunque tampoco falto de problemas. Por ejemplo la tarea clean de repente dejo de funcionar en Windows, mientras que el Linux no había problema. El problema, una de las dependencias subió de versión… y dejo de funcionar. La solución fue añadir la dependencia a la versión que funcionaba directamente en el archivo ‘package.json‘. Espero tener tiempo para explicarlo mejor en otro post.

Epílogo, Conclusiones

Si eres de Back ,tienes algo de experiencia en Ant y quieres montar tu control de configuración para el Front que está basado en Javascript, trabajar con ‘Grunt’ te va a resultar muy familiar.

Son tecnologías diferentes, algunas tareas serán similares y otras más específicas  no encontrarás en Ant, pero la esencia es la misma, así que sin miedo.

Espero que os sirva.

M.E.

Vert.x: Mucho más que trabajar en Java como en node.js.. y en groovy, ruby,…

Prueba de concepto: Gateway con websockets y Gtalk utilizando Vert.x

[Vert.x Logo]La primera vez que oí hablar de Vert.x fue en la charla sobre el nuevo lenguaje Ceylon basado en la JVM que dio Gavin King  (la mente pensante detrás de Hibernate) el pasado febrero en MadridJUG. Comentó que para la web estaban enfocando sus esfuerzos en un framework asíncrono basado en Vert.x.

¿Asíncrono…?” Ya se me levantó la ceja a lo ‘Sobera’ .. y lo que me dio ya la puntilla es cuando se puso a picar en directo un servidor web (puro live coding :-)) me olía todo tenía un aire a como se trabaja con node.js,.. Así que me dije…”esto de Vert.x me lo tengo que mirar“.

He de reconocer que con el título del post me he pasado… He estado dándole vueltas a uno que tuviera ‘punch‘… y me parece que he tirado por lo fácil. En realidad Vert.x es mucho más que un servidor web… Su ‘misión‘, ‘visión‘ y ‘valores‘ es soportar millones de conexiones concurrentes usando un número mínimo de hilos del sistema operativo (¿¿?? así lo asegura en su documentación), imposibles en un esquema multihilo típico.

¿Qué es Vert.x?

Vert.x es un framework basado en eventos que corre en la máquina virtual de Java. Hecho para que sea fácil de escalar y soporte a tolerancia a fallos. Pensado para que existan de una manera sencilla varios cores en diferentes JVM y que se intercomuniquen entre ellos. Vert.x resuelve la concurrencia siguiendo el modelo de actores y además asegura que no existirán bloqueos entre hilos. Otra de sus características es su ‘bus de eventos‘ que permite desacoplar tu aplicación en módulos y comunicarse entre ellos a través de mensajes. Y todo de manera asíncrona.

Vert.x es ‘Políglota‘, soporta JavaScript, Ruby, Groovy, Java o Python y con vista a soportar Scala, Clojure e incluso PHP. Ejecuta código fuente por lo que, por ejemplo, existe la posibilidad de arrancarlo con ficheros ‘.java’ sin necesidad de compilarlos.

Simple hilo ó multihilo

Llegaréis a la conclusión y la compartiré de que con el título lo he simplificando demasiado ¿Pero porque he hecho esta comparación? Porqué Node.js y Vert.x tienen funcionamientos similares.

En JavaScript no existe la concurrencia. Aunque esta afirmación pueda ser no del todo cierto, porque en html5 y en el cliente existe los workers, en JavaScript sólo existe un hilo y las operaciones que bloquean se ejecutan con llamadas asíncronas.

Y quizás esto, lo que parece su debilidad, es su virtud es esto lo que hace que node.js este valorado como un servidor con poca latencia cuando existe mucha carga .

La diferencia fundamental entre node.js (o Vert.x) y un sistema tradicional multihilo es que la máquina virtual de node utiliza un sólo hilo para atender todas las peticiones. El hilo se limita a recibir la petición y realizar llamadas asíncronas. No espera el resultado de la petición y continua con la siguiente. Más tarde recogerá el resultado para devolverlo al cliente.

Por el contrario en un sistema multihilo, por ejemplo en un despliegue tradicional de Java, existe un hilo para cada petición. Este se queda bloqueado mientras espera el resultado de una operación. Esto hace que bajo mucha carga existan muchos hilos y parte de ellos esperando, lo que repercute en la latencia.

Vert.x trabaja de igual manera, en este caso utilizando el modelo de actores en el que cada uno de los actores será un ‘verticle‘. En la documentación lo definen con una partícula de Vert.x y en la práctica es la manera de definir el código desplegado. Los ‘verticles‘ se pueden agrupar en módulos (lo más usual cuando la aplicación deja de ser trivial) y estos se pueden reutilizar.

…Y la prueba de concepto

Con Vert.x es muy sencillo crear servidores y clientes socket, ssl, http y websocket.

Necesitaba poder familiarizarme con la herramienta y tenía que hacer algo. Es entonces cuando recordé la presentación y demo muy, muy chula que hizo Iván López en MadridGUG utilizando una cuenta de Gtalk como boot. Así que basándome en esa idea he creado una prueba de concepto realizando un Gateway con WebSockets y Gtalk utilizando Vert.x. El proyecto es un proyecto Java.

Se utiliza una cuenta de Gtalk para poder crear una sala de chat entre usuarios que se conectan por Gtalk y usuarios que se conectan con un navegador mediante websockets.

Este ejemplo no explota todas las posibilidades  de Vert.x como el escalado y el bus de eventos pero si que despliega servidores web y de websocket. Me ha permitido conocer como se genera, se configura y se ejecuta un módulo. En definitiva, ha conseguido mi objetivo que como he dicho más arriba era familiarizarme con el framework

El proyecto lo he subido a GitHub y que es lo que hace y como está explicado en el README.md .

[Logo GitHub] Prueba de concepto: Gateway WebSockets y Gtalk utilizando Vert.x

README.md

Espero que os sirva.

M.E.

Mis primeros pasos de ‘newbie’ en AngularJs

Logo de AngularActualmente estoy involucrado en un proyecto en el que la arquitectura es un Backend de servicios web Rest (Java) y como Frontend una aplicación de una sola página (SPA Single-page application) hecha en AngularJs, utilizando el patrón MVC en el navegador.

Siempre he tenido ganas en saber algo más de como funciona este framework y no podía perder la oportunidad de echar una mano en el Front.

Para poneros en antecedentes, vaya por delante que en mi anterior trabajo apenas se utilizaba JavaScript en la vista. Así que ahí estaba yo, leyendo un manual de AngularJs con muchas ganas, intentando asimilar todos los nuevos conceptos de la herramienta y del lenguaje.

Aquí van mis primeras conclusiones sobre Angularjs de un ‘newbie’ que todavía tiene mucho que aprender.

Single-page application

La primera y quizás más importante es que me ha encantado el concepto. Te plantea una aplicación web de una manera diferente. Ya no piensas en peticiones web, formularios, etc, sino que piensas en eventos.

Al ser una aplicación de una sola página pasas de pensar en una aplicación web al uso a una que se parece más a .NET. La página se carga una vez (index.html) y es Angular quien se encarga según la url (en realidad ficticia con un ancla #) la que carga las diferentes ‘plantillas’ (vista, código html parcial) y los diferentes ‘controladores’ (funciones javaScript) que hace que se convierta en diferentes ‘páginas’.

No se carga una página por petición por lo que no es necesario guardar variables ‘volátiles’ en sesión, simplemente la almacenas en memoria. De hecho nosotros solamente almacenamos en cookies las credenciales de acceso.

A nivel de controlador defines las funciones que responderán a los diferentes eventos. El apretar un botón, un enlace, el cambio de foco de un campo de formulario,etc… Te centras en programar la lógica del evento, sin preocuparte como propagar el cambio para dibujar el resultado al usuario. De eso se ocupa Angular…

Conexión vista-controlador-backend ¿Programación reactiva?

Dos cosas me han llamado la atención para bien. Primero, la conexión entre la vista y el controlador.

Es directa. Si desde el controlador se cambia una variable esta se propaga directamente en la vista y se produce un cambio en lo que está viendo en usuario. También en el otro sentido, se puede saber cuando se ha modificado una entidad por el usuario y procesar este cambio en el controlador.

Si tenemos en cuenta que los campos de un formulario pueden constituir una entidad en su conjunto, es fácil imaginar lo sencillo que es propagar los cambios también al backend. No se si se puede llamar ‘Programación Reactiva‘ pero se le parece mucho… Un cambio realizado por el usuario se puede propagar al backend y un cambio en el backend se puede propagar y que lo vea el usuario.

Inyección de dependencias

La segunda es la inyección de dependencias que implementa Angular. Una aplicación se divide en módulos y en estos hay controladores, directivas (estas enfocadas más a la vista y a sus validaciones) y servicios. Todas las dependencias, por ejemplo, de un servicio que necesita un controlador, se definen a nivel de módulo de aplicación.

Siguiendo el ejemplo, para poder utilizar el servicio en tu controlador es tan sencillo como tener como argumento en la definición de tu función controlador un objeto servicio. Angular se encarga de instanciar correctamente el servicio que necesita el controlador resolviendo a su vez todas las dependencias.

A nivel de modulo se pueden definir, factorías, servicios y proveedores… Seguro que quien se han pegado en Java con Spring esto les suena algo…

Más cosas

Angular es un framework muy completo. En el core viene con directivas, filtros, y servicios predefinidos (como su propia implementación del patrón ‘promise‘ [$q]) que te hace la vida más fácil para un novatillo en el lenguaje y en el concepto como yo.

Tiene ‘interceptadores‘ que son parecidos a los filtros de Java que te permiten capturar la petición al servidor y por ejemplo enviar las credenciales de conexión sin tener que hacerlo en cada petición.

Angular está orientado a TDD. Es sencillo tanto hacer test unitarios como test de integración.

Conclusiones Pros y Contras

Ventajas

En esta fase de aprendizaje Angular me lo ha puesto sencillo. Me ha definido un marco estándar de trabajo y me ha ayudado a no tener la sensación de estar haciendo las cosas no también como debería.

Además me he encontrado con que la documentación es buena y en este momento ya hay mucha gente trabajando con él por lo que puedes encontrar solución a casi cualquier problema en Stackoverflow.

Otra de las ventajas es su rapidez de ejecución. Las peticiones al servidor son sólo llamadas ajax y plantillas parciales html. Realmente es destacable la rapidez con que se muestran todos los cambios.

Este tipo de arquitectura es fácilmente cacheable al ser todo archivos estáticos por lo que la escalabilidad del Front casi deja de ser un problema.

Por lo que escrito más arriba. El dinamismo que le da a la web es difícil de superar en otra arquitectura.

Contras

La dudas que me surgen es que cuando la aplicación empiece a crecer en ficheros js cuanto va a ser de pesada en la primera carga. A lo mejor cuando llegue habrá que plantearse una librería como RequireJs. Por rendimiento realmente no es necesaria, ya que Angular sólo carga en memoria lo que necesita.

Otra de las pegas es de usabilidad. Es muy común que en un mismo controlador manejes, por ejemplo, dos formularios y que juegues con su visibilidad para mostrar uno u otro. Si en el proceso el usuario aprieta el botón de ‘Atrás’ del navegador lo más probable es que le lleve a una sección de la web que no se corresponde con el anterior paso. Estas cosas hay que tenerlas en cuenta en el diseño de la aplicación.

Otro punto a tener en cuenta es a indexación por parte de los buscadores. Al ser todo javaScript y dinámico probablemente Google no podrá indexar la web.

El problema de IE8. Es el único navegador que no soporta HTML5 y que actualmente aún lo usa mucha gente, aunque afortunadamente cada vez menos. Para que Angular soporte IE8 hay que hacer ‘unas movidas’, que hace que es mejor plantearse indicar al usuario que utilice otro navegador.

Y por último es un cambio de concepto en el diseño de una página web. Por las inercias de las empresas, esto lleva a no pocas reticencias para que alguna se atreva a realizar su proyecto en Angular.

Para una web que siempre requiera un registro, y muy dinámica tipo red social, para mi las ventajas supera con mucho a los inconvenientes.

Espero que os sirva.

M.E.

Java versus JavaScript

Java versus JavaScript, reflexiones

Con la aparición de Node.js y la posibilidad de programar JavaScript en servidor se palpa entre los “javeros” cierta, no se encontrar la palabra, …¿preocupación?. La sensación es de “…nos están cambiando el agua…” y el comentario más oído es “… parece que es lo que se lleva ahora, no me gusta, pero habrá que aprenderlo…

A este desasosiego no ayudan post como los de PayPal (enlace ) en el que en resumen dicen que se pasan a JavaScript entre otras cosas porque es más rápido, necesitan menos gente y además se tira menos código. En respuesta a este post ha habido otros que han salido en defensa de Java y para poner coherencia en el tema (enlace)… y es que es lo que tienen casi todos los benchmark que pecan de partidistas.

En todas las ingenierías, pero mucho más en informática, tienes que estar en continua formación y estar al tanto de lo que se está haciendo. Es cierto que no podemos negar que también va todo un poco por modas y que es todo es cíclico. Parece que más tarde o más temprano siempre volvemos al mismo sitio que nos estamos moviendo en un circulo cerrado. Yo prefiero verlo más como una espiral… si la ves verticalmente parece que estás en el mismo punto,… pero que si la ves horizontalmente te das cuenta que estás en un nivel superior. Un ejemplo de esto son las nuevas bases de datos NOsql. Puede parecer que vuelven a las bases de datos pre-relacionales pero en realidad aportan muchas más cosas (escalabilidad, rapidez, big data y su explotación).

Pasa lo mismo con JavaScript hace mucho mucho tiempo que ha dejado de ser un lenguaje que sirve para poco más que hacer validaciones y hacer las “cosas bonitas” en la capa de presentación.

El gran problema de los “javeros” que dan sus primeros pasos en JavaScript, entre los que me incluyo, es que a la hora de enfrentarse al nuevo lenguaje piensan “… al final será algo como Java, con tipado dinámico y bueno con callbacks... ” y nada más lejos de la realidad, JavaScript es otra filosofía y en realidad casi casi comparte con Java poco más que el nombre y algunas palabras reservadas.

Creo que en el aprendizaje hay que enfrentarse con una actitud diferente y positiva. Me parece muy interesante el trabajo que ha realizado Micael Gallego en su blog (enlace), en el que explica su viaje en el aprendizaje del lenguaje desde el punto de vista de un programador Java y como a lo largo de los diferentes artículos va entendiendo la filosofía de JavaScript. A mi me ha ayudado mucho su lectura, así que no puedo más que recomendarla.

Reconozco que no soy experto en JavaScript y no puedo opinar en profundidad. Pero desde fuera creo que lo bueno y lo malo de JavaScript es que debido a su dinamismo, se pueden hacer las cosas de varias maneras. En Java por el contrario que es todo más cuadriculado.

De todas maneras creo que lo mejor es ser práctico, intentar conocer las debilidades y las fortalezas de cada lenguaje… Por ejemplo no me platearía hacer una aplicación de escritorio para Widonws en Java, para eso creo que es mucho mejor .NET. Por la misma razón me encontraría más a gusto, en aplicaciones de Backend en un proyecto con un equipo de trabajo numeroso, en un arquitectura Java que en una JavaScript, ya que al ser Java más “estricto” el código tendería ser más uniforme.

Lo que es cierto es que JavaScript permite hacer nuevas arquitecturas muy escalables y derivando gran parte de la responsabilidades al cliente. Angular.js es un framework que sigo muy de cerca. Sé que en algunos aspectos puede ser limitado pero prefiero la seguridad de basarme en algo estándar para montar una arquitectura MVC en el cliente.

Además JavaScript, junto con HTML5 se está convirtiendo en la única opción en la parte de navegador. Debido a las restricciones de seguridad que se están poniendo a los applets de java y a las extensiones y plugins. Son un autentico quebradero de cabeza por los agujeros de seguridad encontrados. Un ejemplo, Firefox a partir de su versión 26 no vienen habilitados por defecto los plugins excepto el de Flash.

Por eso en cosas “especiales” en la capa de cliente que por inercia antes te planteabas hacerlas con un applet o una extensión ahora enfocas tus esfuerzos en hacerlas en JavaScript… y se pueden hacer cosas muy, muy chulas.

Espero que os sirva.

M.E.

OpenStreetMap-OpenLayers-OpenRouteService la ‘alternativa’ a Google Maps

Realmente no te das cuenta de la dependencia que tienes de los servicios de Google. Piensas que puedes disponer de ellos porque además de ser potentes son gratis… hasta que dejan de serlo.

[Mapa OpenLayers]Me ha ocurrido en el pasado, en un proyecto personal (747mx.com) que utilizaba el traductor de Google. Era gratis hasta un número de peticiones, suficientes para la pretensiones de esa página y pasó a ser de pago desde la primera petición. Algo que no me podía permitir en ese portal.

Así que cuando en una entrevista a Javier De La Torre uno de los fundadores de Vizzuality señalaba a OpenStreetMap como alternativa seria a Google Maps me dije ‘… esto me lo tengo que mirar‘ .

Para saber como funciona de verdad, lo que me propuse fue migrar un código que tenía con el API de Google Maps en 747mx.com. Basarme en él y hacer lo mismo en OpenStreetMap utilizando lal librería OpenLayers y el servicio de geolocalización de OpenRouteService.org. Sigue leyendo