lunes, noviembre 28, 2011

Algunos libros sobre Java y JVM

Durante estas últimas semanas he tenido la ocasión de terminar varios de los libros que tenía pendientes así como de realizar alguna nueva adquisición que, de momento, está encolada en mi lista de lectura.

Me gustaría aprovechar esta entrada para compartir con vosotros algunos de los libros anteriores que, bajo mi punto de vista, podrían resultar interesantes para tod@s aquell@s que os dediquéis, de algún modo, a trabajar con la plataforma Java (lenguaje y/o máquina virtual).

El primero de ellos es Java Performance from The Java Series. Escrito por Charlie Hunt, JVM performance lead engineer en Oracle, y  Binu John, senior performance engineer en Ning. Ha sido mi última adquisición y únicamente he podido leer los dos primeros capítulos pero creo que estamos ante uno de las lecturas obligatorias para tod@s aquell@s que se dedican y/o les gusta el mundo del rendimiento de aplicaciones sobre la JVM.

JVM Tuning, profiling, mediciones, herramientas, escritura de benchmarks, internals de la JVM, algoritmos de recolección de basura y tuneo de los mismos, gestión de la memoria,  . . .  son sólo algunas de las temáticas tratadas en este magnífico manuscrito.


Otro magnífica referencia  relativa al mundo Java: The well-grounded Java developer. Se trata de un early access por lo que sólo he podido leer los capítulos disponibles hasta el momento. Pensado para desarrolladores con unos sólidos conocimientos de Java el libro abarca un amplio espectro de temáticas como pueden ser:
  • Algunas de las novedades de Java 7
  • Nuevo mecanismo de IO y concurrencia
  • Classfiles y bytecode
  • Inyección de dependencias
  • Lenguajes alternativos en la JVM: Clojure, Groovy y Scala
  • Integración continua
  • . . .
En lineas generales creo que se trata de una lectura recomendada (a la espera de que se publique la segunda mitad del libro). Los capítulos pueden ser leidos de manera independiente, saltándose aquellos en los que ya se conoce de manera profunda la temática tratada en el mismo.

Un libro que había leido hace tiempo y que he vuelto a leer hace  unas semanas ha sido Java Concurrency in Practice. Poco puedo decir de este libro que no se haya dicho ya. Otra de las lecturas obligatorias para todos aquellos desarrolladores que trabajen con el lenguaje Java.

Ofrece una visión práctica de cómo se deben escribir programas escalables y seguros aprovechando la capacidad de las nuevas arquitecturas hardware.









Functional Programming for Java Developers. Escrito por Dean Wampler. Es un libro en el que se introducen los conceptos básicos de la programación funcional (que está "renaciendo" gracias a lenguajes como Scala o Clojure, además de sus beneficios a la hora de escribir programas concurrentes entre otras muchas cosas).

Es un libro muy cortito aunque personalmente no me ha entusiasmado demasiado. Si no tenéis ninguna experiencia en programación funcional puede ser un buen punto de partida. No se cubren mónadas, laziness ni combinators.

jueves, octubre 06, 2011

Escalabilidad, disponibilidad y estabilidad

En algunas ocasiones hemos hablado de temas de escalabilidad y disponibilidad de sistemas aunque siempre desde un punto de vista muy práctico, haciendo referencia a los problemas que ocupan nuestro día a día. Me gustaría recopilar, a lo largo de una serie de posts, algunos de los patrones y/o tecnologías más populares relacionados con la escalabilidad, la concurrencia o la alta disponibilidad.

Me gustaría dejar claro desde un principio que lo aquí expuesto son simplemente mis ideas, adquiridas a lo largo del tiempo gracias a la experiencia acumulada en la construcción de diversos sistemas software, mis estudios de doctorado, leer y practicar mucho, aprender de los maestros y pasarme muchas, pero muchas muchas,  horas aporreando el teclado. Por tanto, las cosas que aquí aparecen podrían ser erróneas y/o incompletas.

Me gustaría comenzar con una tecnología relacionada con la concurrencia: la memoria transaccional (STM en adelante).

Escribir programas concurrentes es una tarea sumamente complicada y, habitualmente, no determinista; ¿cuantas veces habremos probado un programa multihilo en nuestros sistemas de integración continua y , tras poner el sistema en producción, nos hemos encontrado con nuevos errores? Tan real como la vida misma.

Habitualmente las inmutabilidad (hablaremos de ella en el futuro) es un gran aliado a la hora de escribir programas concurrentes dado que resulta mucho más sencillo razonar sobre información cuyo estado permanece estable. Sin embargo, como en la mayoría de las situaciones, la inmutabilidad no es una bala de plata que soluciona todos los problemas por lo que tendremos que lidiar con información cuyo estado puede variar y con toda la problemática asociada a la misma. Llegados a esta situación, y siguiendo con el enfoque con el que estamos más familiarizados, estaríamos peleándonos con bloqueos, granularidad de los mismos, etc.

Un vistazo a la STM

La STM puede ayudarnos a resolver el problema anterior de manera mucho más sencilla visualizando la memoria (heap + pila) como si de un dataset transaccional se tratara. Algunas de las características más relevantes:

  • Concepto muy similar al de una base de datos tradicional. Se llevan a cabo operaciones como begin, commit o abort/rollback
  • En caso de que se produzca una colisión la transacción será relanzada de manera automática
  • Se realiza un proceso de rollback sobre la memoria cuando se produce una operación de abort.
  • Las transacciones se pueden componer y anidar

Un aspecto sumamente importante que debemos tener en cuenta a la hora de utilizar la memoria transaccional es que todas las operaciones englobadas en el ámbito de una transacción deberán ser idempotentes (anteriormente hablábamos del relanzamiento automático en caso de que se produjera una colisión).

Existen numerosas implementaciones disponibles para la máquina virtual de Java (JVM) entre las que destacan:

En la siguiente entrada realizaremos varios ejemplos prácticos de uso de la memoria transaccional y analizaremos cuales son los escenarios más propicios para la utilización de esta solución.

Hasta pronto!

Migue

miércoles, octubre 05, 2011

[Off-Topic] Poniéndome al día y buenas noticias

Hola a tod@s,

Hace más de un mes y medio de la última entrada en el blog pero es que me está costando mucho más de lo esperado retomar todas las cosas pendientes y/o atrasadas por lo que últimamente me estoy agobiando un poquito. De todos modos el objetivo de la entrada no era aburriros con mis "problemas" sino comentaros una buena noticia, al menos para mi :), aunque seguro que muchos de los que os pasáis por aquí ya lo sabréis: ¡vamos a ser papás!

Así es; si todo sigue como hasta ahora, dentro de cuatro semanas aproximadamente tendremos  a nuestro hijo Sergio entre nuestros brazos.


Estos últimos meses han sido, sin lugar a dudas, los mejores meses de mi vida. Meses de cambio, de preparar la casa, de descubrir cosas que ni siquiera sabía que existían o de convertirme en un "manitas".



Con toda seguridad los cambios serán mucho más notables cuando el pequeño nazca pero de momento prefiero no adelantar acontecimientos y centrarnos en disfrutar del "poquito" tiempo de embarazo que nos queda.


Dentro de poco tendré que repartir mimos y cuidados entre mis dos amores aunque mi gordita dice que nada de dividir, que como mínimo duplicar así que . . . difícil tarea me espera.

Hasta pronto!

Migue

viernes, agosto 26, 2011

De regreso

Ya estoy de vuelta.

Por suerte ya me he recuperado por completo de mi parálisis facial (finalmente "solo" me duró once días aproximadamente) con lo que de nuevo estoy online.

La entrada no será muy larga :) , simplemente quería que supierais que me encuentro perfectamente.

Espero retomar el blog durante los próximos días aunque con lo que tenemos en camino tengo una agenda en la que el tiempo libre brill a por su ausencia.

Hasta pronto!

Migue

PD: he escrito la entrada desde el iPad y la verdad que se escribe mucho más rápido de lo que uno podría esperar en un principio.

martes, agosto 02, 2011

Offline

Durante los próximos días estaré "offline" por completo. Nada de ordenador, IPad, Internet y similares :). Voy a ver si consigo desconectar por completo durante estos días y termino de recuperarme de mi parálisis facial.

Hasta pronto!

Migue

sábado, julio 30, 2011

Parálisis facial

Hacía muchísimo tiempo que no me ponía enfermo pero esta vez me ha tocado. Será que me estoy haciendo mayor . . . :(.  La doctora me ha diagnosticado parálisis facial.

Gracias a Dios suena mucho más aparatoso de lo que es: tengo la mitad de la cara dormida (es una sensación similar a la que se presenta cuando regresas del dentista) y se me cierra un poco el ojo con lo que  a veces se me cansa la vista y no puedo enfocar demasiado bien. Las buenas noticias es que no es doloroso aunque si bastante incómodo. Las malas es que me puede durar desde tres días hasta tres meses y que "del mismo modo que viene se va" (palabras textuales de la doctora).

Espero recuperarme cuanto antes y seguir dando un poco de guerra!

Hasta pronto!

Migue

martes, julio 19, 2011

Grupo de escalabilidad: mapa clusterizado

Tras los resultados de la encuesta que realizamos durante la semana pasada hemos creado un pequeño mapa geográfico en el que se muestran a modo de clúster los distintos miembros que componemos el grupo de escalabilidad en español y dónde estamos ubicados cada uno de nosotros:

Embedded from Google Shared Spaces. Create your own space.

El registro el libre y cada una de las personas que aparece en el mapa anterior se ha registrado de manera propia.

Si estáis interesados en alguna temática relacionada con la escalabalidad de sistemas de información os animo a que os registréis en el grupo y también os apuntéis en el mapa!

Hasta pronto!

Migue

miércoles, julio 13, 2011

Evento sobre escalabilidad de sistemas

Desde el grupo de escalabilidad en español hacía tiempo que estábamos barajando la posibilidad de organizar un evento relativo a la escalabilidad de sistemas y finalmente hemos dado un paso adelante.

Es una primera aproximación en la que estamos intentando recabar el mayor conjunto de información posible con el objetivo de llegar al mayor número de gente posible.

No voy a repetir todo el rollo que hemos escrito en otros sitios :) así que simplemente os dejo los enlaces donde podréis encontrar toda la información de la que disponemos hasta este momento:

Estaremos encantados de recibir vuestras críticas, sugerencias y/o propuestas.

Hasta pronto!

Migue

miércoles, junio 29, 2011

AspectJ y Scala (y III)

Última entrada (en esta ocasión mucho menos ladrillo) de esta mini-comparativa que estamos llevando a cabo entre AspectJ y Scala (podéis consultar las anteriores entradas en los siguientes enlaces: AspectJ y Scala (I), AspectJ y Scala (II).

Hemos estado revisando cómo llevar a cabo la aplicación de varias funcionalidades como el uso de cachés o la gestión de transacciones mediante el uso de AspectJ y Scala, haciendo hincapié en las ventajas y desventajas de las dos aproximaciones. Nótese que hemos estado hablando de funcionalidad transversal como las transacciones y la caché pero no hemos hablado de otro tipo de funcionalidades las cuales abarcan un espectro mucho más amplio como por ejemplo FFDC (First Faiulure Data Capture), Profiling, gestión de la concurrencia, etc. En este tipo de situaciones el uso de Scala y HFOs resultaría mucho más tedioso que los ejemplos vistos en las entradas anteriores; derivando en los síntomas clásicos de funcionalidad "difuminada" por toda nuestra apliación.

¿Conclusión? El uso de cualquiera de las dos aproximaciones que hemos estado analizando dependerá, como en el 90 por ciento de todas las situaciones, del problema que estemos resolviendo, por lo que tendremos que escoger la "herramienta" más adecuada para el problema que se nos plantea.

¿Y por qué no un mixin de las anteriores? Esta es una de las alternativas que más me convence:
  • Compilamos nuestros programas Scala de la manera habitual.
  • Definimos nuestros aspectos para llevar a cabo la funcionalidad transversal deseada.
  • Realizamos un proceso de binary weaving (ya sea build time o load time)
Mediante el mecanismo anterior estaremos aplicando nuestros aspectos a nuestro código Scala compilado.

En mi cuenta de GitHub podréis encontrar dos proyectos Eclipse (scala-simple-service y aspectj-advice-scala) que deben ser utilizados de manera conjunta. Mediante estos dos pequeños proyectos de ejemplo se ilustra cómo podemos utilizar conjuntamente aspectos escritos en AspectJ que hagan advice sobre código Scala compilado.

Hasta pronto!


martes, junio 28, 2011

AspectJ y Scala (II)

En la entrada anterior analizamos algunas de las similitudes y diferencias existentes entre Scala y AspectJ, llevando a cabo una implementación de una caché extremadamente simple en ambos lenguajes, describiendo las ventajas y desventajas presentes en cada una de las aproximaciones. Durante esta entrada analizaremos un ejemplo de aplicación de una funcionalidad transversal como la gestión de transacciones. 

El ejemplo que aquí nos ocupa no persigue realizar una implementación detallada de control de transacciones sino simplemente ilustrar como podríamos aplicar una funcionalidad transversal mediante el uso de AspectJ o Scala.

Del mismo modo que en el post anterior, comenzamos por la aproximación basada en AspectJ. Para ello en primer lugar definimos una simple anotación que nos sirva como elemento de marcado de aquellas clases y/o métodos que se deben ejecutar bajo un contexto transaccional.

Una vez definida la anotación anterior definiremos un aspecto que sea capaz de detectar aquellos joint point en los que deseamos establecer un contexto transaccional. 

pointcut transactionalOperation() : execution(@Transactional * * (..) );

Con el pointcut anterior estaremos capturando las llamadas realizadas sobre cualquier método anotado con nuestra anotación @Transactional. Ahora necesitaremos definir un advice en el que llevamos a cabo la gestión de la transacción (nótese que este gestor de transacciones es completamente absurdo y simplemente imprime por pantalla la funcionalidad real que debería ser llevada a cabo por un gestor de transacciones operativo)


En muchas ocasiones todos los métodos de una clase necesitarán ser transaccionales, y no querremos anotar todos los métodos de dicha clase. En este supuesto podríamos utilizar anotaciones a nivel de clase que nos permitan seleccionar aquellos métodos que deseemos (por ejemplo, todos los métodos públicos).

Adicionalmente, podríamos hacer uso de los ITD y establecer la transaccionalidad a todas aquellas clases  que nosotros deseemos. Por ejemplo, supongamos que todos los nombres de nuestros servicios, los cuales deseamos que sean transaccionales, terminan con el sufijo Service. Podríamos, mediante el uso de un aspecto, añadir la anotación @Transactional a todos nuestros servicios.

declare @type : *Service : @Transactional ;

Dicho aspecto, en conjunción con el anterior, provocaría que todos nuestros servicios fueran transaccionales

En Scala, de nuevo, haremos uso de funciones de alto nivel (high order functions) de manera muy similar a la solución de la caché descrita en la entrada anterior:

Si deseamos que un método de uno de nuestros servicios sea transaccional no tendremos más que extender de la clase abstracta y utilizar la HOF anterior:

Si comparamos las soluciones aportadas por cada una de las dos alternativas tendremos que
  • En el caso de AspectJ no necesitamos anotar cada método de manera independiente puesto que podríamos hacer uso de anotaciones a nivel de clase. El nivel de granularidad que podemos alcanzar está definido a nivel de método (aunque tampoco es un problema excesivamente grande puesto que podríamos utilizar el patrón Extract Method para extraer la funcionalidad transaccional a un método sobre el cual podríamos aplicar nuestro aspecto).
  • En el caso de Scala necesitaremos recubrir nuestra lógica con la HOF definida en nuestro ejemplo anterior. En esta situación, el nivel de granularidad es notablemente superior puesto que podemos recubrir una simple parte de nuestro método
Durante esta segunda entrada hemos vuelto a confrontar Scala y AspectJ a la hora de aplicar una funcionalidad transversal, intentando plasmar las ventajas y desventajas de cada uno de ellos.

En la siguiente y última entrada de esta serie analizaremos cómo aunar lo mejor de ambos mundos en un ejemplo práctico que nos sirva como base para futuros ejemplos.

Como siempre podéis encontrar el código fuente de todos los ejemplos del blog (o casi todos :) ) en mi cuenta de GitHub, bajo el proyecto blog-examples.

Hasta pronto!

PD: perdón por el ladrillo de entrada :(.

martes, junio 21, 2011

AspectJ y Scala (I)

¿Podemos establecer alguna conexión entre estos dos mundos? Si nos detenemos por un instante veremos que comparten muchas más cosas de las que a simple vista podría parecer:
  • Son lenguajes de tipado estático.
  • Ambos producen código compatible con la máquina virtual de Java (JVM)
  • Las funciones de alto nivel de Scala comparten algunas características con los advices de AspectJ
  • Los traits de Scala comparten algunas características con el static crosscuting de AspectJ.

Durante el resto de la entrada que nos ocupa (y la siguiente) realizaremos una pequeña comparativa en la que pondremos de manifiesto el modo en que cada uno de estos lenguajes resuelve determinado tipo de problemas. Pongámonos manos a la obra.

Cachés

A través de este ejemplo se pretende presentar el modo en que ambos lenguajes solucionan el problema de aplicar una funcionalidad transversal en un punto determinado del código. Implementaremos un mecanismos de caché extremadamente sencillo de manera que podamos centrar nuestra atención en los aspectos relevantes de las alternativas que estamos planteando

En el caso de AspectJ se está tendiendo a utilizar las anotaciones como un elemento de marcado (y parece que está siendo recibido con una aceptación más que notable). Nuestro primer paso será definir la anotación con la que realizaremos el "marcado" de aquellos métodos que deseamos establecer como cacheados:

@Retention(RetentionPolicy.RUNTIME)
public @interface Cachable {
   String scriptKey () default "";
}


El atributo keyScript de la anotación anterior actuaría (en una caché real), como un pequeño lenguaje de scripting de manera que pudiera ser evaluado por la caché para generar la clave bajo la que se almacenará una determinada llamada (obviaremos esta parte para intentar no distraernos de nuestro principal objetivo).

Una vez definido el elemento de marcado, definiremos nuestro aspecto, el cual será capaz de capturar las llamadas de aquellos métodos anotados con @Cacheable y realizar la lógica necesaria de nuestra sencilla caché



En el caso de Scala llevaremos a cabo nuestra funcionalidad transversal mediante el uso de funciones de primer nivel (high order functions)

Gracias a la funcionalidad anterior, podemos pasar al método cache una función que será ejecutada en caso de ser necesario, devolviendo los valores de la caché en el supuesto de que haya sido calculado en un paso anterior.

Si comparamos las dos alternativas que hemos planteado hasta este momento:
  • En el caso de AspectJ, cada uno de los elementos que deseamos cachear tendremos que anotarlos con, valga la redundancia, la anotación que hemos definido anteriormente. Mientras tanto, en el caso de Scala, tendremos que recubrir cada uno de los métodos que deseamos cachear con la función de alto nivel (high order function).
  • En el caso de AspectJ estamos utilizando un "lenguaje" externo que actua como elementos de las claves de nuestra caché mientras que en el caso de Scala estamos utilizando el propio lenguaje de manera nativa, con el consiguiente beneficio que ello conlleva.
Esta ha sido nuestra primera aproximación a Scala y AspectJ. Durante las siguientes entradas analizaremos algunos ejemplos adicionales y veremos como podemos integrar lo mejor de ambos mundos.

Podéis encontrar el código fuente de los ejemplos anteriores en el siguiente repositorio de GitHub, concretamente en los proyectos AspectJCacheExample y ScalaCacheExample.

Hasta pronto!

    viernes, junio 03, 2011

    Mecanismo de Load Time Weaving (LTW)

    Durante la última entrada analizábamos de manera introductoria los diferentes mecanismos de tejido ofrecidos por AspectJ así como las principales características de los mismos. Durante esta entrada nos acercaremos un poquito más al mecanismo de tejido en tiempo de carga, por normal general más desconocido, desde mi punto de vista, que el mecanismo de tejido en tiempo de construcción (durante todos los ejemplos que hemos visto en anteriores entradas siempre hemos utilizado el tejido en tiempo de construcción).

    Los pasos que tenemos que seguir cuando utilizamos el tejido en tiempo de carga son los siguientes:

    • Iniciar nuestra aplicación con el archivo aspectjweaver.jar el actuando como un agente (hablaremos de agentes en otra entrada). Para ello podríamos utilizar una línea como la siguiente
    java -javaagent:/aspectjweaver.jar
    • Durante el proceso de inicialización del agente (llevado a cabo por la máquina virtual) el propio agente recupera aquellos archivos existentes en el classpath que coincidan con META-INF/aop.xml (en el caso de encontrar múltiples llevará a cabo la combinación de los mismos).
    • Carga de los aspectos indicados.
    • El agente se registra como un listener del evento de carga de clases de la máquina virtual. Mediante este mecanismo se tiene acceso a la definición de la clase, permitiendo incluso la modificación de la misma.
    • Continua el proceso normal de carga de nuestro aplicación.
    • Cada vez que una nueva clase es cargada la máquina virtual notifica al agente dicha situación. En ese momento es posible examinar la clase en cuestión y determinar si algunos de los aspectos cargados con anterioridad necesita ser tejido. En caso afirmativo, la clase será tejida con el aspecto en cuestión, retornando el bytecode resultante a la máquina virtual.
    • La máquina virtual utiliza el bytecode resultante como elemento de definición de la clase.
    Mediante el conjunto de pasos anteriores, aquellas clases que hayan hecho matching con las definiciones de nuestros aspectos tendrán incorporada la funcionalidad definida en éstos últimos.

    El agente anterior utiliza un interfaz de la máquina virtual conocido como JVMTI (Java Virtual Machine Tools Interface) que ha sido introducido a partir de Java 5. En el caso de que utilicéis una versión anterior podréis hacer uso de este mecanismo mediante una versión basada en classloaders específicos.

    viernes, mayo 27, 2011

    Weaving en AspectJ (I)

    Hace un tiempo escribí una serie de entradas relacionadas con la orientación a aspectos en general y AspectJ en particular (podéis encontrar dichas entradas aquí) que posteriormente agrupé en un documento.

    Hasta este momento nos hemos centrado en la teoría de la orientación a aspectos, cómo escribir los mismos y algunas de sus posibles aplicaciones. Sin embargo, no hemos prestado especial atención al modo en el que los aspectos se combinan con las clases para componer nuestro sistema final. Durante esta entrada y las siguientes profundizaremos en diferentes aspectos del proceso de tejido (weaving).

    El mecanismo de tejido es aquel que nos permite combinar la definición de nuestras clases y de nuestros aspectos en un ente ejecutable que conforma nuestro sistema final.

    Podemos clasificar los diferentes modelos en base al momento en el que llevan a cabo el tejido. En este caso tendríamos:

    • Build time. Las clases y los aspectos son combinados durante el proceso de construcción de nuestra aplicación.
    • Load time (LTW). En este caso el tejido se realiza en el momento en el que una clase se carga en la máquina virtual, por lo que en este caso no será necesario llevar a cabo ningún proceso adicional en nuestro proceso de construcción. 
    Otra posible clasificación podría establecerse en función del los tipos de entrada del proceso de weaving
    • Source code weaving. La entrada al proceso son archivos de código fuente (clases y aspectos)
    • Weaving binario (bytecode). La entrada al proceso es el bytecode obtenido como resultado del proceso de compilación de nuestras clases
    De manera esquemática, a continuación se reflejan las diferente combinaciones ofrecidas por el weaver de AspectJ:

    • Tiempo de construcción: las entradas admitidas son tanto código fuente como clases compiladas (bytecode)
    • Tiempo de carga: las entradas pueden ser bytecode o un archivo xml (lo veremos más adelante)

    Con esta pequeña entrada nos hemos aproximado de manera sencilla a los procesos de tejido presentes en AspectJ de una manera teórica. En futuras entradas analizaremos con un poco más de detalle los contenidos aquí presentados, haciendo especial hincapié en los mecanismos de tejido en tiempo de carga.

    Hasta pronto!

    sábado, mayo 21, 2011

    Libros: últimas y futuras lecturas (II)

    Esta es la primera entrada que escribo desde mi reciente adquisición: un IMac 27''. Lo siento, tenía que decirlo :). A ver si me acostumbro a este, para mi, nuevo sistema operativo y le comienzo a sacar partido.

    En la entrada anterior hablaba sobre algunas de las últimas y/o futuras lecturas realizadas durante esta última temporada. Puesto que no quería convertir dicha entrada en un ladrillo, se me quedaron algunos libros en el tintero que analizaremos a continuación.


    Este libro llego a mis manos gracias a un profesor visitante de la UPM que estuvo impartiendo un seminario sobre wait free computing. Siento no recordar ahora su nombre (vaya cabeza que tengo).

    Los profesores Maurice Herlihy, uno de los precursores de la memoria transaccional,  y Nir Shavit nos ofrecen una visión novedosa de los nuevos paradigmas de programación para arquitecturas multinúcleo.

    Los primeros capítulos son más teóricos, dejando la parte más divertida para la segunda mitad del libro. No he tenido ocasión de leérmelo de principio a fin pero si que me he leído capítulos independientes y he de reconocer que me han parecido mucho mejor de lo que esperaba. Espero sacar un poco de tiempo libre para poder leerlo al completo porque todo apunta que se puede convertir en uno de mis libros favoritos.

    Desde que programo en Scala he aprendido muchas cosas nuevas, ya no sólo del lenguaje, sino de la programación funcional en general.

    Siempre he querido dar mis primeros pasos en Haskell pero nunca he tenido tiempo y, sinceramente, me parecía un poco complicado. Tras el inicio de mi andadura en Scala creo que lo veo con otros ojos así que, en la medida de lo posible, voy a intentar dar mis primeros pasos en este lenguaje. 

    Todas las referencias que tengo de este libro son muy buenas pero ni siquiera lo tengo así que, cuando me decida a dar el paso, creo que será mi próxima adquisición.

    Mi fascinación por la máquina virtual java crece por momentos (creo que ya quedó patente en la entrada anterior).

    Clojure es un lenguaje dinámico (dialecto de Lisp) que se ejecuta sobre la JVM (compila directamente a bytecode). Destaca, y esto es lo que más me gusta, por su eficiente infraestructura para la programación multihilo.

    Básicamente es un lenguaje puramente funcional que destaca por su amplio abanico de estructuras de datos inmutables y persistentes. En aquellos casos en los que el cambio es algo necesario, Clojure incluye en el propio lenguaje un sistema de memoria transaccional.


    De nuevo se me quedan en el tintero muchos otros libros pero, de nuevo, no quiero que la entrada sea demasiado larga. En futuras entradas apostaré por comentar de uno en uno los libros ya leídos, intentando profundizar un poquito más de manera que si alguien estaba dudando si leérselo o no, puede tener una opinión más al respecto.

    Hasta pronto! 

    sábado, mayo 14, 2011

    Libros: últimas y futuras lecturas (I)

    Durante estos últimos meses mi tiempo libre se ha convertido en un bien escaso (prácticamente nulo) por lo que muchas de las cosas que me gusta hacer las he tenido que ir aplazando hasta encontrar un mejor momento. Una de ellas es actualizar el blog con una frecuencia un poco mayor a la habitual, y aprovechando que estoy en Esslingen (Alemania), que todo el mundo está durmiendo y que llevo rondando por ahí desde las seis y veinte de la maniana he decidido pasarme un rato por aquí :).

    En esta ocasión me gustaría compartir con vosotros algunos de los últimos libros que me he leído, estoy leyendo, o tengo intención de leer.

    Me he leído la primera edición y ahora estoy terminando la segunda. Creo que se trata de una referencia excelente tanto para aquellas personas que desean comenzar su andadura en Scala así como para desarrolladores más experimentados con conocimientos del lenguaje.

    Si nunca habéis programado en Scala os recomiendo que le echéis un vistazo, os aseguro que no os defraudará. En este blog podréis encontrar una pequenia guía de introducción (en espaniol) así como numerosas entradas relacionadas con diferentes aspectos del lenguaje (espero que en un futuro este tipo de entradas puedan ir incrementando, tanto en calidad como en cantidad)

    Una de mis últimas adquisiciones. Está en Beta pero ya me lo he leído. Necesitará una lectura completa de nuevo, aunque en esta ocasión tendrá que ser delante de una pantalla de manera que pueda "ensuciarme" :) las manos.

    En este libro se tratan algunas de las técnicas/plataformas más novedosas de programación concurrente sobre la máquina virtual java. Nuevos mecanismos de concurrencia en las últimas versiones de Java, análisis de las bondades de Clojure para la programación concurrente, memoria transaccional, modelos de actores, Akka (hablaremos de Akka en futuras entradas), Scala, GPars.

    Una lectura recomendable para aquellos que quieran sacarle partido a los procesadores multinúcleo o que quieran actualizar sus conocimientos sobre programación concurrente.

    Qué son DSL? Para que se utilizan? Cómo escribo un DSL? En este libro , Debasish Ghosh desgrana hasta el último detalle de un temática tan popular en la actualidad como los lenguajes de dominio específicos. Una visión pragmática sobre la creación y utilización de lenguajes de dominio específicos ante la que ninguno se quedará indiferente. 

    A lo largo del libro se desarrollan numerosos ejemplos (complejos en muchas ocasiones) de diversa índole. Scala, Groovy, Clojure, Ruby y Java son los lenguajes utilizados en el desarrollo de los ejemplos por lo que, este libro, además de la temática principal, puede servir como una primera toma de contacto con alguno de los lenguajes de la máquina virtual Java que están adquiriendo una notable popularidad en estos días.

    En este caso de trata de una recomendación de Matín Pérez a la que hacía tiempo que tenía ganas de meterle mano. No tengo una opinión forjada porque sólo llevo leídos dos capítulos pero la verdad que hasta el momento me está gustando mucho, tanto por la temática como por la manera que está escrito.

    Recientemente he tenido la suerte de hacer algunas "cosillas" con la JVM pero por lo que he podido ver hasta el momento, este libro adquiere un nivel de detalle notable.

    Prometo un post independiente cuando lo termine por completo pero me quedo con la idea de que este libro puede ayudar a escribir mejor código.

    No quiero convertir esta entrada en un ladrillo (si no lo he hecho ya :) ) así que vamos a detenernos aquí. Continuaremos en la siguiente entrada con alguno que se ma quedado en el tintero.

    Hasta pronto!!

    PD: Espero que no haya demasiadas faltas de ortogafía; me está costando escribir desde este teclado alemán.

    sábado, mayo 07, 2011

    Parser Combinators: Parsing simple bytecode

    Anteriormente, http://miguelinlas3.blogspot.com/2011/03/parser-combinators-un-poco-de-teoria.html, introducíamos de manera somera el concepto de parser combinators y parte de la teoría relacionada con los mismos. Durante esta entrada vamos a construir un sencillo parser que nos permita analizar un conjunto mínimo de instrucciones de la máquina virtual java (simplemente permitiremos la definición de funciones y la capacidad de ejecución de las mismas).

    No analizaremos en detalle el funcionamiento de la máquina virtual java ni el conjunto de instrucciones  de la misma (podríamos llevarnos algo más que unos cuantos posts :) ) dado que el objetivo principal de esta entrada es profundizar en el concepto de parser combinators y presentar un ejemplo de uso real de los mismos. Pongámonos manos a la obra.

    El código fuente que nos servirá como conductor de la entrada será el de la función factorial mostrado a continuación:

    static int fact(int);
    Code:
    Stack=2, Locals=3, Args_size=1
    0: iconst_1
    1: istore_1
    2: iconst_1
    3: istore_2
    4: iload_2
    5: iload_0
    6: if_icmpgt 19
    9: iload_1
    10: iload_2
    11: imul
    12: istore_1
    13: iinc 2, 1
    16: goto 4
    19: iload_1
    20: ireturn

    Podréis objener el código desensamblado como el mostrado anteriormente mediante el comando javap -v Class donde Class represente un archivo bytecode.

    El proceso de parsing se lleva a cabo mediante el uso de parser combinators (no perdamos de vista el objetivo de nuestra entrada ;) ) y presenta las siguientes características

    1. Para cada una de las diferentes tipos de instrucciones soportadas definimos un parser combinator que es el encargado de parsear este tipo de instrucciones.
    2. Cada uno de los parsers anteriores sabe cómo generar un objeto del tipo correspondiente. Se utiliza una jerarquía de tipos en la que cada una de las instrucciones bytecode soportadas está representada mediante una clase Scala.
    3. El parser global construye un AST (en este caso es un simple lista de objetos) y un conjunto de infraestructura adicional con el objetivo de implementar un intérprete que ejecute la secuencia de instrucciones obtenida (fuera del ámbito de esta entrada podéis echarle un vistazo al código fuente)
    ¿Cómo actúan nuestros diferentes parsers? Analicemos por ejemplo el componente encargado de parsear las instrucciones ISTORE

    lazy val beginInstructionFragment: Parser[Int] = integer <~ ":" ^^ { _.toInt}

    lazy val iStoreBytecode: Parser[List[BytecodeInstruction]] = beginInstructionFragment ~> "istore_" ~ integer ^^ {
        case name ~ value => new IStoreInstruction(name,value)  :: List()
      }

    El parser beginInstructionFragment es el encargado de parsear la primera parte de la instrucción, la que corresponde al lugar que ocupa la instrucción en el array de instrucciones. 

    El segundo parser hace uso del primero y además sabe cómo parsear el texto restante de manera adecuada. En este caso nuestro este analizador es capaz de parsear las instrucciones istore_N donde N representa un número entero positivo cualquiera y devolver un objeto (dentro de una lista) de tipo IStoreInstruction en el que se incluyen el nombre de la instrucción y el entero correspondiente.

    Como seguramente a muchos de los lectores de este post el fragmento de código anterior les suene un poco raro intentaremos analizar las diferentes opciones de combinaciones de parsers disponibles:
    • Si escribimos un parser en el que utilizamos una cadena, como por ejemplo "istore", el resultado es la propia cadena.
    • Podemos utilizar expresiones regulares, como por ejemplo, "[A-Z]".r . En este caso el resultado también sería la propia cadena
    • Si utilizamos el símbolo ~ (composición secuencial) el resultado del proceso de parseo será la combinación de ambos resultados. Por tanto, si A devuelve "X" y B devuelve "true", el resultado de A~B sería  ~("X","true") (el tipo de este resultado sería una case class de tipo ~ . Adicionalmente podemos hacer uso de los operadores <~ y ~> los cuales mantienen los valores a la izquierda y a la derecha respectivamente.
    • Otro elemento de combinación de parsers sería | . En este caso el valor de retorno sería el de aquel parser que pudiera parsear la entrada con éxito.
    • rep(P) o rep(P,separator) retornan una lista de las múltiples ejecuciones de P.
    • opt(P) retorna una instancia de tipo Option.
    Adicionalmente a la combinación de los parsers, necesitaremos un mecanismo que nos permita reescribir la salida de los mismos, en nuestro caso para instanciar los objetos de tipo necesario y configurar nuestro AST. Para ello tendremos que hacer uso del operador de transformación ^^.

    Una definición formar del operador anterior sería: Dado un parser P y una funcion f cualesquiera, una expresión del tipo P^^f implica que para cada resultado R de P el resultado de la expresión global es f(R) 

    En el ejemplo que estamos tratando nuestra función es un simple pattern matching que transforma la case class retornada por nuestra combinación de parsers en un objeto de tipo IStoreInstruction.

    No me ha resultado sencillo ponerlo por escrito y tampoco estoy seguro de que me haya explicado con la mayor claridad posible. Si estáis interesados os recomiendo que clonéis el repositorio alojado en GitHub

    git://github.com/migue/parser-combinators.git

    Hasta pronto!

    viernes, abril 29, 2011

    Nuevo disco de Natch

    El nuevo disco de Natch Scratch, Mejor que el silencio, únicamente puede calificarse como algo ABSOLUTAMENTE INCREÍBLE.

    Una de las canciones que más me gusta:



    Hasta pronto!

    PD: este finde intentaré continuar con el tema de los combinator parsers en Scala

    miércoles, marzo 30, 2011

    Parser Combinators: un poco de teoría

    Puede que en algunas ocasiones os hayais tenido que enfrentar con la necesidad de escribir un pequeño lenguaje que realice una tarea muy concreta (profundizaremos en el tema de los DSLs en un post futuro): como, por ejemplo, procesar determinados archivos de configuración de vuestra aplicación o la definición de interfaces de usuario de manera sencilla.

    Independientemente de las razones por las que estamos desarrollando este componente, necesitaremos un parser que nos ayude a transformar el lenguaje de entrada en una estructura de datos que nuestro programa pueda comprender y procesar. Algunas de las alternativas que se nos plantean son:
    • Escribir nuestro propio parser (conllevaría escribir también el analizador léxico). Si no somos expertos en la materia estaremos enfrentándonos a una tarea relativamente complicada.
    • Utilizar herramientas para la generación de parsers como Antlr,Bison o JavaCC entre otras muchas. En este caso la dificultad estriba en la necesidad de aprender a manejar una nueva herramienta/lenguaje e integrarlo en nuestro desarrollo y ecosistema.
    Durante esta entrada, y posiblemente la siguiente, vamos a presentar un enfoque alternativo a las dos opciones anteriores. En lugar de utilizar un DSL externo como podría ser el ofrecido por Antlr, vamos a utilizar un DSL interno. Dicho DSL estará formado por parser combinators (funciones y operadores definidos en Scala que servirán como base para la construcción de nuestros futuros parsers).

    Siendo originales :), imaginemos que deseamos cosntruir un parser de expresiones aritméticas de números enteros. En primer lugar, definamos la gramática de nuestro lenguaje:

    expr  ::= term {"+" term | "-" term}. 
    term  ::= factor {"*" factor | "/" factor}.
    factor  ::=  integer | "(" expr ")".

    El fragmento de código anterior representa una gramática libre de contexto (no vamos a profundizar en este tema porque tendríamos que escribir miles de posts) que modela nuestro lenguaje de expresiones aritméticas de números enteros. ¿Y ahora?

    Una vez definida la gramática anterior hemos llevado a cabo la tarea más complicada de todas. Si utilizais los parser combinators ofrecidos por Scala tendremos casi todo el trabajo sucio realizado. A modo de ejemplo:

    import scala.util.parsing.combinator._

    class IntegerArithmetics extends JavaTokenParsers {
       def expr: Parser[Any] = term~rep("+"~term | "-"~term)
       def term: Parser[Any] = factor~rep("*"~factor | "/"~factor)
       def factor: Parser[Any] = integer | "("~expr~")"
    }

    Si comparamos el código Scala con la definición en notación EBNF de nuestra gramática observaremos que podríamos inferir nuestro código fuente Scala sin más que realizar una serie de reemplazos en nuestra notación EBNF:
    1. Cada regla se convierte en un método por lo que tendremos que prefijarlas con def.
    2. El tipo de retorno de cada uno de los métodos anteriores es Parser[Any] (veremos en la siguiente entrada que significa esto) por lo que tendremos que cambiar el símbolo "::=" por ":Parser[Any] ="
    3. Insertar el símbolo ~ entre todos los elementos de cada una de las reglas (en la notación EBNF esto es implícito)
    4. La repetición se refleja mediante el uso de rep(...) en lugar de {...}
    5. El punto al final de cada regla no es necesario (podríamos poner ; si lo deseamos)

    Esto no ha sido más que una toma de contacto con el mundo de los parser combinators en Scala. En la siguiente entrada descubriremos cómo realizar construcciones más complejas, formatear la salida de manera que podamos construir las estructuras de datos requeridas para nuestro procesamiento o ejecutar nuestros parsers. 

    Para todo ello diseñaremos y construiremos un pequeño parser que nos permita analizar el bytecode de la máquina virtual una vez desemsamblado (para los más inquietos javap -v ClassFile (sin .class))

    miércoles, febrero 23, 2011

    Introducción a Scala

    El siguiente documento es un pequeño resumen (introductorio) sobre el lenguaje de programación Scala y alguno de sus beneficios. No es nada nuevo que no podáis encontrar en los libros de referencia :) pero a lo mejor a alguien le sirve para dar sus primeros pasos en este genial lenguaje de programación. 

    Espero que os guste:

    lunes, febrero 21, 2011

    DDD, Spring y AspectJ: inyección de depencias (II)

    En la entrada anterior analizabamos el uso de la anotación Configurable y cómo esta nos ayudaba a realizar la inyección de dependencias en nuestro objetos de dominio, ayudándonos de esta manera a realizar nuestro diseño siguiendo una filosofía orientada al dominio (podréis encontrar mucha información, artículos, referencias, ponencias, . . ., relativas a este tema en http://domaindrivendesign.org/).

    Como ya comentamos anteriormente el uso de la anotación Configurable era beneficioso aunque si la clase anotada se instancia un gran número de veces podríamos incurrir en una notable pérdida de rendimiento puesto que la anotación anterior hace uso de la reflectividad. Adicionalmente, indicábamos que  otro de los "problemas" era que nuestro código estaba acoplado a la plataforma, en este caso, Spring. Durante esta entrada plantearemos otro mecanismo de inyección de dependencias en nuestros objetos de dominio: inyección basada en interfaces de dominio.

    Partiendo del ejemplo analizado en el ejemplo anterior, definiremos un nuevo interface PricingStrategyClient que presentará el método setPricingStrategy(PricingyStrategy pricingStrategy) . Todas aquellas entidades de nuestro dominio que necesiten esta funcionalidad deberán implementar el interfaz anterior.

    Hasta el momento no hemos anotado nuestra clase con ningún artefacto adicional (@Configurable) por lo que ahora tendremos que escribir nuestro propio aspecto para inyectar las dependencias en nuestra clase de dominio. Para llevar a cabo este trabajo extenderemos un aspecto abstracto disponible en spring-aspects-3.0.5.jar (los ejemplos de estas entradas están desarrollados con la versión 3.0.5 de Spring) de tipo GenericInterfaceDrivenDependencyInjectionAspect. De manera resumida, este aspecto base determina cuando se crea una nueva instancia (o serializa) de nuestra clase e invoca al método configureBean. Nosotros únicamente deberemos implementar el método configure tal y como se muestra en el siguiente fragmento de código:


    public aspect PricingStrategyDIAspect extends
      GenericInterfaceDrivenDependencyInjectionAspect {
    protected PricingStrategy pricingStrategy;
    public PricingStrategy getPricingStrategy() {
    return pricingStrategy;
    }
    public void setPricingStrategy(PricingStrategy pricingStrategy) {
    this.pricingStrategy = pricingStrategy;
    }
    @Override
    protected void configure(PricingStrategyClient bean) {
    bean.setPricingStrategyClient(pricingStrategy);
    }
    }

    Como último paso de nuestra nueva solución sólo tendremos que definir nuestro nuevo aspecto en el contexto de aplicación:
    <bean id="pricingStrategy" class="com.blogspot.miguelinlas3.springexamples.ddd.domain.strategy.SimplePricingStrategy"/>

    <bean class="com.blogspot.miguelinlas3.springexamples.ddd.domain.interfacedibased.PricingStrategyDIAspect"
    factory-method="aspectOf">
    <property name="pricingStrategy" ref="pricingStrategy"/>
    </bean>
    Una posible mejora sería incluir el aspecto anterior como un aspecto estático dentro del interfaz PricingStrategyClient de modo que estaríamos enfatizando la relación entre ambos aunque esto os lo dejo como ejercicio ;)

    sábado, febrero 19, 2011

    Spring I/O 2011: Hadoop, Cloud y Spring

    Las slides utilizadas en mi presentación del Spring I/O Madrid 2011. Muchas gracias a todos los asistentes (no me imaginaba que fueran a venir tantos :) ) por aguantarme durante una hora.


    A lo largo del finde intentaré hacer un resumen de lo que ha sido  para mi la Spring I/O Madrid 2011.

    ¡De nuevo muchas gracias a todos por asistir a la charla!

    lunes, febrero 14, 2011

    Grupo sobre escalabilidad en español

    El otro día, mientras revisaba alguno de los artículos y libros que tengo a medio leer, me "di cuenta" de que muchas de las cosas que me gustan están relacionadas con temas de programación distribuida, escalabilidad de sistemas y temáticas similares.

    Pues bien, me he movido un poquito por la red y he intercambiado  unos cuantos correos electrónicos con dos auténticos cracks: Martín Pérez y Marc de Palol en los que hemos estado hablando,un poco, sobre la posibilidad de crear un grupo relacionado con temáticas de escalabilidad.

    ¿Qué cosas tendrían cabida en el grupo os estaréis preguntando? Pues me imagino que las inquietudes y conocimientos de todos los participantes irán marcando un poco el devenir del mismo. 

    Nosotros, en un principio (Marc, plagio y añado alguna pincelada a tu correo inicial :) ) habíamos pensado en temas relacionados con la computación distribuida y escalabilidad en general: problemática, soluciones, frameworks, arquitecturas, alternativas, etc utilizados (o que podrían ser utilizados) en el desarrollo software de aquellas aplicaciones en las que  el soporte a millones de usuarios concurrentes, el manejo de cantidades ingentes de datos o los tiempos de respuesta son requisitos altamente importantes.

    La idea del grupo, al menos inicialmente, ya veremos si la cosa evoluciona y cómo evoluciona, no es ceñirse a ninguna tecnología en particular sino tratar los temas anteriores desde una perspectiva un poco más abierta.

    Las tecnologías que podrían aparecer en el grupo, tal y como decía antes, vendrán marcadas por el interés que demuestre la gente por el mismo así como la orientación que se le quiera dar. A modo de "brainstorming" dejo algunas de los temas/tecnologías que, desde mi punto de vista, podrían aparecer:
    • Hadoop y todo su ecosistema: HBase, Hive, Zookeeper, Hive, . . . (aquí iría un largo ecétera : )
    • Modelos de actores: una alternativa "diferente" a la computación distribuida. Aquí habría cabida para hablar largo y tendido: Erlang y OTP, Scala, Akka, . . .
    • Temáticas relacionadas con el cloud (desde un punto de vista de sistemas escalables, no de usuario): ¿cómo se lleva a cabo la elasticidad de recursos en las plataformas PaaS como GAE, Amazon Beanstalk o Heroku? ¿Cuáles son las arquitecturas que utilizan este tipo de sistemas? ¿Qué técnicas utilizan para dar soporte a tantos usuarios y aplicaciones? . . .
    • Movimiento NoSQL: CouchDB, Cassandra, Riak, etc y otras alternativas diferentes como pueden ser las aportadas por plataformas como Greenplum o Vertica.
    • Seguro que muchísimas cosas más . . . .

    ¿Os animáis?

    Martín ha comentado algo en su blog


    lunes, febrero 07, 2011

    DDD, Spring y AspectJ: inyección de depencias (I)

    El paradigma de orentación a objetos promueve que los objetos deberían tener datos y comportamiento. Sin embargo, en la realidad esto no se cumple en muchas ocasiones; especialmente en los objetos de dominio, donde habitualmente las clases se convierten en meros contenedores de información que se van pasando de unas capas a otras, delegando la funcionalidad en capas de servicio externas, creando un modelo anémico (para más información podéis acudir a http://www.martinfowler.com/bliki/AnemicDomainModel.html).

    A lo largo de las siguientes entradas promoveremos el paradigma de diseño dirigido por dominio y analizaremos como podremos enriquecer nuestros objetos de dominio mediante la inyección de dependencias. Para aquellos que estéis familiarizados con las últimas versiones de Spring, estas entradas no serán más que un paseo por los internals de @Configurable (anotación que podemos encontrar las versiones más recientes de este popular framework) unidos a un poco de teoría.

    Imaginemos por un momento que estamos desorrollando una tienda online para la venta de libros electrónicos y que la siguiente clase modela nuestra entidad de dominio libro. Como podemos observar estamos delegando el cálculo del precio del libro en una clase independiente la cual será la encargada de realizar los cálculos necesarios (de este modo podremos configurar el precio del libro en función de nuestras necesidades). Y ahora: ¿cómo llevamos a cabo la inicialización del atributo pricingStrategy ?

    Desde aquí vamos a promover el uso de inyección de dependencias, de manera que añadiendo la infraestructura necesaria (en ese caso un simple setter para el atributo en cuestión) podremos delegar en un contenedor la responsabilidad de inyectar las dependencias necesarias en el momento en el que se instancie nuestro objeto. Siguiendo esta filosofía podríamos intercambiar las estrategias de cálculo de precios sin más que realizar una ligera modificación en la configuración, sin la necesidad de modificar nuestro código fuente. Este enfoque también nos permite llevar a cabo nuestras pruebas unitarias de manera extremadamente sencilla.

    Antes de comenzar a escribir nuestros propios aspectos (lo dejaremos para la próxima entrada) veamos cómo podríamos inyectar las dependencias en nuestro objeto de dominio mediante el uso de spring y un poco de configuración.

    En primer lugar tendremos que indicarle a spring que nuestra clase de dominio Book necesita que sus dependencias sean inyectadas: para ello anotamos la definición de nuestra clase con @Configurable y añadimos un setter para nuestro atributo de clase pricingStrategy. Adicionalmente, anotaremos  el setter anterior (o la propiedad) con @Autowired. Finalmente, definiremos en el contexto de aplicación de spring una implementación concreta del interfaz PricingStrategy e indicamos que estamos haciendo uso @Configurable mediante la instrucción .

    Con la sencilla configuración anterior, cada vez que instanciemos un objeto de la clase Book mediante el operador new: Book book = new Book() el atributo pricingStrategy será inyectado con la referencia adecuada.

    El uso de @Configurable hace uso de la reflectividad por lo que en aquellos objetos que se instancian muy a menudo podríamos incurrir en un serio problema de rendimiento. Adicionalmente, el uso de esta anotación acopla nuestro código a Spring, creando una dependencia hacia el framework.

    En la siguiente entrada analizaremos el uso de interfaces de dominio y escribiremos nuestros propios aspectos como alternativa a la solución presentada a lo largo de esta entrada.


    viernes, enero 28, 2011

    Scala: Clases y objetos

    Durante esta entrada analizaremos algunas de las características básicas del paradigma orientado a objetos presentes en Scala. Pongámonos manos a la obra:

    Del mismo modo que en todos los lenguajes orientados a objetos Scala permite la definición de clases en las que podremos añadir métodos y atributos:

    class MyFirstClass{
      val a = 1
    }

    Si deseamos instanciar un objeto de la clase anterior tendremos que hacer uso de la palabra reservada new


    val v = new MyFirstClass


    En Scala existen dos tipos de variables, vals y vars, que deberemos especificar a la hora de definir las mismas:

    • Se utilizará la palabra reservada val para indicar que es inmutable. Una variable de este tipo es similar al uso de final en Java. Una vez inicializada no se podrá reasignar jamás.
    • De manera contraria, podremos indicar que una variable es de clase var, consiguiendo con esto que su valor pueda ser modificado durante todo su ciclo de vida.

    Uno de los principales mecanismos utilizados que garantizan la robustez de un objeto es la afirmación de que su conjunto de atributos (variables de instancia) permanezca constante a lo largo de todo el ciclo de vida del mismo. El primer paso para evitar que agentes externos tengan acceso a los campos de una clase es declarar los mismos como private. Puesto que los campos privados sólo podrán ser accedidos desde métodos que se encuentran definidos en la misma clase, todo el código podría modificar el estado del mismo estará localizado en dicha clase.

    Por defecto, si no se especifica en el momento de la definición, los atributos y/o métodos, de una clase tienen acceso público. Es decir, public es el cualificador por defecto en Scala

    El siguiente paso será incorporar funcionalidad a nuestras clases; para ello podremos definir métodos mediante el uso de la palabra reservada def:

    class MyFirstClass{
      var a = 1
      def add(b:Byte):Unit={
    a += b
      }
    }


    Una característica importante de los métodos en Scala es que todos los parámetros son inmutables, es decir, vals. Por tanto, si intentamos modificar el valor de un parámetro en el cuerpo de un método obtendremos un error del compilación:

    def addNotCompile(b:Byte) : Unit = {
      b = 1  // Esto no compilará puesto que el 
     // parámetro b es de tipo val
      a += b
    }

    Otro aspecto relevante que podemos apreciar en el código anterior es que no es necesario el uso explícito de la palabra return, Scala retornará el valor de la última expresión que aparece en el cuerpo del método. Adicionalmente, si el cuerpo de la función retorna una única expresión podemos obviar la utilización de las llaves.

    Habitualmente los métodos que presentan un tipo de retorno Unit tienen efectos colaterales, es decir, modifican el estado del objeto sobre el que actúan. Otra forma diferente de llevar a cabo la definición de este tipo de métodos consiste en eliminar el tipo de retorno y el símbolo igual y englobar el cuerpo de la función entre llaves, tal y como se indica a continuación:
    class MyFirstClass {
      private var sum = 0
      def add(b:Byte) { sum += b }
    }

    En la siguiente entrada introduciremos el concepto de singleton objects. También intentaré que la apariencia de las entradas sea un poquito más atractiva utilizando el genial servicio ofrecido por http://pastie.org

    jueves, enero 27, 2011

    Scala: Primeros pasos (cont)

    En la entrada anterior comenzabamos nuestra pequeña aventura en Scala analizando las características principales del paradigma orientado a objetos y revisando alguna de las contribuciones que este lenguaje presenta al modelo. Durante la entrada que nos ocupa revisaremos brevemente los fundamentos del paradigma funcional y analizaremos cómo Scala incorpora y unifica lo mejor de ambos paradigmas en un lenguaje estáticamente tipado.

    La programación funcional es un paradigma en el que se trata la computación como la evaluación de funciones matemáticas y se evitan los programas con estado y datos que puedan ser modificados. Se adopta una visión más matemática del mundo en el que los programas están compuestos por numerosas funciones que esperan una determinada entrada y producen una determinada salida y, en muchas ocasiones, otras funciones.

    Otro de los aspectos de la programación funcional es la ausencia de efectos colaterales gracias a los cuales los programas desarrollados son mucho más sencillos de comprender y probar. Adicionalmente, se facilita la programación concurrente, evitando que se convierta en un problema gracias a la ausencia de cambio.

    Los lenguajes de programación que soportan este estilo de programación deberían ofrecer algunas de las siguientes características:
    • Funciones de primer nivel
    • Closures
    • Asignación simple
    • Evaluación tardía
    • Inferencia de tipos
    • Optimización del tail call
    • Efectos monadic

    Es importante tener claro que Scala no es un lenguaje funcional puro dado que en este tipo de lenguajes no se permiten las modificaciones y las variables se utilizan de manera matemática (un ejemplo de lenguaje funcional puro sería Haskell).

    Durante las dos últimas entradas hemos centrado nuestra atención en algunos de los aspectos más teóricos por lo que posiblemente a los (pocos) que hayáis leído esto se os haya hecho demasiado aburrido.

    Esperemos que la siguiente entrada sea más entretenida.

    martes, enero 18, 2011

    Scala: Primeros pasos

    Me gustaría comenzar una serie de post relativos al lenguaje de programación Scala para que, si alguien se pasa por aquí y tiene interés, pueda dar sus primeros pasos en este fantástico lenguaje. Dejar claro desde el principio que no soy, ni por asomo,  un experto :) , aunque intentaré explicarme con la mayor claridad que me sea posible.


    Para comenzar, un poquito de teoría e historia:

    Scala es un lenguaje de propósito general diseñado para expresar los patrones de programación más comunes de una manera sencilla, elegante y segura. Integra de manera sencilla características de orientación a objetos y lenguajes funcionales, permitiendo de este modo que los desarrolladores puedan ser más productivos. Su creador, Martin Odersky, y su equipo comenzaron el desarrollo de este nuevo lenguaje en el año 2001, en el laboratorio de métodos de programación en EPFL (École Polytechnique Fédérale de Lausanne)

    Scala hizo su aparación pública sobre la plataforma JVM (Java Virtual Machine) en enero de 2004 y unos meses después haría lo propio sobre la plataforma .NET. Aunque se trata de un elemento relativamente novedoso dentro del espacio de los lenguajes de programación, ha adquirido una notable popularidad la cual se acrecenta día tras día.


    Orientación a objetos


    Un lenguaje orientado a objetos "puro" debería presentar las siguientes características:

    Ocultación de información.

    • Herencia.
    • Polimorfismo/Enlace dinámico.
    • Todos los tipos predefinidos son objetos.
    • Todas las operaciones son llevadas a cabo mediante en envío de mensajes a objetos.
    • Todos los tipos definidos por el usuario son objetos.
    • Scala da soporte a todas las características anteriores mediante la utilización de un modelo puro de orientación a objetos muy similar al presentado por Smalltalk (lenguaje creado por Alan Kay sobre el año 1980).

    De manera adicional Scala añade algunas innovaciones en el espacio de los lenguajes orientados a objetos:
    • Composición modular de mixin. Mecanismo que permite la composición de clases para el diseño de componentes reutilizables evitando los problemas presentados por la herencia múltiple. Similar a los interfaces Java y las clases abstractas. Por una parte se pueden definir múltiples "contratos" (del mismo modo que los interfaces). Por otro lado, se podrían tener implementaciones concretas de los métodos.
    • Self-type. Los mixin no dependen de ningún método y/o atributo de aquellas clases con las que se está entremezclando aunque en determinadas ocasiones será necesario hacer uso de las mismas. Esta capacidad es conocida en Scala como self-type
    • Se ha optado por mantener el término original disponible en la documentación del lenguaje.
    • Abstracción de tipos. Existen dos mecanismos principales de abstracción en los lenguajes de programación: la parametrización y los miembros abstractos. Scala soporta ambos estilos de abstracción de manera uniforme para tipos y valores
    Vamos a dejar la entrada en este punto para no convertirla en un ladrillo (más aun de lo que ya  es) y en el próximo post analizaremos, de manera general, las características generales del paradigma funcional.