• Shortcuts : 'n' next unread feed - 'p' previous unread feed • Styles : 1 2

» Publishers, Monetize your RSS feeds with FeedShow:  More infos  (Show/Hide Ads)


Date: Tuesday, 07 Oct 2014 11:58
imageCuando los lenguajes evolucionan, no todas las novedades son espectaculares ni revolucionan la forma de escribir nuestro código. A veces la cosa va simplemente de añadir pequeños detalles que nos hacen la vida más fácil y ayudan a evitar errores.

Y hoy hablaremos de uno de ellos: el nuevo operador nameof, que acompañará a C# a partir de su versión 6.

Imaginad un escenario que podría ser bastante frecuente, como el siguiente:



Observad que mediante el uso de las constantes "firstString"  y "secondString" estamos introduciendo una dependencia en nuestro código entre dos elementos que viven en mundos diferentes, como son el nombre de una variable a nivel de código y la cadena que representa el nombre de dicho parámetro en tiempo de ejecución.

El problema que tiene esto es que si más adelante decidimos refactorizar y modificar el nombre de los parámetros, muy probablemente olvidaremos modificar estas cadenas de texto, por lo que la excepción no mostrará información correcta sobre el error.

Para solucionar este escenario, C# 6 incluirá el operador nameof que, como se puede intuir, nos ayudará a conocer en tiempo de ejecución el nombre de una variable o miembro tal y como ha sido definida en la codificación. El ejemplo más sencillo que podemos ver es el siguiente:



¡Voila! Como sabréis, conseguir algo similar sin un operador como el que nos regala la nueva versión de C# sería bastante más complejo y farragoso. El operador nameof simplemente retornará en forma de cadena de texto el nombre de la variable que le indiquemos.

Volviendo al primer ejemplo, ahora podemos escribir el mismo método, pero asegurando que la información de ayuda de la excepción siempre incluirá el valor correcto, a prueba de refactorizaciones:



Pero no sólo de variables locales y parámetros se alimenta el operador nameof ;-) En realidad  podemos pasarle casi cualquier cosa, y su comportamiento será siempre el esperado:



Aunque hay otros usos que no son tan intuitivos. Por ejemplo, para referenciar miembros de instancia hay que hacerlo como si fueran miembros estáticos de la clase donde residen:



Además de para facilitar el trazado de errores, hay muchos otros escenarios en los que este nuevo operador podría ayudarnos a cometer menos errores. Así a bote pronto, se me ocurre que en MVC podría ser una vía sencilla para evitar las constantes de cadena si quisiéramos añadir errores al ModelState de un controlador (cosa que, por otra parte, no es especialmente recomendable):



También sería de utilidad, por ejemplo, si quisiéramos implementar un interfaz  INotifyPropertyChanged o cualquier otro que requiera conocer el nombre del miembro actual. De nuevo, simplemente haciendo uso de nameof podremos averiguar con facilidad el nombre de la propiedad que cambió para pasarlo al evento oportuno.

En definitiva, una pequeña incorporación al lenguaje que puede resultar utilísima en esos escenarios en los que debemos referenciar mediante una cadena de texto el nombre de elementos definidos a nivel de código.

Por último, recordaros que C# 6 traerá muchas otras novedades. Si queréis conocerlas, no os perdáis los posts anteriores de la serie:
Publicado en Variable not found.
Author: "noreply@blogger.com (José M. Aguilar)"
Send by mail Print  Save  Delicious 
Date: Monday, 06 Oct 2014 11:45
Enlaces interesantesAhí van los enlaces recopilados durante la semana pasada, espero que os resulten interesantes ;-)

.Net

ASP.NET

Data access

Html/Css/Javascript

Visual Studio/Complementos/Herramientas

Cross-platform

Otros

Publicado en Variable not found
Author: "noreply@blogger.com (José M. Aguilar)"
Send by mail Print  Save  Delicious 
Date: Sunday, 05 Oct 2014 11:54
C#Seguimos comentando novedades que encontraremos en la próxima versión de C#, y en esta ocasión vamos a ver una nueva característica que, sin resultar espectacular, sí nos va a proporcionar una fórmula más cómoda y concisa para resolver algunos escenarios bastante habituales.

Seguro que os resulta familiar el siguiente código, más que nada porque lo habréis escrito decenas o cientos de veces:


Personalmente, la introducción de parámetros out en las llamadas siempre me resulta incómodo porque me hace volver atrás para declarar una variable expresamente para la ocasión. Y hay otros casos en los que la sensación de vuelta atrás es igualmente molesta.

Pues la respuesta de C# a este frecuente escenario, y como veremos enseguida a otros más, son las llamadas declaration expressions, que vendrá a traducirse como expresiones de declaración o algo así. Esta nueva característica permite introducir declaraciones de variables en el interior de expresiones, por lo que el ejemplo anterior podría implementarse de forma más concisa:



Como podréis observar, hemos introducido la declaración de la variable en línea, justo en el lugar en el que la vamos a necesitar, lo que nos ahorra esa molesta vuelta atrás para declararla.

Veamos otro ejemplo. Esta vez vamos a utilizar una expresión declarativa con un parámetro ref que inicializamos también sobre la marcha:



¿Interesante, verdad? Pues veamos otro ejemplo bastante frecuente: el uso de variables para almacenar temporalmente el resultado de una expresión que necesitamos reutilizar más adelante. Seguro que no son pocas las veces que os encontráis con un escenario como el siguiente:



Por supuesto, a nadie se le ocurriría dejar ese código así; lo normal sería utilizar su equivalente más legible y eficiente:

image

Pues bien, usando la declaración en expresiones podríamos obtener un código como el siguiente:

image

Con esto, además de no tener que volver atrás para declarar la variable cuando estamos escribiendo el if, habremos conseguido en efecto colateral bastante interesante: no polucionar el bloque de código en el que nos encontramos con variables que sólo tienen sentido en un ámbito interior.

Es decir, en el nuevo C# la declaración de una variable en una expresión dará a ésta visibilidad únicamente en el interior del bloque de código en el que la utilizamos. Volviendo al ejemplo anterior, la variable index sólo será visible dentro del if, que es precisamente donde la necesitamos.

Como ya habréis adivinado, podemos utilizar este tipo de expresiones en cualquier punto de nuestro código: prácticamente, en todos los lugares en los que podamos introducir expresiones, podremos declarar variables. Esto quiere decir que también tendremos capacidad de usar esta característica desde el lado oscuro de la legibilidad:



Una última observación. Habréis notado que no es necesario indicar explícitamente el tipo de dato cuando declaramos variables de esta forma. Siempre que la inferencia de tipos tenga información para hacer bien su trabajo podremos usar var, mientras que en otras ocasiones tendremos que ser más explícitos. Vaya, que será exactamente igual que cuando declaramos variables de la forma tradicional.

En definitiva, creo que es una incorporación interesante al lenguaje que agilizará la codificación en esos escenarios tan frecuentes y, como efecto colateral, nos ayudará a que el ámbito de las variables sea más cercano a su punto de utilización. Pero como todo, úsese con sentido común ;-)

Y si queréis conocer más sobre el C# que se avecina, no os perdáis los posts anteriores de la serie:
Publicado en Variable not found.
Author: "noreply@blogger.com (José M. Aguilar)"
Send by mail Print  Save  Delicious 
Date: Sunday, 05 Oct 2014 11:54
En posts anteriores hemos hablado del operador de navegación segura “.?” y de la inicialización de propiedades automáticas, y vamos a comentar ahora otra de las novedades de la versión de C# que viene en camino, pero que en esta ocasión no tengo claro que sea un avance en la dirección correcta. Os lo cuento y ya decidís vosotros ;-)

Hay escenarios en los que en el interior de una clase utilizamos de forma intensiva miembros estáticos de otras clases. Un ejemplo habitual podemos encontrarlo en componentes que hagan mucho uso de System.Math para la realización de cálculos matemáticos, o incluso en el conocido System.Console:




Pues bien, en C# 6 podremos indicar mediante un using que vamos a realizar llamadas a miembros estáticos de la clase que indiquemos, por lo que no será necesario especificarla en cada llamada:



Internamente, cuando el compilador encuentra esas llamadas a WriteLine() o ReadLine(), determinará que pertenecen al objeto System.Console porque no existe ningún otro candidato más apropiado que las implemente. Si la propia clase Program dispusiera de un método estático WriteLine(), se habría utilizado éste.

También se tienen en cuenta casos en los que la llamada pudiera resultar ambigua para evitar. Por ejemplo, si estamos haciendo un using de dos clases que implementan un método estático con el mismo nombre y signatura, el compilador se quejará y tendremos que referenciarlas de forma explícita, como hemos hecho hasta ahora.

Ciertamente usando esta característica podemos ahorrar muchas pulsaciones de teclas, así como hacer más claro nuestro código… ¿o no? El problema lo veo justamente ahí: en la claridad. Aunque visualmente el código resulta menos denso y más fácil de leer, estamos incluyendo un cierto grado de “ofuscación” (por llamarlo de alguna forma) que puede complicar la comprensión de lo que se hace o dónde se hace. Por ejemplo, fijaos en las llamadas que se realizan desde el siguiente método:



Podemos ver que usamos muchos métodos matemáticos y por tanto sería un caso de uso de esta nueva característica del lenguaje, pero en un vistazo no se sabríamos quién los está implementando. En versiones de C# anteriores a la 6, podríamos asegurar que Sinh(), Pow(), Sqr() o Floor() son miembros de la clase actual o algunas de sus antecesoras, pero en la nueva versión un using System.Math al principio del archivo podría invalidar esta afirmación.

De hecho, ni aún existiendo ese  using System.Math  podríamos estar seguros de dónde se encuentra definido un método, porque podríamos tener una implementación local a la clase del mismo que sería la utilizada aunque a nivel de código no quede explícitamente indicado. Y también puede dar lugar a confusiones casos como la llamada a Sqr() del código anterior porque, aunque parezca lo contrario, no existe en System.Math (el método que realmente existe es  Sqrt()).

En fin, supongo que ocurre como con muchas otras características del lenguaje, que no son de por sí buenas ni malas: todo depende del uso que se les dé. Probablemente hacer un uso razonable de esta característica en un contexto concreto y acotado podría ser útil para ahorrarnos trabajo, pero no tengo claro si el coste en términos de legibilidad compensará en muchos casos.

Ya con el tiempo, cuando vea cómo se utiliza y los problemas que crea en proyectos reales igual cambio de idea, pero de momento pienso que se podían haber ahorrado el esfuerzo.

Publicado en Variable not found.
Author: "noreply@blogger.com (José M. Aguilar)"
Send by mail Print  Save  Delicious 
Date: Sunday, 05 Oct 2014 11:54
Novedades de C# 6.0Hace algún tiempo comentamos alguna de las novedades que se incluirán en la próxima versión de C#, concretamente el nuevo operador de navegación segura “?.”, pero la cosa no acaba aquí: se avecinan un buen número de cambios que prometen seguir mejorando nuestro lenguaje favorito :-)

Por ejemplo, una nueva característica que tendremos disponible es la inicialización de propiedades automáticas, algo que antes también podíamos hacer, aunque de forma menos directa.


Es decir, hasta el momento para inicializar una propiedad automática teníamos que hacerlo en el constructor de la clase, como sigue:



Pues bien, en la nueva versión podremos usar una nueva construcción mucho más directa:



Simplemente añadimos la expresión de igualdad tras la declaración, y listo. Además del obvio ahorro en pulsaciones de teclas, el resultado a nivel de código es más expresivo y legible, puesto que mantiene unida la definición de la propiedad con su valor inicial.

Los valores usados en la inicialización son los que podríamos suponer de forma intuitiva: constantes, miembros estáticos o llamadas a métodos estáticos, nada de referencias a this o a otros miembros de instancia de la clase. Vaya, igual que en la inicialización de miembros privados de la clase de toda la vida.

Y como era de esperar, la inicialización se producirá antes de que la ejecución pase por el constructor, por lo que en ese punto ya tendremos los valores cargados si los necesitamos para algo:



Por supuesto, es algo que también podemos utilizar con propiedades en las que el setter es privado, puesto que la inicialización es interna a la clase:



E incluso hace posible el uso de propiedades automáticas de sólo lectura, algo que antes sólo podíamos conseguir usando propiedades con backing fields:



En fin, que sin ser un cambio espectacular, se trata de uno de esos pequeños detalles que nos hará la vida algo más fácil cuando aterricen las nuevas versiones de todo que se están cocinando.

Publicado en Variable not found.
Author: "noreply@blogger.com (José M. Aguilar)"
Send by mail Print  Save  Delicious 
Date: Sunday, 05 Oct 2014 01:30
Java

En algunas web las urls incluyen el identificativo del objeto de la base de datos a partir de cual se muestra el contenido principal de la página, en Blog Stack esto podría ser un artículo. Esto genera urls «feas» de cara al usuario y al SEO de los buscadores además de exponer cierta información de la base de datos que probablemente no interese a nadie excepto al desarrollador de la página. En este artículo voy a explicar una forma de generar urls semánticas o «bonitas» de cara al usuario y al SEO para los buscadores y como lo he implementado en un ejemplo real como es Blog Stack.

Lo primero que debemos conseguir es que las urls sean únicas para cualquier página de la web, por tanto, en la url deberemos incluir tanta información como sea necesaria pero al mismo tiempo la mínima para hacerlas únicas y que nos permitan identificar de forma unequívoca el contenido a mostrar o el objeto que nos permite obtener la información a visualizar en la página, esta información formará el denominado slug. En el caso de Blog Stack las urls «bonitas» se emplean en este momento en dos sitios, para los artículos y para las etiquetas. La información mínima para un artículo es el nombre de la fuente, el año, el mes y el título, para las etiquetas es simplemente el nombre de la etiqueta. Este es un desglose de las partes que forman una url.

<noscript><pre><code>http://www.blogstack.info/post/blogbitix/2013/12/hola-nuevo-mundo/ ^ ^ ^ ^ ^ ^ Dominio Página Año Artículo Bitácora Mes </code></pre></noscript>

Pero eso no es todo además quizá queramos transliterar los caracteres de forma que las urls no tengan ciertos caracteres propios de cada idioma. La solución simple pero poco efectiva es hacer una serie de sustituciones como por ejemplo reemplazar á por a, ñ por n, etc… Esta solución aparte de tener que hacerla nosotros probablemente no seamos ni siquiera conscientes que deberíamos haber reemplazado algún carácter más, se complica más si hemos de hacer lo mismo con el resto de codificaciones de la que ni siquiera conocemos los caracteres. Una solución mejor es utilizar el comando iconv disponible en linux que hace precisamente lo que buscamos:

<noscript><pre><code>$ echo &quot;áéíóú&quot; | iconv -f UTF-8 -t ASCII//TRANSLIT aeiou</code></pre></noscript>

Para que la url sea más fácilmente legible es recomendable convertir las mayúsculas a minúsculas y sustituir los caracteres de espacio por un guión (–). En Blog Stack suponiendo un artículo de la fuente blogbitix publicado en diciembre de 2013 y de título «¡Hola nuevo mundo!» partiríamos de la siguiente url previamente a aplicar la transliteración de caracteres:

<noscript><pre><code>/blogbitix/2013/12/¡Hola nuevo mundo!</code></pre></noscript>

Convertida a minúsculas:

<noscript><pre><code>/blogbitix/2013/12/¡hola nuevo mundo!</code></pre></noscript>

Transliterada con iconv a ASCII:

<noscript><pre><code>/blogbitix/2013/12/?hola nuevo mundo!</code></pre></noscript>

Y finalmente sustituidos cualquier carácter que no esté entre en la siguiente expresión regular [^a-z1-9-] para eliminar por ejemplo signos de puntuación, múltiples guiones seguidos y si el resultado empieza o acaba por guión eliminándolo, al final tenemos el slug o parte de la url final a la que deberíamos añadir el protocolo y el dominio:

<noscript><pre><code>/blogbitix/2013/12/hola-nuevo-mundo</code></pre></noscript>

Todo esto en código java se traduce en:

<noscript><pre><code>package info.blogstack.misc; ... public class Utils { ... public static Object[] getContext(Post post) { String f = post.getSource().getAlias(); String y = String.valueOf(post.getConsolidatedPublishDate().getYear()); String m = StringUtils.leftPad(String.valueOf(post.getConsolidatedPublishDate().getMonthOfYear()), 2, &quot;0&quot;); String e = Utils.urlize(post.getTitle()); return new Object[] { f, y, m, e }; } public static Object[] getContext(Label label) { String l = Utils.urlize(label.getName()); return new Object[] { l }; } public static String urlize(String text) { return Utils.trasnliterate(text.toLowerCase()).replaceAll(&quot;[^a-z1-9-]&quot;, &quot;-&quot;).replaceAll(&quot;-+&quot;, &quot;-&quot;).replaceAll(&quot;^-+&quot;, &quot;&quot;).replaceAll(&quot;-+$&quot;, &quot;&quot;); } public static String trasnliterate(String s) { try { Process p = Runtime.getRuntime().exec(&quot;iconv -f UTF-8 -t ASCII//TRANSLIT&quot;); Writer w = new OutputStreamWriter(p.getOutputStream()); Reader r = new InputStreamReader(p.getInputStream()); IOUtils.copy(new StringReader(s), w); w.close(); Writer sw = new StringWriter(); IOUtils.copy(r, sw); r.close(); return sw.toString(); } catch (IOException e) { throw new RuntimeException(e); } } ... }</code></pre></noscript>

Pero ¿si el identificativo del artículo no está en la url como lo asociamos con el artículo? Nos queda proporcionar una solución a esta necesidad de como identificar esa url semántica y más amigable con el objeto del artículo guardado en la base de datos para mostrarlo al visualizar la página solicitada.

La idea para asociar la url con un objeto de base de datos es crear un hash de la url y tenerlo precalculado en la base de datos, con el hash que generamos a partir de la url y su slug cuando recibimos la petición buscamos el objeto que en la base de datos tenga ese hash. ¿Por qué guardar el hash y no el slug? Un motivo es porque el hash tiene una longitud constante, probablemente mas corto que el slug además de mayor dispersión en el valor del dato que usando un índice de base de datos es beneficioso en la búsqueda. Si la url es única podemos suponer que el hash será único. Si en un futuro cambiásemos la información del slug para calcular el hash lógicamente deberíamos recalcular todos los hashs. Para calcular el hash podemos usar la función MD5 o SHA con el siguiente código en java.

<noscript><pre><code>package info.blogstack.misc; ... public class Utils { public static String getHash(Post post) { return Utils.getHash(Utils.getContext(post)); } public static String getHash(Object[] context) { try { String[] s = new String[context.length]; for (int i = 0; i &lt; s.length; ++i) { s[i] = &quot;%s&quot;; } String ss = String.format(StringUtils.join(s, &quot;/&quot;), context); byte[] h = MessageDigest.getInstance(&quot;MD5&quot;).digest(ss.getBytes()); return Base64.encodeBase64String(h); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } } ... public static Object[] getContext(Post post) { String f = post.getSource().getAlias(); String y = String.valueOf(post.getConsolidatedPublishDate().getYear()); String m = StringUtils.leftPad(String.valueOf(post.getConsolidatedPublishDate().getMonthOfYear()), 2, &quot;0&quot;); String e = Utils.urlize(post.getTitle()); return new Object[] { f, y, m, e }; } ... }</code></pre></noscript>

Esta solo es una forma de crear las urls pero suficiente para el propósito de Blog Stack. Quizá en otro caso podríamos querer generar urls caracteres que no solo sean ASCII o incluyan los propios de otra codificación como por ejemplo caracteres cirílicos, chinos o japoneses. También en vez de incluir en la url la referencia a un solo objeto con el slug incluir los slugs de varios objetos, sin esta solución deberíamos incluir un segundo identificativo de la base de datos y las urls serán aún más feas, menos amigables y peores en cuanto a SEO.

El código fuente completo de la clase Utils.java lo puedes encontrar en el repositorio de GitHub de Blog Stack.

Author: "--"
Send by mail Print  Save  Delicious 
Date: Sunday, 05 Oct 2014 01:30
Java

En algunas web las urls incluyen el identificativo del objeto de la base de datos a partir de cual se muestra el contenido principal de la página, en Blog Stack esto podría ser un artículo. Esto genera urls «feas» de cara al usuario y al SEO de los buscadores además de exponer cierta información de la base de datos que probablemente no interese a nadie excepto al desarrollador de la página. En este artículo voy a explicar una forma de generar urls semánticas, «bonitas» o amigables de cara al usuario y al SEO para los buscadores y como lo he implementado en un ejemplo real como es Blog Stack.

Lo primero que debemos conseguir es que las urls sean únicas para cualquier página de la web, por tanto, en la url deberemos incluir tanta información como sea necesaria pero al mismo tiempo la mínima para hacerlas únicas y que nos permitan identificar de forma unequívoca el contenido a mostrar o el objeto que nos permite obtener la información a visualizar en la página, esta información formará el denominado slug. En el caso de Blog Stack las urls «bonitas» se emplean en este momento en dos sitios, para los artículos y para las etiquetas. La información mínima para un artículo es el nombre de la fuente, el año, el mes y el título, para las etiquetas es simplemente el nombre de la etiqueta. Este es un desglose de las partes que forman una url.

<noscript><pre><code>http://www.blogstack.info/post/blogbitix/2013/12/hola-nuevo-mundo/ ^ ^ ^ ^ ^ ^ Dominio Página Año Artículo Bitácora Mes </code></pre></noscript>

Pero eso no es todo además quizá queramos transliterar los caracteres de forma que las urls no tengan ciertos caracteres propios de cada idioma. La solución simple pero poco efectiva es hacer una serie de sustituciones como por ejemplo reemplazar á por a, ñ por n, etc… Esta solución aparte de tener que hacerla nosotros probablemente no seamos ni siquiera conscientes que deberíamos haber reemplazado algún carácter más, se complica más si hemos de hacer lo mismo con el resto de codificaciones de la que ni siquiera conocemos los caracteres. Una solución mejor es utilizar el comando iconv disponible en linux que hace precisamente lo que buscamos:

<noscript><pre><code>$ echo &quot;áéíóú&quot; | iconv -f UTF-8 -t ASCII//TRANSLIT aeiou</code></pre></noscript>

Para que la url sea más fácilmente legible es recomendable convertir las mayúsculas a minúsculas y sustituir los caracteres de espacio por un guión (–). En Blog Stack suponiendo un artículo de la fuente blogbitix publicado en diciembre de 2013 y de título «¡Hola nuevo mundo!» partiríamos de la siguiente url previamente a aplicar la transliteración de caracteres:

<noscript><pre><code>/blogbitix/2013/12/¡Hola nuevo mundo!</code></pre></noscript>

Convertida a minúsculas:

<noscript><pre><code>/blogbitix/2013/12/¡hola nuevo mundo!</code></pre></noscript>

Transliterada con iconv a ASCII:

<noscript><pre><code>/blogbitix/2013/12/?hola nuevo mundo!</code></pre></noscript>

Y finalmente sustituidos cualquier carácter que no esté entre en la siguiente expresión regular [^a-z1-9-] para eliminar por ejemplo signos de puntuación, múltiples guiones seguidos y si el resultado empieza o acaba por guión eliminándolo, al final tenemos el slug o parte de la url final a la que deberíamos añadir el protocolo y el dominio:

<noscript><pre><code>/blogbitix/2013/12/hola-nuevo-mundo</code></pre></noscript>

Todo esto en código java se traduce en:

<noscript><pre><code>package info.blogstack.misc; ... public class Utils { ... public static Object[] getContext(Post post) { String f = post.getSource().getAlias(); String y = String.valueOf(post.getConsolidatedPublishDate().getYear()); String m = StringUtils.leftPad(String.valueOf(post.getConsolidatedPublishDate().getMonthOfYear()), 2, &quot;0&quot;); String e = Utils.urlize(post.getTitle()); return new Object[] { f, y, m, e }; } public static Object[] getContext(Label label) { String l = Utils.urlize(label.getName()); return new Object[] { l }; } public static String urlize(String text) { return Utils.trasnliterate(text.toLowerCase()).replaceAll(&quot;[^a-z1-9-]&quot;, &quot;-&quot;).replaceAll(&quot;-+&quot;, &quot;-&quot;).replaceAll(&quot;^-+&quot;, &quot;&quot;).replaceAll(&quot;-+$&quot;, &quot;&quot;); } public static String trasnliterate(String s) { try { Process p = Runtime.getRuntime().exec(&quot;iconv -f UTF-8 -t ASCII//TRANSLIT&quot;); Writer w = new OutputStreamWriter(p.getOutputStream()); Reader r = new InputStreamReader(p.getInputStream()); IOUtils.copy(new StringReader(s), w); w.close(); Writer sw = new StringWriter(); IOUtils.copy(r, sw); r.close(); return sw.toString(); } catch (IOException e) { throw new RuntimeException(e); } } ... }</code></pre></noscript>

Pero ¿si el identificativo del artículo no está en la url como lo asociamos con el artículo? Nos queda proporcionar una solución a esta necesidad de como identificar esa url semántica y más amigable con el objeto del artículo guardado en la base de datos para mostrarlo al visualizar la página solicitada.

La idea para asociar la url con un objeto de base de datos es crear un hash de la url y tenerlo precalculado en la base de datos, con el hash que generamos a partir de la url y su slug cuando recibimos la petición buscamos el objeto que en la base de datos tenga ese hash. ¿Por qué guardar el hash y no el slug? Un motivo es porque el hash tiene una longitud constante, probablemente mas corto que el slug además de mayor dispersión en el valor del dato que usando un índice de base de datos es beneficioso en la búsqueda. Si la url es única podemos suponer que el hash será único. Si en un futuro cambiásemos la información del slug para calcular el hash lógicamente deberíamos recalcular todos los hashs. Para calcular el hash podemos usar la función MD5 o SHA con el siguiente código en java.

<noscript><pre><code>package info.blogstack.misc; ... public class Utils { public static String getHash(Post post) { return Utils.getHash(Utils.getContext(post)); } public static String getHash(Object[] context) { try { String[] s = new String[context.length]; for (int i = 0; i &lt; s.length; ++i) { s[i] = &quot;%s&quot;; } String ss = String.format(StringUtils.join(s, &quot;/&quot;), context); byte[] h = MessageDigest.getInstance(&quot;MD5&quot;).digest(ss.getBytes()); return Base64.encodeBase64String(h); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } } ... public static Object[] getContext(Post post) { String f = post.getSource().getAlias(); String y = String.valueOf(post.getConsolidatedPublishDate().getYear()); String m = StringUtils.leftPad(String.valueOf(post.getConsolidatedPublishDate().getMonthOfYear()), 2, &quot;0&quot;); String e = Utils.urlize(post.getTitle()); return new Object[] { f, y, m, e }; } ... }</code></pre></noscript>

Esta solo es una forma de crear las urls pero suficiente para el propósito de Blog Stack. Quizá en otro caso podríamos querer generar urls caracteres que no solo sean ASCII o incluyan los propios de otra codificación como por ejemplo caracteres cirílicos, chinos o japoneses. También en vez de incluir en la url la referencia a un solo objeto con el slug incluir los slugs de varios objetos, sin esta solución deberíamos incluir un segundo identificativo de la base de datos y las urls serán aún más feas, menos amigables y peores en cuanto a SEO.

El código fuente completo de la clase Utils.java lo puedes encontrar en el repositorio de GitHub de Blog Stack.

Author: "--"
Send by mail Print  Save  Delicious 
Date: Friday, 03 Oct 2014 18:14
Java

En algunas web las urls incluyen el identificativo del objeto de la base de datos a partir de cual se muestra el contenido principal de la página, en Blog Stack esto podría ser un artículo. Esto genera urls «feas» de cara al usuario y al SEO de los buscadores además de exponer cierta información de la base de datos que probablemente no interese a nadie excepto al autor de la página. En este artículo voy a explicar una forma de generar urls semánticas o «bonitas» de cara al usuario y al SEO para los buscadores y como lo he implementado en un ejemplo real como es Blog Stack.

Lo primero que debemos conseguir es que las urls sean únicas para cualquier página de la web, por tanto, en la url deberemos incluir tanta información como sea necesaria pero al mismo tiempo la mínima para hacerlas únicas y que nos permitan identificar de forma unequívoca el contenido a mostrar o el objeto que nos permite obtener la información a visualizar en la página, esta información formará el denominado «slug». En el caso de Blog Stack las urls «bonitas» se emplean en este momento en dos sitios, para los artículos y para las etiquetas. La información mínima para un artículo es el nombre de la fuente, el año, el mes y el título, para las etiquetas es simplemente el nombre de la etiqueta. Este es un desglose de las partes que forman una url.

<noscript><pre><code>http://www.blogstack.info/post/blogbitix/2013/12/hola-nuevo-mundo/ ^ ^ ^ ^ ^ ^ Dominio Página Año Artículo Bitácora Mes </code></pre></noscript>

Pero eso no es todo además quizá queramos transliterar los caracteres de forma que las urls no tengan ciertos caracteres propios de cada idioma. La solución simple pero poco efectiva es hacer una serie de sustituciones como por ejemplo reemplazar á por a, ñ por n, etc… Esta solución aparte de tener que hacerla nosotros probablemente no seamos ni siquiera conscientes que deberíamos haber reemplazado algún carácter más, se complica más si hemos de hacer lo mismo con el resto de codificaciones de la que ni siquiera conocemos los caracteres. Una solución mejor es utilizar el comando iconv disponible en linux que hace precisamente lo que buscamos:

<noscript><pre><code>$ echo &quot;áéíóú&quot; | iconv -f UTF-8 -t ASCII//TRANSLIT aeiou</code></pre></noscript>

Para que la url sea más fácilmente legible es recomendable convertir las mayúsculas a minúsculas y sustituir los caracteres de espacio por un guión (–). En Blog Stack suponiendo un artículo de la fuente blogbitix publicado en diciembre de 2013 y de título «¡Hola nuevo mundo!» partiríamos de la siguiente url previamente a aplicar la transliteración de caracteres:

<noscript><pre><code>/blogbitix/2013/12/¡Hola nuevo mundo!</code></pre></noscript>

Convertida a minúsculas:

<noscript><pre><code>/blogbitix/2013/12/¡hola nuevo mundo!</code></pre></noscript>

Transliterada con iconv a ASCII:

<noscript><pre><code>/blogbitix/2013/12/?hola nuevo mundo!</code></pre></noscript>

Y finalmente sustituidos cualquier carácter que no esté entre en la siguiente expresión regular [^a-z1-9-] para eliminar por ejemplo signos de puntuación, múltiples guiones seguidos y si el resultado empieza o acaba por guión eliminándolo, al final tenemos el «slug» o parte de la url final a la que deberíamos añadir el protocolo y el dominio:

<noscript><pre><code>/blogbitix/2013/12/hola-nuevo-mundo</code></pre></noscript>

Todo esto en código java se traduce en:

<noscript><pre><code>package info.blogstack.misc; ... public class Utils { ... public static Object[] getContext(Post post) { String f = post.getSource().getAlias(); String y = String.valueOf(post.getConsolidatedPublishDate().getYear()); String m = StringUtils.leftPad(String.valueOf(post.getConsolidatedPublishDate().getMonthOfYear()), 2, &quot;0&quot;); String e = Utils.urlize(post.getTitle()); return new Object[] { f, y, m, e }; } public static Object[] getContext(Label label) { String l = Utils.urlize(label.getName()); return new Object[] { l }; } public static String urlize(String text) { return Utils.trasnliterate(text.toLowerCase()).replaceAll(&quot;[^a-z1-9-]&quot;, &quot;-&quot;).replaceAll(&quot;-+&quot;, &quot;-&quot;).replaceAll(&quot;^-+&quot;, &quot;&quot;).replaceAll(&quot;-+$&quot;, &quot;&quot;); } public static String trasnliterate(String s) { try { Process p = Runtime.getRuntime().exec(&quot;iconv -f UTF-8 -t ASCII//TRANSLIT&quot;); Writer w = new OutputStreamWriter(p.getOutputStream()); Reader r = new InputStreamReader(p.getInputStream()); IOUtils.copy(new StringReader(s), w); w.close(); Writer sw = new StringWriter(); IOUtils.copy(r, sw); r.close(); return sw.toString(); } catch (IOException e) { throw new RuntimeException(e); } } ... }</code></pre></noscript>

Pero ¿si el identificativo del artículo no está en la url como lo asociamos con el artículo? Nos queda proporcionar una solución a esta necesidad de como identificar esa url semántica y más amigable con el objeto del artículo guardado en la base de datos para mostrarlo al visualizar la página solicitada.

La idea para asociar la url con un objeto de base de datos es crear un hash de la url y tenerlo precalculado en la base de datos, con el hash que generamos a partir de la url y su «slug» cuando recibimos la petición buscamos el objeto que en la base de datos tenga ese hash. ¿Por qué guardar el hash y no el «slug»? Un motivo es porque el hash tiene una longitud constante, probablemente mas corto que el «slug» además de mayor dispersión en el valor del dato que usando un índice de base de datos es beneficioso en la búsqueda. Si la url es única podemos suponer que el hash será único. Si en un futuro cambiásemos la información del «slug» para calcular el hash lógicamente deberíamos recalcular todos los hashes. Para calcular el hash podemos usar la función MD5 o SHA con el siguiente código en java.

<noscript><pre><code>package info.blogstack.misc; ... public class Utils { public static String getHash(Post post) { return Utils.getHash(Utils.getContext(post)); } public static String getHash(Object[] context) { try { String[] s = new String[context.length]; for (int i = 0; i &lt; s.length; ++i) { s[i] = &quot;%s&quot;; } String ss = String.format(StringUtils.join(s, &quot;/&quot;), context); byte[] h = MessageDigest.getInstance(&quot;MD5&quot;).digest(ss.getBytes()); return Base64.encodeBase64String(h); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } } ... public static Object[] getContext(Post post) { String f = post.getSource().getAlias(); String y = String.valueOf(post.getConsolidatedPublishDate().getYear()); String m = StringUtils.leftPad(String.valueOf(post.getConsolidatedPublishDate().getMonthOfYear()), 2, &quot;0&quot;); String e = Utils.urlize(post.getTitle()); return new Object[] { f, y, m, e }; } ... }</code></pre></noscript>

Esta solo es una forma de crear las urls pero suficiente para el propósito de Blog Stack. Quizá en otro caso podríamos querer generar urls caracteres que no solo sean ASCII o incluyan los propios de otra codificación como por ejemplo caracteres cirílicos, chinos o japoneses. También en vez de incluir en la url la referencia a un solo objeto con el «slug» incluir los «slugs» de varios objetos, sin esta solución deberíamos incluir un segundo identificativo de la base de datos y las urls serán aún más feas, menos amigables y peores en cuanto a SEO.

Author: "--"
Send by mail Print  Save  Delicious 
Date: Friday, 03 Oct 2014 15:00

Captain Marvel 01Vengo leyendo y reseñando Captain Marvel de Peter David y Chriscross. Por si no leyeron la primera reseña, arranqué hace un par de semanas con Captain Marvel: First Contact.

Captain Marvel: Nothing to Lose es un compilado que incluye los números 1 al 6 de Captain Marvel Volume 4, que es en verdad el relanzamiento de Captain Marvel Volume 3 (cuyos primeros números reseñe en la entrada anterior en esta serie).

Pasaron 30 números desde entonces, y realmente se trata de un “relanzamiento”. Si bien se mantiene el contexto de los personajes, parece que Peter David quiso hacer borrón y cuenta nueva (los 35 números del volúmen 3 no anduvieron muy bien de ventas), a ver si con un enfoque distinto levantaba la serie, y así fue.

No se necesita haber leído First Contact ni nada anterior para leer estos números, entenderlos y disfrutarlos. Al principio se resumen bastante bien las cosas como para tener el contexto necesario para entender todo.

El arte mejoró mucho respecto a First Contact, parece que hubieran cambiado al dibujante, pero se trata del mismo Chriscross con la ayuda de Ivan Reis (capo dibujando Green Lantern) y Paco Medina. La ambientación también es completamente distinta, las aventuras se desarrollan en el espacio, naves espaciales y planetas extraños.

Ya no están presentes el humor y los guiños que caracterizaron a los primeros números.  Ahora la cosa se pone seria, y entra el toque Irredeemable que me llamó la atención la primera vez que leí algo de este material. Si se fijan la imagen que acompaña esta nota, los personajes The Plutonian y Captain Marvel hasta se parecen físicamente…

El tema es que uno de los poderes de Captain Marvel es la conciencia cósmica: La habilidad de saber todo lo que está pasando, lo que va a pasar, y lo que podría pasar en todo el universo todo el tiempo. Con tal poder, el capi termina perdiendo su cordura y se empieza a desarrollar una historia a nivel cósmico que se aleja del género super heróico y se acomoda bien en la ciencia ficción.

Rick Jones queda atrapado en el Microverso, haciendo en parte el papel de la conciencia de Genis hasta que éste deja de escucharlo. Termina teniendo sus propias aventuras en esta dimensión paralela, intentando volver a su universo. Me encanta todos los temas que abarca la historia en estos pocos números. En el segundo tenemos una movida a lo “Life Of Pi”, donde Rick Jones prefiere contar una historia a su manera y no llegar a la conclusión real.

Es genial cómo se maneja el tema de habilidad de Captain Marvel de ver el futuro y las distintas consecuencias de cada evento. Esto afecta su comportamiento y el de sus “aliados” (durante un buen rato hace equipo con The Punisher para aprender de su disciplina).

Captain Marvel: Nothing to LoseEn el tercer número la serie pega un salto a lo más cósmico, dejando atrás la tierra y encontrándose con el imperio Kree y sus soldados. Ahí es donde Marvel se une a ellos como Captain Marvel del Ejército del Imperio Kree, como su padre antes que él. Por un tiempo deja de tener un comportamiento tan errático siendo leal al ejército. Por un tiempo, como dije, y eventualmente la locura vuelve a él.

En algún momento de todo esto, Genis-Vell se encuentra con su padre Mar-Vell. Esto detona varios planteos interesantes sobre la muerte, la demencia y las relaciones padre-hijo.

Rick Jones mientras en cierto momento ya lleva una vida normal en otra parte del Microverso, y empieza a conocer a entidades cósmicas como Epiphany y Entropy, hijos de Eternity. A esa altura se comienzan a aparecer más conceptos cósmico/celestiales, siendo estos seres básicamente personificaciones de los conceptos  que le dan nombre.

De ahí en más la cosa se va para arriba en lo que respecta a Dios (o la no existencia de), la creación, los seres cósmicos y la siempre presente locura mental de Captain Marvel en un desenlace que te deja pensando y dudando si entendiste bien o no lo que pasó. Me gusta.

Como predecía al leer First Contact, me gustó mucho más esta parte de la historia. Además de ser bastante más serio y profundo, se llevan varios hilos conductores: la demencia del antihéroe principal, la vida de Rick Jones y todos esos temas abstractos cósmicos que asumo son bastante complicados de escribir. A mí particularmente me entretiene, pero veo que tiene que estar bien escrito para ser llevadero y estar bien pensados de antemano para no caer en salidas fáciles tras haberse armado una historia complicada.

Captain Marvel Senior

Leí y recomiendo. No es realmente necesario tener demasiado contexto del personaje principal o saber mucho qué estaba pasando en el Universo Marvel en ese momento, es una serie que se puede arrancar desde cero con este volúmen. Me dejó con más ganas de seguir leyendo así que en estos momentos estoy empezando con Captain Marvel: Coven, que incluye los números 7 al 13.

Author: "--"
Send by mail Print  Save  Delicious 
Date: Friday, 03 Oct 2014 07:45
La Wikipedia, define a los lenguajes de propósito general, como: Los lenguajes de propósito general, son lenguajes que pueden ser usados para varios propósitos, acceso a bases de datos, comunicación entre computadoras, comunicación entre dispositivos, captura de datos, cálculos matemáticos, diseño de imágenes o páginas. Era una filosofía completamente válida en la época (dorada) de [...]
Author: "--"
Send by mail Print  Save  Delicious 
Date: Wednesday, 01 Oct 2014 22:27

He intentado recuperar la rutina de publicar como tarde el lunes por la noche, pero por una cosa u otra al final no publiqué el lunes, y tampoco el martes. Pero casi mejor no dejar que se vuelva a acumular con otra semana.

Otro mes que se acababa, y otro Zaragozarb. Donde Néstor nos estuvo hablando de su proyecto personal bolt y de cómo integra ruby y arduino.

Tenía marcado en el calendario el Jacathon Aragón Open Data. Un hackathon para el que no cerramos equipo hasta 2 o 3 días antes, y donde no decidimos los sets de datos sobre los que trabajar y qué íbamos a hacer hasta después de la media hora de haber empezado. Teníamos un par de ideas algo diferentes, pero hasta que no invertimos unos minutos en investigar los sets de datos, no nos decidimos.

Mi equipo (los JodoCoders) lo formamos Rafa Ramos, Javi Rubio, Jesús Barón y yo. Desde luego que para mi un equipo un tanto extraño con 3 desarrolladores y 1 analista de datos, sin alguien de diseño yo me sentí un poco perdido al principio (vale, principalmente porque eso me obligó a tener que hacer tareas de frontend para lo que soy un zoquete :P).

El proyecto fue CRAs Aragón, para visualizar la situación y conocer la evolución de los Colegios Rurales Agrupados de Aragón. Utilizamos los datos del catálogo Open Data, pero encontramos inconsistencias y, comparándolo con otros datos oficiales, llegamos a la conclusión que en ese set los datos no podían ser totalmente correctos.

A nivel técnico, hicimos la web en python con flask. Se procesaron los datos con Access para importarlos posteriormente a MySQL. Mientras que en el frontend usamos html5boilerplate, foundation, leaflet con los tiles toner y el casi-omnipresente jquery.

Al final resultó que nos llevamos un par de premios. A la idea más novedosa y la votación del resto de participantes. Aunque hay que aclarar que el primer premio del jurado y el de participantes no podían coincidir; al parecer fuimos segundos en la votación de participantes tras Visual Aragopedia, que se llevaron uno de los primeros premios. Y tras las 24 horas de competición, disfrutamos de la noche jacetana :).

En fin, en cuanto a trabajo, además de algunas cosas relacionadas con posibles nuevos proyectos y ver si cerramos alguno que anda por ahí coleando hace algunos meses, esto es un resumen de lo que dio la semana:

  • Ya hay imagen nueva para minchador, falta maquetar el diseño y adaptar algunas partes de la aplicación, aunque me temo que esto se va a quedar un par de semanas parado.
  • Tuvimos reunión del proyecto paralelo a mhop para definir algunas cosas de la landing page y aplicación
  • Y en Nort el grueso del trabajo de desarrollo. Resolviendo algunos tickets relacionados con las aplicaciones web y móvil, implementando gráficas, realizando algunos cambios en funcionalidades existentes… Estamos en un punto del proyecto en el que tenemos que pulir detalles para que todo vaya lo más fino posible.
Author: "--"
Send by mail Print  Save  Delicious 
Date: Tuesday, 30 Sep 2014 19:00
Blog Stack

Estas últimas semanas he podido dedicar un poco de tiempo a al proyecto personal de Blog Stack. Blog Stack es un agregador o planeta de bitácoras en español sobre linux, sotware libre, programación, desarrollo, metodologías ágiles y tecnología. En dos artículos anteriores explicaba más en detalle que es Blog Stack, en uno de ellos hacía una descripción y presentación y en otro explicaba como está hecho en el aspecto técnico tanto detallando cuales son las tecnología que usa como la arquitectura del proyecto.

En este tiempo que he podido dedicarle he mejorado el diseño y aspecto visual de la página, destacando a dos columnas los últimos artículos agregados, incluyendo etiquetas con imágenes y modificando ligeramente el menú de navegación al archivo, preguntas frecuentes y como solicitar agregar una bitácora. Probablemente cuando tenga más ideas, un poco más de tiempo y el ánimo para implementarlas siga mejorándolo más. Pero el rediseño no ha sido todo, he credo una cuenta de twitter para BS de modo que los artículos que vaya agregando sean publicados en tweets de forma automática y posiblemente lleguen a más gente.

Si tienes una bitácora de la temática de BS con pocos “offtopics” y quisieras agregarla en un apartado de las preguntas frecuentes tienes las instrucciones, basta con un correo electrónico o una petición en GitHub y una información básica sobre tu bitácora. Blog Stack tiene algunas características que otros agregadores o planetas carecen para los editores, por ejemplo, agregar de forma segura los gist de GitHub, vídeos de youtube o vimeo, presentaciones de SpeakerDeck o publicidad de Amazon de modo que el contenido agregado se presente de forma muy parecida que en la bitácora original. Además, BS es capaz de mostrar publicidad de la bitácora agregada si usa AdSense o los comentarios de las entradas si usa Disqus. En el caso de los lectores pueden suscribirse únicamente a determinadas etiquetas de Blog Stack si solo están interesados en determinados temas.

La siguiente acción que realizaré será preguntar a los autores de algunas buenas bitácoras si quisieran agregarse a BS. En muchos casos por las licencias de creative commons que muchos empleamos para nuestras bitácoras podría hacerlo sin preguntar pero prefiero hacerlo antes por lo que considero las formas correctas y cortesía.

Author: "--"
Send by mail Print  Save  Delicious 
Date: Monday, 29 Sep 2014 15:00
The Original Hacker #9

The Original Hacker #9

Está disponible de manera libre y gratuita la revista digital The Original Hacker. Es un proyecto que trata de Software Libre, Hacking y programación a cargo de Eugenia Bahit.

Pueden descargarla en este enlace, y acá tienen el resumen de esta edición:

Si la edición anterior de The Original Hacker a alguien le resultó fuera de lo común, con esta nueva publicación probablemente flipe por completo. Filosofía Zen, mitos derrumbados, recuerdos desenterrados y raros descubrimientos unidos por un denominador común: el verdadero espíritu Hacker.

El artículo estrella de la edición Nº9 de The Original Hacker, es el que mejor representa al verdadero espíritu de la palabra Hacker. Se trata de «Las 12 reglas del aprendiz de Hacker», una guía para no solo convertirse en un buen estudiante de sistemas, sino también, para aprender a emplear la inteligencia estratégica en beneficio de la propia sabiduría. Un artículo que bien aprovechado podría convertirse en el futuro «Zen del Hacker».

Con la llegada de la última versión LTS de Ubuntu, la 14.04, comenzaron los problemas con Apache. La mayoría, generados por una política poco acercada por parte de Canonical, que en el afán por hacer un sistema «apto para usuarios poco ávidos» terminaron excediéndose, llegando a establecer configuraciones por defecto en binarios destinados a programadores, como el caso del paquete apache2 disponible en los repositorios. Sin embargo, en medio del caótico resultado, uno de ellos, resulta ser un bug que Apache se niega a reconocer como tal. En esta entrega, la «explicación del bug #56883 de Apache y la forma de solventarlo» hasta tanto los desarrolladores se animen a revisarlo.

Para retomar con «cosas raras» un artículo que parece salido del cajón de los recuerdos ¿alguien se acuerda de las TUI, las Text User Interfaces? Para los amantes del scripting, una «guía de desarrollo con dialog, la herramienta principal para creación de TUI con GNU Bash» y su disponibilidad en otros lenguajes como Python.

Finamente, se hace honor al verdadero hacking avanzando sobre uno de los temas más controvertidos y que mayor cantidad de discusiones genera en el mundo del desarrollo de aplicaciones Web: la «ingeniería de Web Software con Python y ¡Sin Frameworks!» En esta oportunidad, desmitificando otro de los tantos mitos que corren sobre el terreno de las aplicaciones Web: «el manejo de sesiones». En este artículo queda demostrado como con un simple «pip» y unas pocas líneas de código, el manejo de sesiones en Python NO requiere de frameworks para aportar seguridad, confianza y un desarrollo sustentable a la aplicación.

Perderse esta edición, podría ser peligroso para la salud. ¡Disfrútenla!

Descarga: The Original Hacker #9

Author: "--"
Send by mail Print  Save  Delicious 
Date: Monday, 29 Sep 2014 11:55
Enlaces interesantesAhí van los enlaces recopilados durante la semana pasada, espero que os resulten interesantes ;-)

.Net

ASP.NET

Azure / Cloud

Data access

Html/Css/Javascript

Cross-platform

Otros

Publicado en Variable not found
Author: "noreply@blogger.com (José M. Aguilar)"
Send by mail Print  Save  Delicious 
Date: Monday, 29 Sep 2014 10:06
Tuvieron que convencerme para migrar a Git, y lo cierto es que ahora que lo conozco, a pesar de estar lejos de ser un fan boy, reconozco que me gusta. Tienes mucha información al respecto, así que sólo citaré la cantidad de posibilidades que ofrece, así como el elevado rendimiento que da comparado con Subversion. [...]
Author: "--"
Send by mail Print  Save  Delicious 
Date: Monday, 29 Sep 2014 05:06

Después de conocer un poco con ReactJS, hacer un pequeño ejemplo con ReactJS y ver cómo podíamos automatizar la compilación de aplicaciones basadas en ReactJS, ha llegado el momento de cambiar de lenguaje y ver cómo podemos utilizar ReactJS desde ClojureScript.

ClojureScript es una implementación de Clojure que permite compilar código Clojure a Javascript, con lo que podemos ejecutarlo en el browser o incluso en plataformas como Node.js, en lugar de usar la JVM como motor de ejecución. Como era de esperar, con ClojureScript podemos utilizar las APIs nativas del navegador, pero además existen librerías que nos permiten trabajar de una forma más idiomática.

En el caso concreto de ReactJS, hay varias alternativas para utilizarlo desde ClojureScript. La más completa seguramente sea Om, que no sólo ofrece un interface sobre ReactJS sino que además aprovecha otras características “modernas” de Clojure (como los canales de core.async). Esto hace que sea una librería algo más intrusiva que el propio ReactJS, puesto que cubre un área mayor de la aplicación en lugar de limitarse a la pura generación del DOM.

En este post vamos a ver otra alternativa, reagent, que se define a si misma como un interface minimalista entre ReactJS y ClojureScript, y que no es más que eso, una pequeña capa de abstracción sobre ReactJS para poder escribir componentes de ReactJS de una forma más cómoda desde ClojureScript.

¿Por qué ClojureScript?

Dada la cantidad de lenguajes que compilan (o transpilan, según se mire) a Javascript, es razonable preguntarse por qué usar ClojureScript en lugar de, por ejemplo, TypeScript o ClojureScript.

Dejando de lado las bondades de Clojure como lenguaje, hay un par de factores que hacen que me parezca especialmente interesante la integración entre ClojureScript y ReactJS.

Por una parte, como vimos en el primer post de esta serie, ReactJS hace una distinción muy férrea entre la información mutable (state) y la información inmutable (props). Esto cuadra muy bien con la filosofía de Clojure, en la que por defecto la información es inmutable y existen mecanismos, como los atom para gestionar de forma explícita la mutabilidad.

Esto hace además que podamos mejorar el ya de por si excelente rendimiento de ReactJS. ReactJS utiliza un modelo de DOM Virtual sobre el que calcula diferencias para optimizar el renderizado en pantalla reduciendo al máximo el número de operaciones lanzadas sobre el DOM real. Para ello, necesita comparar las distintas versiones del DOM virtual y así detectar los cambios. Puesto que la mayoría de la información en Clojure se almacena en estructuras de datos persistentes (inmutables), esta comparación puede hacerse muchas veces realizando una simple comparación por referencia, lo que evita tener que recorrer estructuras de datos complejas para detectar cambios, acelerando así el proceso de renderizado aún más.

Por otro lado, y esto es una cuestión más personal, en ReactJS se utiliza una sintaxis especial, el JSX, para “mezclar” javascript con HTML a la hora de generar el DOM. En Clojure es frecuente utilizar técnicas similares, con librerías como Hiccup, por lo que esta forma de trabajar resulta bastante idiomática.

Un ejemplo

No voy a entrar en mucho detalle de cómo funciona ClojureScript (eso daría para un par de posts), pero vamos a ver un ejemplo de uso muy básico de reagent para poder compararlo con ReactJS.

Partiremos del mismo ejemplo de la lista de cervezas, en el que pretendíamos construir un interface como éste:

react-sample

En ReactJS, la forma de implementar cada componente era definiendo un objeto a través de la función React.createClass:

var BeerList = React.createClass({
  render: function() {...}
});

Con reagent, la forma más simple de implementar una función es a través de una función. Un componente en reagent no es más que una función que devuelve el DOM que se debe generar. Para ello, cuenta con una sintaxis parecida a la de hiccup, y la información inmutable que recibe el componente (las props de ReactJS) son directamente los parámetros que recibe la función. Existen otras alternativas para cubrir casos más complejos, pero de momento nos quedaremos con esta forma de trabajar.

Partiendo de esto, el componente que muestra la información de una cerveza sería algo tan simple como esto:

(defn beer-item [beer count]
  [:li "[" count "] " beer
   [:button {:on-click #(add-one! beer)} "Otra más"]])

Se trata de una función que recibe el nombre de la cerveza (beer) y las unidades consumidas hasta el momento (count) y genera el DOM necesario.

Para el componente que genera la lista completa, tendríamos algo así:

(defn beer-list []
  (let [total (reduce + (vals @beers))
        items (map (fn [[name count]] (beer-item name count)) @beers)]
    [:div
     [:p "Llevas " total  " cervezas"]
     [:ul items]]))

Aquí podemos ver una diferencia entre la manera de gestionar el estado mutable en ReactJS y en Reagent. En ReactJS es necesario utilizar las funciones getInitialState, setState y getState para tratar con el estado mutable, porque era necesario que la librería pudiese detectar cambios en el estado y así forzar el renderizado del componente que poseía ese estado.

En reagent se utilizan atoms para almacenar el estado mutable. Estos atoms no son exactamente los mismos que en Clojure, sino que son una implementación propia de reagent con algunas características especiales, pero exponen el mismo API que un atom de Clojure (y que podéis consultar en este post). A través de los atoms reagent puede detectar cuando se producen cambios en el estado y volver a renderizar a los componentes necesarios.

Aunque en el ejemplo se está utilizando un atom definido globalmente, es posible trabajar con atoms locales a cada componente si tiene más sentido.

El código completo del ejemplo sería éste:

(ns reagent-cljs.core
  (:require [reagent.core :as r]))

(enable-console-print!)

(def beers
  (r/atom {"Mahou 5 Estrellas" 0
           "Chimay triple" 0
           "Cibeles Imperial IPA" 0}))

(defn add-one! [beer]
  (swap! beers update-in [beer] inc))

(defn beer-item [beer count]
  [:li "[" count "] " beer
   [:button {:on-click #(add-one! beer)} "Otra más"]])

(defn beer-list []
  (let [total (reduce + (vals @beers))
        items (map (fn [[name count]] (beer-item name count)) @beers)]
    [:div
     [:p "Llevas " total  " cervezas"]
     [:ul items]]))

(r/render-component [beer-list] (.-body js/document))

Si tenéis curiosidad por ver cómo se estructura un proyecto de ClojureScript (o al menos una de las formas de estructurarlo), podéis echarle un vistazo en GitHub.

Una vez instalado leiningen y clonado el repositorio, tan sólo necesitáis ejecutar:

lein cljsbuild auto

El código se generará cada vez que se modifique algún fichero y podréis ver la página en funcionamiento abriendo el archivo index.html de la raíz del proyecto.

Resumen

Algunas de las ideas subyacentes a ReactJS hacen que encaje muy bien con un lenguaje como ClojureScript, especialmente por el tratamiento de la (im)mutabilidad y, en menor medida, por el uso de una sintaxis embebida en el propio lenguaje para la generación del DOM.

Reagent ofrece un interface simple sobre ReactJS para hacer que usarlo desde ClojureScript sea una experiencia muy cómoda. Como se puede ver en el ejemplo, el código que resulta mantiene un estilo muy típico de Clojure y aprovecha bastante bien las características de este lenguaje.

Posts relacionados:

  1. Crear un componente con ReactJS
  2. Cómo utilizar ReactJS con Browserify
  3. ReactJS: un enfoque diferente
Author: "--"
Send by mail Print  Save  Delicious 
Date: Sunday, 28 Sep 2014 12:07

Coursera

Estos días comienzan unos cuantos cursos en Coursera que quizá te interesen (yo estoy apuntado a un par de ellos):

  • Programming Languages
    Este no es un curso en el que se aprenda a programar. Es un curso para gente que ya sepa programar en el que se estudian los conceptos detrás de los lenguajes de programación. Se pone un gran énfasis en la programación funcional (es una buena oportunidad para aprender sobre ella) y durante el curso (que dura 10 semanas) se estudian los lenguajes ML, Racket y Ruby (aunque la elección de lenguajes es lo de menos, las técnicas que se estudian son aplicables a muchos lenguajes, sobre todo funcionales). Este es un curso que ya empecé en una edición anterior (hace algo así como un año ) y tuve que abandonar por falta de tiempo. Esta vez, espero completarlo.
  • Data Science Specialization
    Esta en realidad es una “especialización” de Coursera (una serie de cursos relacionados entre sí para especializarte en una materia). Aquí se trata de aprender sobre la “ciencia de los datos”: Cómo usar la informática para recolectar y analizar las grandes cantidades de datos disponibles hoy en día (secuencias de ADN, información sobre millones de estrellas disponibles en internet, etc). Yo seguramente no voy a hacer todos los cursos de esta especialización, pero por ahora me he apuntado a los siguientes:
    • The Data Scientist’s Toolbox
      Este es un curso muy corto (teóricamente son 4 semanas pero la verdad es que se puede hacer perfectamente en un fin de semana) donde se explican las bases para hacer el resto de cursos: Cómo instalar el software necesario, qué es Github y cómo crearse una cuenta, etc. Este ya lo he completado pero cada mes empieza una nueva edición.
    • R Programming
      Se oye mucho hablar últimamente del lenguage R (para análisis de datos y estadísticos) y este es el curso de la especialización en el que yo estaba más interesado. Ya lo he completado (termina hoy) y realmente me ha parecido muy interesante. R es un lenguaje super-especializado en el tratamiento de datos con cosas muy curiosas (como que todas las funciones, incluso la simple suma, funcionan con vectores, de tal manera que cuando escribes “a+b” en realidad estás sumando dos vectores que pueden contener 1 millón de datos cada uno). Igual que el anterior (y que todos los de la especialización) el curso inicia una nueva edición cada mes.
    • Getting and Cleaning Data
      Este es el que voy a empezar ahora. Se trata de utilizar el lenguage R para obtener los datos de distintas fuentes y en distintos formatos (CSV, XML, json) y limpiar los datos para dejarlos listos para la fase de análisis.

Y por ahora ya está bien. En la próxima entrada os hablaré de algunos otros cursos a los que no me he apuntado por distintas razones pero que creo que os pueden interesar.

Author: "--"
Send by mail Print  Save  Delicious 
Date: Friday, 26 Sep 2014 17:18
Java

En las dos últimas entradas he explicado como compilar un archivo de código fuente Java desde una aplicación y como cargar esa clase compilada de forma dinámica para ser utilizada en un programa, la segunda entrada trataba el como monitorizar un directorio o archivo para ver si han tenido cambios con la nueva API que a partir de Java 7 disponemos.

En esta entrada quiero explicar un ejemplo de como aprovechar estas dos funcionalidades diferentes en un caso práctico y que nos puede ser útil en algún caso. La idea del ejemplo es definir la configuración de una aplicación como podría ser una aplicación web en un archivo de código fuente Java y que cuando se produjese algún cambio se recargase de forma dinámica.

Algunas ventajas de definir la configuración de la aplicación de esta manera son las siguientes:

  • Al ser el archivo de configuración código Java que se compila podemos aprovecharnos de la validación que hace el compilador para estar seguros de que está libre de errores léxicos y sintácticos, el archivo solo se cargará cuando está libre de errores de compilación. Al compilarlo el compilador nos advertirá de los errores que contenga de forma precisa.
  • Por otra parte al ser código en el archivo de configuración podemos usar el lenguaje Java para hacer ciertas operaciones que en un xml u otro formato de archivo de texto plano no podemos hacer. Podríamos hacer un cálculo o conectarnos a la base de datos u otro sistema para recuperar cierta información. En algunos casos el lenguaje Java puede ser mejor opción para describir la configuración que los archivos de texto, son los mismos problemas de ant y maven comparados con gradle. También el código Java puede ser la forma más breve y útil para describir la configuración de la aplicación que archivos de texto, usando código Java podremos devolver objetos, listas, … en vez de Strings o números.
  • La recarga del archivo de configuración cuando se produzcan cambios en él nos evitará tener que reiniciar la aplicación, simplemente haremos el cambio y la configuración se aplicaría. Esto puede ser útil en las aplicaciones web evitándonos tener que hacer un reinicio de la aplicación.

Una de las razones de la existencia de los archivos de configuración es tener esa configuración de forma externalizada a la aplicación de tal forma que podamos cambiar la configuración sin tener que modificar la aplicación ni tener que recompilarla. Con la compilación y carga dinámica de la clase Java de la configuración podemos tener estas mismas propiedades de los archivos de configuración. Si a esto le sumamos la recarga dinámica evitamos tener caídas de servicio en la aplicación por modificaciones en el archivo de configuración.

Todo esto es algo que se comenta en el libro The Pragmatic Programmer con las siguientes lineas:

Many programs will scan such things only at startup, which is unfortunate. If you need to change the configuration, this forces you to restart the application. A more flexible approach is to write programs that can reload their configuration while they’re running. This flexibility comes at a cost: it is more complex to implement. If it is a long-running server process, you will want to provide some way to reread and apply metadata while the program is running.

Esta es la teoría, veamos el código del ejemplo de configuración en Java con recarga dinámica. La mayor parte del código está en la clase ConfiguracionManager. Esta tiene dos métodos que son usados en la clase Main de la aplicación, el método load carga la clase y la compila, y el método monitor que monitoriza el archivo en busca de cambios y llama al método load cuando los detecte.

<noscript><pre><code>package io.github.picodotdev.blogbitix.config; import java.nio.file.FileSystems; import java.nio.file.Path; public class Main { public static void main(String[] args) throws Exception { Path path = FileSystems.getDefault().getPath(&quot;src/main/java/io/github/picodotdev/blogbitix/config/AppConfiguracion.java&quot;); ConfiguracionManager manager = new ConfiguracionManager(&quot;io.github.picodotdev.blogbitix.config.AppConfiguracion&quot;, path).load().monitor(); int n = 0; while (n &lt; 20) { Thread.sleep(2000); System.out.println(manager.get()); } } }</code></pre></noscript>
<noscript><pre><code>package io.github.picodotdev.blogbitix.config; import java.io.FileReader; import java.io.Reader; import java.nio.file.FileSystems; import java.nio.file.Path; import java.nio.file.StandardWatchEventKinds; import java.nio.file.WatchEvent; import java.nio.file.WatchKey; import java.nio.file.WatchService; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import javax.tools.JavaCompiler; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; import javax.tools.ToolProvider; public class ConfiguracionManager { private String fullName; private Path path; private Configuracion configuracion; private Thread thread; private boolean closed; public ConfiguracionManager(String fullName, Path path) { this.fullName = fullName; this.path = path; } public Configuracion getConfiguracion() { return configuracion; } public Map get() { return configuracion.get(); } public ConfiguracionManager load() throws Exception { List&lt;String&gt; l = Arrays.asList(fullName.split(&quot;\\.&quot;)); String name = l.get(l.size() - 1); String source = loadSource(); JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); JavaFileManager manager = new ClassFileManager(compiler.getStandardFileManager(null, null, null)); List&lt;JavaFileObject&gt; files = new ArrayList&lt;JavaFileObject&gt;(); files.add(new CharSequenceJavaFileObject(fullName, source)); compiler.getTask(new NullWriter(), manager, null, null, null, files).call(); configuracion = (Configuracion) manager.getClassLoader(null).loadClass(fullName).newInstance(); return this; } public ConfiguracionManager monitor() throws Exception { closed = false; Runnable task = new Runnable() { @Override public void run() { while (!closed) { try (WatchService watchService = FileSystems.getDefault().newWatchService()) { path.getParent().register(watchService, StandardWatchEventKinds.ENTRY_MODIFY); WatchKey watchKey = watchService.take(); if (watchKey == null) { return; } for (WatchEvent&lt;?&gt; event : watchKey.pollEvents()) { Path p = (Path) event.context(); Path pp = path.getParent().resolve(p); if (path.equals(pp)) { load(); } } } catch (Exception e) { throw new RuntimeException(e); } } } }; thread = new Thread(task); thread.setDaemon(true); thread.start(); return this; } public void close() throws Exception { closed = true; } private String loadSource() throws Exception { StringBuffer source = new StringBuffer(); char[] buffer = new char[128 * 1024]; Reader reader = new FileReader(path.toFile()); int n = reader.read(buffer); while (n != -1) { source.append(buffer, 0, n); n = reader.read(buffer); } return source.toString(); } } </code></pre></noscript>

Esta idea de no utilizar archivos de configuración sino emplear código como la mejor forma y más breve de definirla es algo que hace gradle con los archivos de configuración del proyecto y apache tapestry para definir los módulos y la configuración del contenedor de inversión de control, parece una tendencia por el hecho de tener las propiedades y ventajas comentadas sobre otro tipo de archivos ya sean xml o sus sustitutos más recientes como yaml, json, … que son más compactos y legibles que xml pero que siguen adoleciendo de algunos de los mismos defectos.

El código fuente completo puede encontrarse en el siguiente repositorio de GitHub.

Author: "--"
Send by mail Print  Save  Delicious 
Date: Friday, 26 Sep 2014 16:00
Debian Jessie + GNOME Shell

Debian Jessie + GNOME Shell

Hace poco Debian volvió a elegir a GNOME como entorno de escritorio por defecto. En noviembre de 2013 Debian cambió GNOME por XFCE pero tras una recalificación, XFCE perdió su lugar.

Aparentemente las razones principales son la accesibilidad y la compatibilidad con systemd.

La verdad que mi experiencia con GNOME y Debian viene siendo lo suficientemente buena como para que no me ponga a pensar en probar otro entorno de escritorio. Cuando volví a Debian de ArchLinux, comenté un poco las primeras impresiones.

Me resulta sumamente práctico que la tecla “Windows” (o Super) sea un atajo de teclado que nos deja ver las “actividades” y elegir aplicaciones de cualquiera de los escritorios, reacomodarlas arrastrando y soltando, o buscar aplicaciones y lugares desde el lanzador. Es lo que se ve en la imagen que acompaña esta nota. Siempre uso 4 escritorios virtuales y me sirve para separar distintos perfiles de actividad.

El “lanzador” hoy en día se ha transformado para mí en parte imprescindible del uso de la computadora. Lo que antes haría desde un menú de aplicaciones o con “ejecutar comando” (Alt + F2), ahora lo hago apretando la tecla “Windows” y empezando a escribir las primeras letras del comando. Generalmente el sistema es lo suficientemente inteligente como para mostrarme lo que quiero usar a las pocas letras de haber empezado.

GNOMELas aplicaciones que más uso son 3 básicamente: La terminal, el navegador web y el procesador de texto. Para la terminal vengo usando desde hace años la terminal al estilo “Quake”, cuando usaba KDE era Yakuake y desde hace un tiempo Guake.

Lo único que me presenta problemas en todo el entorno es que usando 2 monitores, cuando salgo de Guake el foco puede estar en cualquier lado y nunca está donde esperaría. Creo que es mas bien un problema de definir el foco con el mouse en las preferencias. Según un comentario que dejaron en la entrada que enlazo más arriba del cambio de XFCE a GNOME, este problema estaría arreglado en la versión más nueva. Pero a su vez estoy usando cada vez menos el mouse por lo siguiente:

Un ejercicio que hago de hace unos años cada tanto, es poner el mouse a la izquierda del teclado. Esto hace que use más la mano que menos uso -en mi caso al ser derecho- la izquierda. Para los zurdos aplica lo mismo poniendo el mouse a la derecha del teclado. La idea es que esa parte del cerebro que se encarga de dirigir el brazo que no usamos haga algo, y a la vez que esa mano no sea tan inútil. Un efecto colateral interesante es que al empezar a acostumbrarme de cero muchas veces elijo usar el teclado y creo que me muevo mas rápido o por lo menos de manera más eficiente eligiendo la aplicación que quiero usar desde el teclado mismo.

En cuanto al navegador, uso Firefox y las herramientas para desarrolladores para todo lo que sea desarrollo con JavaScript. La consola web, el editor de estilos, el inspector, son herramientas imprescindibles que ya vienen instaladas con Firefox (o Iceweasel en Debian).

Mi procesador de texto es Emacs y hago todo lo que es programación y “funcionalidades de IDE” con Emacs y la terminal. También uso Thunderbird para el correo, y prácticamente todo lo demás que necesito está en el navegador.

Una herramienta que ayuda mucho a la personalización de GNOME es gnome-tweak-tool (disponible en los repos de Debian) que entre otras cosas permite gestionar las extensiones.

Debian Jessie va a entrar en modo código congelado en noviembre, así que de a poco se va a ir preparando la próxima versión estable de Debian. En breve seguramente llegue a Debian Testing la versión 3.14 de GNOME que trae varias mejoras, veremos qué tal está:



Author: "--"
Send by mail Print  Save  Delicious 
Date: Thursday, 25 Sep 2014 14:00

Oktober Datagest

Empieza el mes de los datos abiertos nuevamente en Uruguay \o/

Como vienen haciendo desde 2012, DATA organiza este octubre un Datafest, una serie de eventos para fomentar la creación de aplicaciones sociales en base a datos abiertos:

Buscamos desarrollar aplicaciones, visualizaciones o herramientas bajo licencias de software libre y a la vez colaborar en la resolución o visibilización de problemáticas sociales.

Este año el Oktober DATAFEST estará compuesto por 4 actividades. A lo largo de los distintos eventos los equipos seguirán un proceso de creación, desarrollo y puesta en funcionamiento de los proyectos. Si ya pensaste alguna idea (aunque aún no tengas equipo) te recomendamos que la subas al hackdash, así se puede ir sumando gente, podés ir recibiendo comentarios y la empezamos a trabajar.

El 1er evento será este sábado 27/09, nos juntamos en Crafted Code (Bvar. España 2529) a las 15:00 hs. para darle forma a las ideas y los equipos detrás de ellas. ¡Ideal para curiosos!

No te olvides de anotarte en: https://eventioz.com/oktober2014

Oktober Datafest 2014

Oktober Datafest 2014


Author: "--"
Send by mail Print  Save  Delicious 
Next page
» You can also retrieve older items : Read
» © All content and copyrights belong to their respective authors.«
» © FeedShow - Online RSS Feeds Reader