Noticias Weblogs Código

Variable not found

Inicialización de diccionarios en C# 6

October 21, 2014 11:48 AM

image33En otras ocasiones hemos hablado de novedades que acompañarán a la próxima revisión de C# que nos ahorraban algo de tiempo y pulsaciones de tecla a la hora de codificar algunos escenarios bastante frecuentes, a la vez que mejoraban la legibilidad.

Pues en esa misma línea, vemos ahora una nueva forma de inicializar colecciones clave-valor, como son los diccionarios. Ciertamente es un cambio bastante pequeño, de los que fácilmente podrían pasar desapercibidos junto a otras novedades de mayor peso, pero creo que también vale la pena conocerlo.

Para ponernos en situación, echemos un vistazo al siguiente código, totalmente válido en las versiones actuales de C#:



El código anterior es bastante limpio y pocas pegas se le podría poner, salvo que a primera vista no queda claro en absoluto qué tipo de estructura es CustomColorConverter. Si lo pensamos un poco, veremos que no es sino un Dictionary<string, string>  disfrazado, pero está claro que los elementos con los que lo estamos inicializando no expresan claramente que se trata de una colección de claves y valores. De hecho, a priori una expresión como { "red", "yellow"} pasaría mejor por ser un array o algún tipo de tupla que por ser un diccionario.

Para mejorar la legibilidad en estos escenarios, C# 6 introducirá una sintaxis adicional para la inicialización de este tipo de construcciones. No reduce el número de teclas a pulsar a la hora de escribirlo, pero sin duda deja bastante más claro qué es lo que estamos haciendo:



Ahora sí que salta a la vista que estamos cargando un diccionario, ¿verdad?

Otro ejemplo claro de uso, a menudo citado a la hora de hablar de esta nueva característica, es a la hora de utilizar diccionarios para crear objetos que posteriormente van a ser serializados, por ejemplo, en JSON:



Para finalizar, como curiosidad, decir que hasta hace bien poco se ha mantenido en la lista de características candidatas para C# 6 la introducción del símbolo $ tanto para inicializar diccionarios como para acceder de forma rápida a su contenido con una sintaxis similar a la siguiente:

image

Y salvo la ligera y molesta sensación de estar tocando código PHP, la verdad es que no pintaba mal, pero finalmente ha sido descartada. En principio, este uso del símbolo $ no vendrá la luz en la próxima versión de C#, aunque no se cierra la puerta a que en el futuro se introduzca si existe demanda por parte de la comunidad.

Otros posts de la serie:
Publicado en Variable not found.

» Leer más, comentarios, etc...

Arragonán

Semana 332

October 21, 2014 07:56 AM

La semana pasada resultó bastante agotadora, el lunes era festivo en Aragón y quedó una semana un tanto comprimida con mucho por hacer para recuperar los días no trabajados la semana anterior. Mucho estrés, preocupaciones y descansar bastante mal; os aseguro que cuando empalmas varios días seguidos así te preguntas por qué cojones te pusiste por tu cuenta, por suerte no es lo habitual. Y para rematar, el fin de semana fue de todo menos tranquilo.

Había Rails Rumble y me apunté con Javi, Rafa y Guillermo. Hasta el día de antes no decidimos proyecto, estuvimos hablando de diferentes ideas que teníamos, hasta que comenté uno que me rondaba hace tiempo que podría tener sentido. Una web que te recomendara recetas a partir de los ingredientes que tengas. Y de este hackathon salió leancook.

Leancook

Falta trabajo para afinar las búsquedas, pero no está mal para un fin de semana en el que tampoco es que estuviéramos concentradísimos en ello y nos metiéramos un palizón. Podéis ver un pequeño resumen de la parte técnica en nuestra ficha de equipo, y si queréis votarnos ahí genial :).

Ha vuelto a empezar la temporada en los 2 equipos de fútbol 7 en los que juego los fines de semana. La temporada pasada dije que debería dejar alguno, y además de no haber dejado ninguno, resulta que en el que juego entre semana (fútbol sala) pasamos a los lunes por votación del equipo: 3 partidos en 3 días. Veremos cuanto tardo en reventar.

En cuanto a cuestiones de trabajo:

  • No sin dolor, desplegué en el servidor de producción proyectoSinNombre. Aproveché para actualizar la versión de Refinery y alguna que otra gema. En realidad está desplegada la parte de la que tenemos la conformidad del cliente, tenemos otra parte de la que todavía la tenemos pendiente. Pero al ser partes complementarias, el cliente ya podría hacer público el proyecto una vez cargado de contenidos.
  • Trabajé sobre algunas pequeñas mejoras de mhop que me habían pedido los gestores del contenido.
  • Estuve analizando una web para presupuestar a una startup local un trabajo de web scraping.
  • Tocó trabajar duro en Nort. Seguir trabajando en detalles tanto para la aplicación móvil como para la web, trabajando bastante con el SDK de Facebook para mejorar la integración entre otras cosas. A finales de semana hicimos una demo con el cliente y salió bastante bien.

Buena semana.

» Leer más, comentarios, etc...

Variable not found

Enlaces interesantes 174

October 20, 2014 12:14 PM

Enlaces interesantesAhí van los enlaces recopilados durante la semana pasada, espero que os resulten interesantes :-)

.Net

ASP.NET

Azure / Cloud

Conceptos/Patrones/Buenas prácticas

Data access

Html/Css/Javascript

Visual Studio/Complementos/Herramientas

Otros

Publicado en Variable not found

» Leer más, comentarios, etc...

Koalite

Formas de organizar el código

October 20, 2014 05:06 AM

Excepto las prácticas de primero de carrera y algunos scripts muy simples, cualquier aplicación acaba constando de un montón de ficheros que necesitamos organizar de alguna manera en carpetas para poder manejarlos sin volvernos locos.

Existen muchas formas de organizar el código y en ellas influye mucho el gusto de cada uno o las convenciones aplicadas por cada equipo de desarrollo, pero eso no quita que también haya formas más o menos estándar, cada una de ellas centrada en mejorar determinados aspectos.

En este post vamos a ver dos filosofías distintas a la hora de organizar el código y veremos qué nos puede aportar cada una.

Organización por roles tecnológicos

La organización por roles es una de las más extendidas actualmente en el desarrollo de software. Probablemente uno de los proyectos que más hizo por este tipo de organización fue Ruby on Rails con su convención sobre configuración basada en la ubicación física en disco de sus modelos, vistas y controladores, y que luego ha sido copiada por otros frameworks como ASP.NET MVC.

Esta organización se basa en agrupar los ficheros en base al rol tecnológico que desempeña en el sistema. De esta forma, si en la capa de presentación estamos aplicando un patrón MVC, tendremos carpetas con Models, Views y Controllers o si tenemos un modelo de dominio estilo DDD, tendremos carpetas con Entities, Repositories, Factories.

Algo parecido a esto:

organización de código por roles

La organización por roles tecnológicos fomenta una forma de pensar homogénea y centrada en aspectos técnicos. Al definir tanto los roles y hacerlos tan explícitos con las carpetas independientes, sirve para remarcar mucho la arquitectura del sistema y eso nos lleva a encajar las nuevas funcionalidades dentro de esa arquitectura.

La principal ventaja de esto es que el diseño del sistema tiende a mantenerse muy homogéneo y la estructura de carpetas actúa como guía al implementar nuevas funcionalidades.

Si quieres montar una nueva funcionalidad para gestionar clientes potenciales en tu aplicación web, te crearás la entidad cliente potencial en la carpeta Entities, el repositorio en la carpeta Repositories, el controlador en Controllers, etc.

Es una buena opción cuando se está trabajando con equipos de desarrollo grandes en los que hay más rotación de personal, porque marca unas pautas muy claras de cómo hacer las cosas y el resultado final resulta más predecible.

Precisamente esta homogeneización se puede convertir en uno de los inconvenientes de esta forma de organizar el código, porque lleva a intentar encajar todas las funcionalidades del sistema en una serie de roles que, a veces, no son necesarios o no son necesariamente la mejor forma de implementar una funcionalidad concreta.

Es algo parecido a lo que ocurre con los diseños de N capas tradicionales, en los cuales puedes acabar creando capas que no aportan ningún valor sólo para mantener el diseño uniforme.

Además, al organizar el código por roles, tendemos a pensar sólo en términos de esos roles. Hay ocasiones en que la mejor forma de implementar algo es utilizando una clase o una función que no encaja en ninguno de los roles, pero como la estructura de carpetas sólo nos habla de controladores, vistas y modelos, acabaremos implementándolo como una de esas cosas. Es frecuente encontrar proyectos en los que todo es un NoSeQuéController, NoSeQuéView o NoSeQuéModel.

Otro problema (menor, si estás usando un IDE moderno con un sistema de navegación potente), es que el código necesario para comprender una funcionalidad queda repartido en muchas carpetas y es difícil saber realmente cuánto código está relacionado con una funcionalidad concreta.

Organización por funcionalidades

La organización por funcionalidades (features) se basa en primar el aspecto funcional sobre el técnico a la hora de decidir dónde colocar cada fichero.

En lugar de agrupar los ficheros por el rol que tienen (Controlador, Repository, ViewModel, Directive…), los agrupamos en base a la funcionalidad que implementan.

Más o menos así:

Organización de código por funcionalidad

Por ejemplo, en una aplicación web MVC que tiene una parte para gestionar clientes podríamos tener una carpeta customers que incluyese el modelo, la vista, el controlador y el resto de cosas que necesitemos.

Llevado al extremo, en cada carpeta tendríamos un slice vertical completo de la aplicación, desde el UI hasta la persistencia, pero normalmente no se llega a tanto, y podemos tener una carpeta customers con el código javascript y html de la nuestra aplicación SPA hecha con angularjs, y en alguna otra parte otra carpeta customers con el código C# de un proyecto WebAPI, con su controlador, servicios para cargar datos, etc.

Si la organización basada en roles tenía cierto parecido con las arquitecturas N capas, podríamos decir que la organización basada en funcionalidades se asemeja más (salvando las enormes distancias) al concepto de microservicios que está tan de moda ahora, porque fomenta el minimizar las dependencias entre unas carpetas y otras para tener funcionalidades lo más cohesivas e independientes posibles.

Esta forma de organizar el código evita los inconvenientes de la organización por roles. Con ella todo el código relativo a una funcionalidad está físicamente cerca, ayudando a saber mejor qué código está ligado a esa funcionalidad y a navegar por él.

Además facilita la navegación por la aplicación a un nivel más alto. Cuando ves carpetas llamadas Customers, Orders o Catalogue, es más fácil hacerse a la idea de qué hace la aplicación que si ves carpetas llamadas Controllers, Views y Models.

A la hora de implementar nuevas funcionalidades ayuda a considerarlas de forma independiente, por lo que resulta más sencillo “separarse” del diseño general y utilizar diseños más optimizados para cada funcionalidad concreta sin necesidad de ajustarnos a unos roles marcados previamente.

Esa libertad para implementar nuevas funcionalidades se convierte en un arma de doble filo si estás trabajando con gente que no es capaz de diseñar con un mínimo de sentido común, puesto que resulta más complicado fomentar el uso de buenas prácticas prácticas estandarizadas de diseño.

Mezclando ambas alternativas

Hasta ahora hemos visto dos formas de organizar el código que parten de ideas distintas y priorizan objetivos diferentes, pero no hace falta ser muy listo para darse cuenta de que en realidad estamos hablando de dos ejes distintos, roles técnicos y funcionalidades, y que en el fondo son dos conceptos ortogonales, por lo que podemos mezclarlos a nuesto antojo.

De hecho, lo normal es que cuando una aplicación se hace realmente compleja (cientos de ficheros) se acaben mezclado de una forma u otra.

Si se ha empezado organizando por roles técnicos, llega un momento en que tener 400 controladores de AngularJS en una sola carpeta se hace inmanejable y se acaba separándolos en distintas carpetas dentro de la carpeta controllers.

Igualmente, si cada funcionalidad de una aplicación con AngularJS acaba teniendo 3 directivas, 2 filtros, 4 controllers y 5 vistas, es razonable que terminemos particionando más los ficheros, ya sea mediante carpetas o alguna convención de nombres en los propios ficheros.

Conclusiones

La manera de organizar el código no sólo influye en dónde colocamos cada fichero, sino que también puede condicionarnos a la hora de diseñar el sistema o de implementar nuevas funcionalidades.

Si priorizamos el aspecto técnico organizando el código por roles, conseguiremos sistemas más homogéneos, con un código más estándarizado entre unas partes y otras de la aplicación, pero también nos puede hacer sentir una pérdida de libertad al implementar nuevas funcionalidades por intentar encajarlas en una estructura preestablecida.

Personalmente, hoy en día prefiero inclinarme hacia el lado de la organización por funcionalidad, incluso aunque luego el 80% de las funcionalidades tengan la misma estructura (y, por tanto, encajarían bien en una organización por roles). Pese a que esto requiere pensar más para decidir cómo implementar cada funcionalidad, a cambio permite pensar con más libertad en la forma de implementarla, y en mi opinión eso merece la pena.

No hay posts relacionados.

» Leer más, comentarios, etc...

Blog Bitix

Qué es y cómo hacer «web scraping» en Java

October 17, 2014 04:00 PM

Java

Algunas aplicaciones en internet necesitan intercambiar información para hacer algún tipo de integración. La tendencia actual es proporcionar una API REST o algún tipo de archivo descargable con cierto formato que permita procesarlo de forma automatizada y a las aplicaciones obtener la información de forma sencilla y precisa. Sin embargo, hay ocasiones en las que las aplicaciones de las que necesitamos extraer la información no proporcionan ni una API REST ni un archivo descargable con lo que no nos queda más remedio que extraer los datos de la propias páginas web inspeccionando el código HTML, esto en inglés se le conoce como «web scraping».

En este artículo explicaré como hacer web «scraping» usando la librería jsoup y usando el lenguaje de programación Java. jsoup proporciona una API para poder extraer la información que necesitemos, ya sean las URLs de los enlaces, determinado texto que contiene una valor, imágenes, … . A través de los selectores similares a los usados en jquery podemos llegar a los elementos que queremos de forma simple sin tener que hacer complicados algoritmos.

Dada la URL, archivo o String con contenido HTML podemos extraer los enlaces de imágenes, enlaces, hojas de estilos, iconos como se muestra en el siguiente ejemplo:

http://jsoup.org/cookbook/extracting-data/example-list-links

Un ejemplo práctico en el que podríamos hacer «scraping» es por ejemplo para extraer los enlaces torrent de descarga de todos los libros de un determinado autor o determinada serie de la página epublibre, esto nos ahorraría tener que hacerlo manualmente. Además si usamos transmission a través de su API podríamos automatizar la descarga.

El algoritmo o algoritmos que necesitemos para extraer la información será específico según la estructura HTML de cada página web, si esta cambia deberemos cambiar el algoritmo o los selectores, en cualquier caso es mejor que tener que hacer la tarea manualmente constantemente que al cabo de un tiempo será tediosa, aburrida y repetitiva.

Pero hay que tener cuidado con el contenido «scrapeado» y se debe tratar como una fuente de datos no segura. Por seguridad hay que tener especial cuidado con los scripts del contenido importado que podrían hacer que nuestra aplicación al mostrarlos tuviese algún problema de seguridad. La siguiente semana explicaré como «scrapear» contenido de forma segura en un ejemplo real como es el agregador de bitácoras Blog Stack donde solo se permiten los scripts de fuentes consideradas seguras como presentaciones de Speakerdeck, Gist de GitHub, YouTube, Vimeo o publicidad del programa de afiliados de Amazon.

Referencia:
Cómo filtrar contenido HTML de forma segura

» Leer más, comentarios, etc...

Blog Bitix

Cómo filtrar contenido HTML de forma segura

October 17, 2014 02:53 PM

Java

Algunos sitios y aplicaciones pueden tener la necesidad de «scrapear» el contenido de sitios web para extraer información de ellos y posteriormente usarla de alguna forma. El contenido «scrapeado» o obtenido de una fuente externa debe ser filtrado, si no es filtrado y posteriormente es servido a los usuarios puede enviárseles principalmente scripts con contenido malicioso (provocando un ataque cross-site scripting, XSS) o causar una desmaquetación al visualizar el contenido. A la hora de implementar la agregación de contenido de forma segura en Blog Stack, contenido obtenido de una fuente RSS o Atom pero que en esencia es HTML he usado la librería jsoup, de tal forma que solo el contenido considerado seguro o confiable de los artículos sea agregado.

¿Que puede pasar si en una fuente envía elementos <script>, <iframe> u <object>? Los <script> son código que se envía al navegador del usuario y que podrían explotar algún fallo de seguridad del navegador que usen, los <iframe> permiten cargar contenido de una tercera fuente. En definitiva podrían hacer que visitar Blog Stack fuese inseguro. Pero no permitir incluir estos elementos también haría que no se pudiesen mostrar vídeos de YouTube, Vimeo, Gist de GitHub, presentaciones de SpeackerDeck y se perdería parte del contenido original. La solución que he aplicado en Blog Stack es permitir el contenido de esos elementos que provienen de una fuente considerada confiable, es decir, si se trata de un iframe cuyo elemento src proviene de YouTube se permite el contenido ya que se supone que YouTube y su contenido es seguro. De esta forma el contenido puede agregarse de forma segura sin perder nada del contenido original.

Para hacer el filtrado de HTML en java podemos usar jsoup, para ello deberemos usar la clase Whitelist que proporciona jsoup o implementar una clase que la extienda con las etiquetas y sus atributos que consideramos seguros. En Blog Stack he necesitado implementar una clase Whitelist agregándole la funcionalidad que deseaba.

Esta es la implementación de la clase Whitelist, con el método addTag se indican los tags permitidos, con addAttributes se indican los atributos permitidos para cada etiqueta, addProtocols se indican los protocolos permitidos para cada etiqueta y atributo, finalmente el método addAttribute permite usar una expresión regular para el valor del atributo, esto se comprueba en el método isSafeAttribute:

<noscript><pre><code>package info.blogstack.misc; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.jsoup.nodes.Attribute; import org.jsoup.nodes.Element; import org.jsoup.safety.Whitelist; public class AppWhitelist extends Whitelist { private List&lt;Map&lt;String, String&gt;&gt; attributes; private AppWhitelist() { attributes = new ArrayList&lt;&gt;(); } public static Whitelist relaxed() { Whitelist wl = new AppWhitelist() .addTags(&quot;a&quot;, &quot;b&quot;, &quot;blockquote&quot;, &quot;br&quot;, &quot;caption&quot;, &quot;cite&quot;, &quot;code&quot;, &quot;col&quot;, &quot;colgroup&quot;, &quot;dd&quot;, &quot;div&quot;, &quot;dl&quot;, &quot;dt&quot;, &quot;em&quot;, &quot;h1&quot;, &quot;h2&quot;, &quot;h3&quot;, &quot;h4&quot;, &quot;h5&quot;, &quot;h6&quot;, &quot;i&quot;, &quot;img&quot;, &quot;li&quot;, &quot;ol&quot;, &quot;p&quot;, &quot;pre&quot;, &quot;q&quot;, &quot;small&quot;, &quot;strike&quot;, &quot;strong&quot;, &quot;sub&quot;, &quot;sup&quot;, &quot;table&quot;, &quot;tbody&quot;, &quot;td&quot;, &quot;tfoot&quot;, &quot;th&quot;, &quot;thead&quot;, &quot;tr&quot;, &quot;u&quot;, &quot;ul&quot;) .addAttributes(&quot;a&quot;, &quot;href&quot;, &quot;title&quot;) .addAttributes(&quot;blockquote&quot;, &quot;cite&quot;) .addAttributes(&quot;col&quot;, &quot;span&quot;, &quot;width&quot;) .addAttributes(&quot;colgroup&quot;, &quot;span&quot;, &quot;width&quot;) .addAttributes(&quot;img&quot;, &quot;align&quot;, &quot;alt&quot;, &quot;height&quot;, &quot;src&quot;, &quot;title&quot;, &quot;width&quot;) .addAttributes(&quot;ol&quot;, &quot;start&quot;, &quot;type&quot;) .addAttributes(&quot;q&quot;, &quot;cite&quot;) .addAttributes(&quot;table&quot;, &quot;summary&quot;, &quot;width&quot;) .addAttributes(&quot;td&quot;, &quot;abbr&quot;, &quot;axis&quot;, &quot;colspan&quot;, &quot;rowspan&quot;, &quot;width&quot;) .addAttributes(&quot;th&quot;, &quot;abbr&quot;, &quot;axis&quot;, &quot;colspan&quot;, &quot;rowspan&quot;, &quot;scope&quot;, &quot;width&quot;) .addAttributes(&quot;ul&quot;, &quot;type&quot;) .addProtocols(&quot;a&quot;, &quot;href&quot;, &quot;ftp&quot;, &quot;http&quot;, &quot;https&quot;, &quot;mailto&quot;) .addProtocols(&quot;blockquote&quot;, &quot;cite&quot;, &quot;http&quot;, &quot;https&quot;) .addProtocols(&quot;cite&quot;, &quot;cite&quot;, &quot;http&quot;, &quot;https&quot;) .addProtocols(&quot;img&quot;, &quot;src&quot;, &quot;http&quot;, &quot;https&quot;) .addProtocols(&quot;q&quot;, &quot;cite&quot;, &quot;http&quot;, &quot;https&quot;) // .addTags(&quot;script&quot;, &quot;iframe&quot;, &quot;noscript&quot;) .addAttributes(&quot;div&quot;, &quot;style&quot;) .addAttributes(&quot;img&quot;, &quot;style&quot;) .addAttributes(&quot;script&quot;, &quot;src&quot;, &quot;data-.*&quot;) .addAttributes(&quot;iframe&quot;, &quot;src&quot;, &quot;width&quot;, &quot;height&quot;, &quot;frameborder&quot;, &quot;allowfullscreen&quot;, &quot;style&quot;, &quot;marginwidth&quot;, &quot;marginheight&quot;, &quot;frameborder&quot;, &quot;scrolling&quot;) .addAttributes(&quot;object&quot;, &quot;width&quot;, &quot;height&quot;) .addAttributes(&quot;param&quot;, &quot;name&quot;, &quot;value&quot;) .addAttributes(&quot;embed&quot;, &quot;src&quot;, &quot;type&quot;, &quot;width&quot;, &quot;height&quot;, &quot;allowscriptaccess&quot;, &quot;allowfullscreen&quot;); return wl; } public Whitelist addAttribute(String tag, String key, String regexp) { Map&lt;String, String&gt; attribute = new HashMap&lt;&gt;(); attribute.put(&quot;tag&quot;, tag); attribute.put(&quot;key&quot;, key); attribute.put(&quot;regexp&quot;, regexp); return this; } @Override protected boolean isSafeAttribute(String tagName, Element el, Attribute attr) { for (Map&lt;String, String&gt; attribute : attributes) { String tag = attribute.get(&quot;tag&quot;); String key = attribute.get(&quot;key&quot;); String regexp = attribute.get(&quot;regexp&quot;); if (tag.equals(tagName) &amp;&amp; attr.getKey().matches(key) &amp;&amp; attr.getValue().matches(regexp)) { return true; } } return super.isSafeAttribute(tagName, el, attr); } } </code></pre></noscript>

Y esta es la forma de usar la clase a través de Jsoup.clean:

<noscript><pre><code>AppWhitelist whitelist = (AppWhitelist) AppWhitelist.relaxed(); whitelist.addAttribute(&quot;script&quot;, &quot;src&quot;, &quot;^http[s]?://speakerdeck.com/.*$&quot;); whitelist.addAttribute(&quot;script&quot;, &quot;src&quot;, &quot;^http[s]?://gist.github.com/.*$&quot;); whitelist.addAttribute(&quot;iframe&quot;, &quot;src&quot;, &quot;^http[s]?://www.youtube.com/embed/.*$&quot;); whitelist.addAttribute(&quot;iframe&quot;, &quot;src&quot;, &quot;^http[s]?://player.vimeo.com/video/.*$&quot;); whitelist.addAttribute(&quot;iframe&quot;, &quot;src&quot;, &quot;^http[s]?://rcm-eu.amazon-adsystem.com/.*$&quot;); whitelist.addAttribute(&quot;embed&quot;, &quot;src&quot;, &quot;^http[s]?://www.youtube.com/v/.*$&quot;); String content = Jsoup.clean(postContent.toString(), source.getPageUrl(), whitelist);</code></pre></noscript>

El código fuente completo de BS junto con el «scrapeado» y el uso de esta clase está disponible en un repositorio de GitHub.

Referencia:
Qué es y cómo hacer «web scraping» en Java

» Leer más, comentarios, etc...

Picando Código

RubyConf Argentina 2014

October 16, 2014 03:00 PM

RubyConf Argentina 2014

Los próximos viernes 24 y sábado 25 de octubre se lleva a cabo una vez más RubyConf Argentina :D Una de las mejores conferencias técnicas de América Latina y el mundo, si me permiten el atrevimiento. Como el año anterior, el lugar del evento va a ser Ciudad Cultural Konex en Buenos Aires, con dos días de charlas y un Ruby Fun Day (talleres, tutoriales y actividades para rubyistas de todos los niveles).

Todavía quedan entradas a AR$ 1.000, la entrada final va a estar a AR$ 1.200. Esto proporciona además de la admisión a los dos días de charlas: desayuno, almuerzo y merienda, remera oficial de la conferencia y bolsa de regalos, acceso a las fiestas post evento, servicio de traducción y acceso a toda la gente que se junta para estos eventos.

Hay un muy buen nivel de charlas, tengo particular expectativa por algunas:

Chris Hunt – Resolviendo el Cubo Rubik con los ojos vendados. Chris dió una charla excepcional sobre manejo de memoria (no en computadoras, en seres humanos) en la pasada RubyConf Uruguay, y demostró ser un excelente orador tanto en forma como en contenido.

Lucía Escanellas – “Look ma’, I know my algorithms! Conozco a Lu en LaVidaReal™, y hace tiempo que quiero verla dar una charla en una conferencia de este estilo. Una persona sumamente inteligente y que sabe mucho, estoy seguro que se va a lucir y va a dar terrible charla.

Marta Paciorkowska – Lenguajes de programación, literatura. Es una de esas charlas que seguramente te dejen pensando un buen rato y de para temas de discusión.

Patricio Bruna – De desarrollo a producción con Docker. No sé mucho de Docker y no he tenido tiempo para ponerme a aprender, y quiero saber de qué va la cosa. Así que me viene bien la charla.

Hay un montón de charlas más, si no están convencidos revisen la lista completa. A nivel personal también me alegra tener la oportunidad de volver a ver a mucha gente de la comunidad Ruby. Estos eventos sirven para reencontrarse con amigos de todas partes :)

Si están en Uruguay y tienen ganas de ir a la conferencia, únanse a los Rubistas del Meetup, que varios miembros van a cruzar el charco y pueden coordinar para ir con más gente por ahí.

Todavía hay tiempo de registrarse.

¡Nos vemos ahí!

» Leer más, comentarios, etc...

Variable not found

Rendimiento de nameof en C# 6

October 16, 2014 11:45 AM

imageHace unos días mostrábamos por aquí el nuevo operador nameof que acompañará a C# 6, y cuya función, resumidamente, es obtener el nombre a nivel de código de la variable o miembro a la que se aplica:



En los comentarios de este post, el amigo Kiquenet se preguntaba qué incidencia podía tener el uso de este operador en el rendimiento de nuestras aplicaciones, y esa duda es la que vamos a responder muy rápidamente ahora.

Se podía intuir que la incidencia sería cero porque la resolución del nombre tenía toda la pinta de ser realizada en tiempo de compilación y, por tanto, los usos del operador nameof serían transformados en una constantes de cadena, pero la verdad es que siempre quedaba la duda de si había algún tipo de “magia” adicional por detrás.

Por esta razón, he realizado una prueba muy sencilla. Primero, implementando y compilando el siguiente código:



Seguidamente, descompilando la .dll resultante con ayuda de dotPeek, podemos ver que el código que finalmente ha sido incluido en el ensamblado es el siguiente:



Aunque la optimización ha hecho algún estrago, creo que queda claro que la llamada a nameof es sustituida en tiempo de compilación por una constante de cadena (en este caso, “number”). Por tanto, ahora sí podemos asegurar que el uso de nameof ni tiene incidencia alguna sobre el rendimiento en tiempo de ejecución.

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.

» Leer más, comentarios, etc...

Bitácora de Javier Gutiérrez Chamorro (Guti)

Software abandonado

October 15, 2014 06:24 PM

A raíz de un comentario en el blog de An Drekke, que hablábamos de programas abandonados, pero que siguen siendo útiles, he decidido escribir al respecto. Cuando un programa comercial deja de ser un negocio, lo normal es que se abandone su desarrollo, y deje de venderse. Si en cierta forma podemos atribuirles vida, es [...]

» Leer más, comentarios, etc...

Arragonán

Semanas 330 y 331

October 15, 2014 04:54 PM

Se acabaron las fiestas del pilar, este año han sido bastante más tranquilas para mi que el año anterior (en el que posiblemente debí perder un par de años de vida :P). Pero aún me tomé un par de días libres para poder disfrutar de conciertos y juntarme con algunos amigos.

La semana previa a pilares la empecé bastante acatarrado, el gen de los autónomos para evitar bajas laborales lo debía tener un poco averiado y tuve un par de días de bajo rendimiento, pero llegué mejor al final de la semana.

En la de pilares pasé por las Geek’s Talks especial Oktoberfest, a la que había decidido no ir pero terminé arrancándome en el último momento a base de lo que me trolearon.

Durante este par de semanas dediqué algunos ratos a un petproject para poder ver en el teléfono la oferta de conciertos en Zaragoza, una aplicación Rails bastante chorras alimentada de datos por un pequeño scraper basado en Nokogiri (también le puse Active Admin, por trastearlo un poco). Y es que aunque hay un par webs que tienen bastante información de lo que se mueve en las grandes y pequeñas salas de Zaragoza, son una castaña para consultarlas en el teléfono.

En realidad ya hace un par de años que esta idea la estuvimos trabajando sobre el papel con un amigo, además de conciertos pensábamos en incluir otro tipo de actividades culturales y de ocio. Pero al no ver un modelo de negocio claro que nos pudiera dar algo de rentabilidad a medio plazo (lo de afiliados, publicidad, cobrar a las salas/bares… iba a estar jodido) pasó a la lista de ideas felices que me vendrían bien a mi pero difícilmente jamás den un duro.

Y, en fin, como todo final de trimestre hacer la recopilación de facturas para cerrarlo.

En cuanto a proyectos:

  • Aún a vueltas con proyectoSinNombre, estuve de mailing con la gente de sistemas para que me dieran acceso a una máquina suya vía VPN. Lo típico que se presupone a grandes organizaciones, me tocó cruzarme bastantes emails hasta que conseguí acceso a la máquina tanto ssh para el despliegue como http para ver y probar la web.
  • En mhop estuve mirando algunas propuestas de mejoras sobre las que tengo que trabajar. También tuvimos una nueva reunión de coordinación, pero nada productivo.
  • Y en Nort empezamos a ver la recta final para la puesta en producción. La mayor parte de mi esfuerzo ha ido en trabajar en la versión móvil Cordova, que es la que tiene nuestra prioridad en este momento; aunque trabajando también en adaptar algunas cosas de backend que tenemos en Grails. Y por supuesto tocó ir resolviendo algunos errores e ir limando detalles.

Buena semana.

» Leer más, comentarios, etc...

Variable not found

Software patch, literalmente

October 15, 2014 11:45 AM

Parche informáticoSiempre he pensado que el término “parche” aplicado al desarrollo de software se utilizaba por analogía con el mundo real. Al fin y al cabo, poner un parche en una aplicación es conceptualmente bastante parecido a hacerlo en una rueda pinchada, ¿no?

Pero no, como en otras ocasiones que ya hemos visto por aquí, no es un tema nada conceptual. La realidad es bastante más pragmática, y el uso de la palabra “parche” es literal y simplemente responde a razones históricas.

Y es que resulta que en los albores de la informática, cuando los programas se escribían a base de realizar perforaciones en cintas de papel, los errores detectados sólo se podían corregir parcheando físicamente la zona afectada y volviendo a perforar para aplicar las correcciones.

Una tarea casi más propia de un sastre que de un desarrollador ;-)


Programa para Mark I (1944)
Imagen: Wikipedia

Imagen: Smithsonian Archives Center

Es maravilloso tener una profesión en la que cada día puedes aprender cosas nuevas, ¿verdad?

Fuentes:
Publicado en Variable not found.

» Leer más, comentarios, etc...

Variable not found

Enlaces interesantes 173

October 14, 2014 11:52 AM

Enlaces interesantesAhí van los enlaces recopilados durante la semana pasada, espero que os resulten interesantes ;-)

Eventos

    .Net

    ASP.NET

    Azure / Cloud

    Conceptos/Patrones/Buenas prácticas

    Html/Css/Javascript

    Visual Studio/Complementos/Herramientas

    Cross-platform

    Publicado en Variable not found

    » Leer más, comentarios, etc...

    xailer.info

    Centrado de ventanas

    October 14, 2014 09:28 AM

    Estimados usuarios de Xailer,

    Los formulario de Xailer tienen una propiedad de nombre lCentered que permite indicar si la ventana ha de mostrarse centrada o no.  El centrado se produce con la totalidad de la pantalla y si el usuario tiene dos monitores, se centro en el monitor donde se está ejecutando la aplicación. No obstante, están proliferando monitores cada vez más grandes y sobre todo más anchos y la visualización centrada en el monitor puede no ser la correcta.

    Os vamos a mostrar un pequeño truco,  -que además servirá para entender algo más la sobrecarga de clases de Xailer-, para centrar la ventana sobre su formulario padre. Este es el código:

    CLASS TForm FROM XForm
      METHOD Show( nCmdShow, lCenter )
    END CLASS
    
    METHOD Show( nCmdShow, lCenter ) CLASS TForm
       LOCAL nDifW, nDifH
       DEFAULT lCenter TO ::lCentered
       ::Super:Show( nCmdShow, .f. )
       IF lCenter .AND. ::oParent:IsKindOf( "TForm" )
         nDifW := Max( (::oParent:nWidth - ::nWidth) / 2, 0 )
         nDifH := Max( (::oParent:nHeight - ::nHeight) / 2, 0 )
         ::nLeft := ::oParent:nLeft + nDifW
         ::nTop := ::oParent:nTop + nDifH
       ENDIF
    RETURN Nil

    Basta con poner este código en cualquier parte de su código y a partir de entonces los formularios que tengan la propiedad lCentered a verdadero se mostrarán centrados respecto a su formulario padre y no con respecto al monitor.  Espero que os haya gustado.

    Un saludo

     

    » Leer más, comentarios, etc...

    Koalite

    De abstracciones y repositorios

    October 13, 2014 05:06 AM

    No esperaba yo verme en esta situación de tener que defender el uso de abstracciones, después de haber criticado los arquitectos y sus superarquitecturas, las capas que no aportan ningún valor o el uso de abstracciones en cosas que no pueden abstraerse, pero igual que con los comentarios en el código, creo que el tema merece una reflexión un poco más profunda.

    Ya lo he dicho otras veces, el desarrollo de software no está exento de modas y, como casi todas las modas, éstas vienen en ciclos. Muchas veces, después de una fase de hype a favor de una tecnología o técnica sigue una fase de completo desprecio por ella, pasando en poco tiempo de un extremo a otro. Esto hace que en ocasiones nos dejemos llevar por razonamientos simplistas, recordando sólo el abuso que se ha hecho de algo y olvidando las partes positivas que podía aportarnos.

    El valor de las abstracciones

    Recientemente me he encontrado en la enésima discusión sobre repositorios sí o repositorios no, y he leído algún artículo en el que se critica duramente las arquitecturas basadas en capas, cosa que, por cierto, yo también he hecho en alguna ocasión.

    En ambos casos la discusión subyacente trata sobre el uso y abuso de abstracciones, lo que sin duda es un tema interesante y que debe ser considerado con cuidado, pero en mi opinión el principal argumento que se da para no usar abstracciones es erróneo.

    Este argumento se centra en que las abstracciones protegen frente a los cambios y, por tanto, si no vas a necesitar cambiar esa parte del sistema, no es necesario introducir una abstracción. El ejempo más típico de esto es si no vas a cambiar de nunca de ORM, para qué vas a abstraerlo detrás de repositorios.

    Es cierto que introducir algún tipo de abstracción sirve para aislar distintos componentes de un sistema, introduciendo un mecanismos que nos permita evolucionarlos por separado y evitando que los cambios en uno afecten al otro, pero una abstracción es más que eso.

    El proceso de abstraer consiste en aislar la esencia de algo de manera que podamos tratarlo sin tener que considerar aquellas características que son accidentales y por ello innecesarias para definir ese algo.

    Podemos aplicar este proceso a muchos niveles, y es algo que hacemos continuamente. Cuando introducimos una variable para almacenar un resultado temporal y poder darle un nombre, estamos abstrayendo la forma de calcular ese resultado temporal. Cuando extraemos parte de código a un método, estamos haciendo lo mismo, estamos separando una parte de un proceso y utilizando un nombre que nos permita referirnos a ella, sin necesidad de conocer cómo está implementada.

    Estas abstracciones, muy relacionadas con el principio DRY, no sólo nos protegen frente a los cambios, sino que además aportan algo más importante: ayudan a elevar el nivel del discurso, permitiéndonos razonar en términos más generales y facilitando la comprensión del sistema.

    El valor real de muchas abstracciones es ayudarnos a manejar sistemas complejos encapsulando ciertas áreas, y no tanto protegernos de cambios en esas áreas (aunque esto no deja de ser un agradable valor añadido).

    Abstracciones sobre el ORM

    Por ver un ejemplo, y volviendo al (recurrente) tema de los repositorios (del cual podéis ver mi opinión en estos posts sobre repositorios), utilizar repositorios para encapsular el acceso a datos no debería tener como finalidad principal protegernos frente a cambios en el ORM que estamos utilizando, sino proporcionarnos un lenguaje de más alto nivel para razonar sobre un problema.

    Efectivamente, escribir una consulta directamente contra un DbContext o un ISession es mucho más potente y flexible que encapsularla en un repositorio y nos permitirá utilizar toda la potencia de nuestro ORM, pero abstraer esa consulta en un repositorio (o con cualquier otra técnica, por ejemplo un Query Object) nos posibilitará darle un nombre y nos ayudará a entender mejor las partes del código donde se usa esa consulta.

    Podemos ver estas abstracciones como una fachada que oculta la complejidad de manejar el ORM. Es más sencillo y legible utilizar un repositorio con una consulta para obtener clientes preferentes que han comprado algo en el último mes que generar inline esa consulta con LINQ.

    Además, para los amantes de los principios SOLID y todas esas cosas, el uso de repositorios (y especialmmente el de Query Objects) hace que limitemos la superficie de las dependencias en lo que podríamos considerar una aplicación del principio de segregación de interfaces.

    Con todo esto no pretendo decir que lo mejor sea siempre encapsular el ORM detrás de repositorios o Query Objects, la respuesta, como diría un gallego, es que depende, pero lo que sí hay que tener en cuenta es que el motivo de base para decidir si encapsular o no el ORM no debe ser si lo vamos a cambiar en un futuro o no (seamos realistas, probablemente no).

    Conclusiones

    Normalmente, cada periodo de popularidad es seguido por una reacción contraria hacia lo que fue popular en su momento, y cuando mayor ha sido la popularidad, mayor será la reacción en contra. Es complicado abstraerse (valga la redundancia) de las corrientes de pensamiento de cada momento, pero es necesario intentar mantener cierta distancia y ver con perspectiva qué nos aporta cada técnica.

    Que se haya abusado de abstracciones en arquitecturas ultracomplejas no quiere decir que las abstracciones no aporten ningún valor, y ese valor va más allá de la mera protección ante el cambio.

    Desarrollar software es una actividad muy compleja; gracias a las abstracciones podemos obviar determinados detalles en ciertos momentos para que seamos capaces de gestionar esa complejidad: las abstracciones nos permiten quitar los árboles para poder ver el bosque.

    No hay posts relacionados.

    » Leer más, comentarios, etc...

    Bitácora de Javier Gutiérrez Chamorro (Guti)

    Punteros en Basic

    October 12, 2014 06:21 PM

    Quizás os sorprenda que hable de punteros, y de Basic. Los punteros, o apuntadores, un recurso típico de C/C++, ensamblador y Pascal en menor medida. Así que puede que te extrañe, que PowerBasic, desde su versión 3.2 de 1996 soportara incluso aritmética de punteros. La sintaxis es realmente sencilla, tenemos el tipo de datos Ptr, [...]

    » Leer más, comentarios, etc...

    Navegapolis

    Un equipo scrum necesita 3 sprints para aprender a estimar, pero es lo menos importante.

    October 11, 2014 12:17 AM

    A la terceraLas estimaciones de esfuerzo y velocidad no suelen ser fiables en los equipos novatos de scrum hasta el tercer sprint, pero de todas formas la precisión al estimar es la habilidad menos relevante de las analizadas para un equipo ágil.

    Son conclusiones del estudio realizado por la Facultad de Informática de la Universidad de Liubliana: A Case Study on Agile Estimating and Planning using Scrum.

    Se ha desarrollado en el curso académico 2009-10, y en él han participado 52 alumnos de Ingeniería Informática, formando 13 equipos.

    Los 13 han desarrollado el mismo sistema empleando Scrum: una plataforma web de gestión académica: registro de alumnos, exámenes, estadísticas... a partir de una pila de producto inicial de 60 historias de usuario.

    Antes de empezar todos recibieron una pequeña formación sobre agilidad y trabajo con scrum, porque el objetivo ha sido simular la implantación de trabajo ágil en una empresa para determinar: la precisión de las estimaciones y qué prácticas de scrum consideraban que habían sido más útiles al terminar el desarrollo.

    En cuanto a las estimaciones el resultado ha sido que en el primer sprint son normales las estimaciones muy optimistas, y que no se logre terminar con las tareas previstas (sólo lo logró 1 de los 13 equipos del estudio). La media fue completar sólo el 42% de las tareas. A partir del tercer sprint las estimaciones ya comienzan a ser fiables. En cuanto a la valoración que daban a cada una de las prácticas (de 0 a 5) empleadas para el éxito de una implantación ágil estos son los resultados.

     

    Resultados

    » Leer más, comentarios, etc...

    El blog de Adrián Arroyo

    La mística relación entre el 9N y Firefox

    October 08, 2014 12:00 AM

    Si habeis leído el título pudiera parecer que he empezado a tomar drogas o alguna sustancia estupefaciente variada. Sin embargo nada más lejos de la realidad, la mística relación entre el 9N (la consulta catalana) y Firefox se abrió ante mis ojos cuando vi esta valoración de mi complemento en el sitio de complementos de Firefox Cataluña y Firefox - Es un complot

    He intentado por tres golpes instalar este complemento, pero, como ya es fuerza normal, si no eres de MADRID (“Villa y Corte”) no funciona. Puedes entrar a “Opciones”, pero el identificador de municipio NO ADMITE un primer número que sea el “0”. Por lo tanto, Barcelona, que es id 08019 , no funciona. SIEMPRE IGUAL. 9N. (Traducción hecha por Apertium)

    Os pongo en situación. El comentario en cuestión se refiere al complemento El Tiempo en España y la vloración anterior (solo había una antes) le daba 5 estrellas sobre 5. ¿Qué ha pasado? Resulta que cuando hice el complemento (es bastante viejo) use el control numérico que ofrece XUL y almacené la preferencia como un entero. Esto funcionaba con todos los códigos que había probado pero fallaba con los que empezaban con 0. ¿Por qué? La respuesta es muy sencilla y es que al estar en un control numérico al introducir un número a la izquierda este se nos quita tan rápidamente como introdujamos la siguiente cifra. El código de Barcelona empieza por 0 y claro, en esa ciudad no funcionaba el complemento. En eso le doy la razón al autor de la valoración. Pero de ahí a relacionar el que no funcione con un compot contra los catalanes por parte de Madrid me parece excesivo y un sin sentido. ¿Cómo alguien puede relacionar un bug con un complot político? (encima de un complemento que es open source)

    » Leer más, comentarios, etc...

    Variable not found

    El operador nameof de C# 6

    October 07, 2014 11:58 AM

    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.

    » Leer más, comentarios, etc...

    Blog Bitix

    Generar URLs semánticas y amigables

    October 05, 2014 01:30 AM

    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.

    » Leer más, comentarios, etc...

    Blog Bitix

    Generación de URLs y transliteración de caracteres

    October 05, 2014 01:30 AM

    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.

    » Leer más, comentarios, etc...

    Blog Bitix

    Generación de URLs y tansliteración de caracteres

    October 03, 2014 06:14 PM

    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.

    » Leer más, comentarios, etc...

    Picando Código

    Captain Marvel: Nothing to Lose

    October 03, 2014 03:00 PM

    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.

    » Leer más, comentarios, etc...

    Bitácora de Javier Gutiérrez Chamorro (Guti)

    Lenguajes de propósito general

    October 03, 2014 07:45 AM

    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 [...]

    » Leer más, comentarios, etc...

    Arragonán

    Semana 329

    October 01, 2014 10:27 PM

    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.

    » Leer más, comentarios, etc...

    Blog Bitix

    Agregador Blog Stack rediseñado

    September 30, 2014 07:00 PM

    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.

    » Leer más, comentarios, etc...

    Meta-Info

    ¿Que es?

    Planeta Código es un agregador de weblogs sobre programación y desarrollo en castellano. Si eres lector te permite seguirlos de modo cómodo en esta misma página o mediante el fichero de subscripción.

    rss subscripción

    Sponsors

    Puedes utilizar las siguientes imagenes para enlazar PlanetaCodigo:
    planetacodigo

    planetacodigo

    Si tienes un weblog de programación y quieres ser añadido aquí, envíame un email solicitándolo.

    Idea: Juanjo Navarro

    Diseño: Albin