Noticias Weblogs Código

Arragonán

Semana 324

August 25, 2014 11:23 PM

Los días post-fiestas de pueblo suelen hacerse cuesta arriba, y la semana pasada no fue una excepción, el lunes fue relajado pero el resto de la semana hubo que ponerse las pilas.

Estuvimos analizando el alcance de un proyecto web de gestión de contenidos y una pequeña parte de gestión documental, para hacer una propuesta tanto para el desarrollo de la parte backend como la de frontend.

Los proyectos actuales:

  • Pequeños cambios en minchador, básicamente mejorar el mailing entre restaurante y comensal.
  • Resolver errores de copy en mhop y alguna que otra tarea de mantenimiento.
  • De nuevo fue Nort lo que se llevó el grueso de la dedicación, estuve implementando varias historias de usuario relacionadas con edición de perfiles, tanto para la versión web como la móvil.
  • Empezar con la web de Biera Solutions, estuve trabajando en el contenido, que siempre es algo que se me hace difícil.

Buena semana

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

Koalite

Utilizar Chart.js con Knockout.js

August 25, 2014 05:06 AM

Dentro del caótico vibrante mundo de las librerías para Javascript, existen muchas alternativas para mostrar gráficos en pantalla, pero la que más me gusta, por su equilibro entre facilidad de uso y vistosidad de resultados es chart.js.

Micro introducción a Chart.js

En la completa documentación de chart.js podéis encontrar información de sobra para manejarla con soltura, pero para que os hagáis una idea, para mostrar un gráfico de tarta típico sólo hace falta el siguiente código (podéis jugar con él en jsfiddle):

<canvas id="sales-chart" width="400" height="400"></canvas>
var context = document.getElementById('sales-chart').getContext('2d');
var chart = new Chart(context).Pie([
  { label: 'Red', value: 75, color: '#F7464A' },
  { label: 'Not-Red', value: 23, color: '#4D5360' }
]);

Lo único que necesitamos es tener un elemento canvas (como el que usamos para implementar el juego de la vida en Javascript) y crear un objeto Chart sobre él. Este objeto cuenta con distintos métodos para crear cada tipo de gráfico, y cada método recibe dos objetos, uno obligatorio con los datos a mostrar, y otro opcional con la configuración del gráfico (ejes, leyendas, etc.).

Disclaimer

Lo lógico sería haber escrito este post explicando cómo usar Chart.js en una directiva de angularjs que para eso es el framework de moda (con permiso de ReactJS), pero como mi relación con angular está de capa caída y la aplicación donde quería integrarlo usa Knockout.js, ha tocado Knockout.js.

En ningún momento pretendo incentivar el uso de Knockout.js ;-)

Creando un custom binding para Knockout.js

Ya expliqué en su momento cómo crear custom bindings con Knockout.js, así que no me extenderé mucho, pero la idea básica es que podemos añadir nuevas propiedades al objeto ko.bindingHandlers y a través de las funciones init y update indicar cómo debe comportarse nuestro binding.

La estructura es la siguiente:

ko.bindingHandlers.myCustomBinding = {
  init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
    // Función invocada cuando se crea el binding. 
    // Úsala para modificar el DOM, enganchar manejadores de eventos, etc.
  },
  update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
    // Función invocada cada vez que cambia el valor de la propiedad enlazada
    // Úsala para actualizar la información mostrada en el DOM
  }
};

Viendo esto, definir un custom binding no parece muy complicado. Realmente lo más difícil en este caso es decidir cómo queremos construir el API para definir nuestro binding.

Chart.js permite configurar infinidad de parámetros tanto a través de los datos que se le pasan, como a través de las opciones del gráfico, pero para que sea relativamente cómodo de manejar, he optado por crear la siguiente sintaxis:

<canvas width="400" height="400" 
  data-bind="chartType: 'Pie', chartData: quarterSales, chartOptions: salesFormat">
</canvas>

La idea es definir no uno, sino tres bindings para indicar por separado el tipo de gráfico, los datos que queremos mostrar y las opciones del gráfico. Así podremos enlazarlas por separado y, por ejemplo, permitir al usuario mostrar la misma información como gráfico de tarta o de barras, o actualizar la información en tiempo real según se reciben nuevos datos.

El código para implementar esto es el siguiente:

(function(ko, Chart) {

  ko.bindingHandlers.chartType = {
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
      if (!allBindings.has('chartData')) {
        throw Error('chartType must be used in conjunction with chartData and (optionally) chartOptions');
      }
    },
    update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
      var ctx = element.getContext('2d'),
        type = ko.unwrap(valueAccessor()),
        data = ko.unwrap(allBindings.get('chartData')),
        options = ko.unwrap(allBindings.get('chartOptions')) || {},
        chart = new Chart(ctx);

      chart[type](data, options);
    }
  };

  ko.bindingHandlers.chartData = {
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
      if (!allBindings.has('chartType')) {
        throw Error('chartData must be used in conjunction with chartType and (optionally) chartOptions');
      }
    }
  };

  ko.bindingHandlers.chartOptions = {
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
      if (!allBindings.has('chartData') || !allBindings.has('chartType')) {
        throw Error('chartOptions must be used in conjunction with chartType and chartData');
      }
    }
  };

})(ko, Chart);

En realidad, todo el proceso se hace a en el binding chartType, desde el cual podemos acceder a los valores enlazados en chartData y chartOptions a través del objeto allBindings. Los otros dos bindings se limitan a validar que la configuración de bindings es correcta para hacer la cosa un poco más amigable para el usuario.

El código es bastante sencillo, aunque tener que usar ko.unwrap para tratar con los observables de Knockout.js lo ensucia un poco (nadie dijo que Knockout.js fuese bonito). Al final todo se reduce a obtener los valores enlazadas e invocar “dinámicamente” el método del objeto Chart correspondiente al valor enlazado como chartType.

Podéis verlo en funcionamiento (y jugar con él) en este jsfiddle:

El código es tan simple que podéis copiarlo del propio post, pero si lo queréis un poco más limpio, aquí tenéis el código fuente completo.

Una nota final

Hay que tener en cuenta que en el diseño del binding ha primado la comodidad de uso frente a la eficiencia. Tal y como está diseñado, cada vez que se modifica algo del gráfico, éste se redibuja por completo, lo que puede ser un problema si estamos actualizándolo en tiempo real. Chart.js expone métodos optimizados para ese caso de uso y, si te enfrentas a ese escenario, sería bueno echarles un vistazo.

Posts relacionados:

  1. Tutorial jQuery Mobile + Knockout (III): Definiendo el ViewModel con Knockout
  2. Tutorial jQuery Mobile + Knockout (I): Sentando las bases
  3. Tutorial jQuery Mobile + Knockout (y IV): Configurando el Data Binding

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

Blog Bitix

Forzar el uso del protocolo https en Apache Tapestry

August 22, 2014 09:09 AM

Apache Tapestry

El protocolo seguro https hace que los datos que viajan entre el servidor y el cliente a través de internet estén cifrados de modo que nadie más pueda saber cual es es la información intercambiada ni se pueda alterar sin el conocimiento entre las dos partes. Estas propiedades nos son de interés para ciertas partes de una aplicación o en algunos casos la aplicación entera. ¿Cuales son estos casos? Son aquellos en los que queramos garantizar una mayor seguridad, estos pueden ser para proteger usuarios y contraseñas de autenticación para iniciar sesión, ciertos datos sensibles como datos personales, datos de tarjetas de crédito, … evitando que una tercera parte los obtenga y los utilice para su provecho propio y supongan un problema de seguridad en la aplicación.

Es casi obligatorio forzar a que ciertas páginas de una aplicación o página web funcionen mediante el protocolo seguro https como las páginas de inicio de sesión donde los usuarios se autentican normalmente introduciendo su usuario y contraseña, páginas de compra donde los usuarios introducen los datos de su tarjeta de crédito o algunas secciones de una aplicación como las secciones de las cuentas de los usuarios o un backoffice.

En Apache Tapestry hay varias formas de forzar a que una determinada página use el protocolo seguro de modo que si se accede por el protocolo no seguro http la aplicación obligue a usar https haciendo una redirección. Una de ellas es utilizar la anotación @Secure en las páginas que queramos obligar a usar https. Basta con anotar las clases de las páginas con @Secure y Tapestry automáticamente hará la redirección al protocolo https cuando se acceda con http a la página.

<noscript><pre><code>package es.com.blogspot.elblogdepicodev.plugintapestry.pages; ... @Secure public class Login { ... } </code></pre></noscript>

Probablemente nos interese configurar el puerto y el host que usará Tapestry al hacer la redirección para que coincidan con el usado en el servidor al que accede el usuario, sobre todo si en la aplicación usamos un servidor web proxy como apache, lighttpd o nginx delante del servidor de aplicaciones donde realmente se ejecuta la aplicación web. El puerto seguro del protocolo https predeterminado es 443 pero en el servidor de aplicaciones tomcat por defecto es 8443. Esto en tapestry lo indicamos configurando con ciertos símbolos.

<noscript><pre><code>package es.com.blogspot.elblogdepicodev.plugintapestry.services; ... public class AppModule { public static void contributeApplicationDefaults(MappedConfiguration&lt;String, Object&gt; configuration) { ... configuration.add(SymbolConstants.SECURE_ENABLED, true); configuration.add(SymbolConstants.HOSTPORT, 8080); configuration.add(SymbolConstants.HOSTPORT_SECURE, 8443); ... } ... }</code></pre></noscript>

Para probar mientras desarrollamos, al menos en nuestro equipo, que la redirección se hace correctamente empleando el plugin de gradle para tomcat podemos hacer que el servidor de desarrollo se inicie con el puerto https disponible. Para usar https se necesita un certificado digital que el plugin de gradle para tomcat se encarga de generar al iniciar la aplicación, aunque sea autofirmado y el navegador alerte que no lo reconoce como firmado un una autoridad en la que confíe, si lo aceptamos podemos acceder a la aplicación sin más problema. Usando gradle la configuración que podemos emplear es:

<noscript><pre><code>... buildscript { repositories { mavenCentral() jcenter() } dependencies { classpath 'org.gradle.api.plugins:gradle-tomcat-plugin:1.2.4' } } ... tomcat { httpPort = 8080 httpsPort = 8443 enableSSL = true } ...</code></pre></noscript>

La anotación @Secure en Tapestry es suficiente pero podemos hacer lo mismo empleando Shiro. Integrando Shiro con Tapestry nos permite realizar autenticación y autorización, pero además empleando Shiro también podemos obligar a usar el protocolo https del mismo modo que lo hacemos con la anotación Secure. Cualquiera de las dos formas es perfectamente válida y depende más de cual prefiramos. Con la anotación @Secure deberemos anotar cada página, con Shiro podemos tener centralizado en un único punto en que páginas requerimos https. Con Shiro la configuración se hace con una contribución al servicio SecurityConfiguration y usando el método contributeSecurityConfiguration del módulo y la clase SecurityFilterChainFactory y su método ssl(). Un ejemplo es el siguiente:

<noscript><pre><code>package es.com.blogspot.elblogdepicodev.plugintapestry.services; ... public class AppModule { .... public static void contributeSecurityConfiguration(Configuration&lt;SecurityFilterChain&gt; configuration, SecurityFilterChainFactory factory) { configuration.add(factory.createChain(&quot;/admin/**&quot;).add(factory.authc()).add(factory.ssl()).build()); } .... } </code></pre></noscript>

En cualquiera de los dos casos mostrados en este ejemplo se obliga a usar https en la página de login:

El ejemplo completo puede encontrarse en la aplicación del libro PlugIn Tapestry que puedes descargar y probar de mi repositorio de GitHub. Por supuesto también puedes descargar el libro PlugIn Tapestry si quieres conocer de forma más profunda cuales son las características y como funciona Apache Tapestry.

Referencia:
Configurar SSL en un servidor Tomcat, JBoss, WildFly, Lighttpd, nginx o Apache
Generar y convertir claves y certificados con OpenSSL
Libro PlugIn Tapestry

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

Arragonán

Semana 323

August 18, 2014 10:13 PM

Como todos los meses de agosto, que cantaban los Ixo Rai, llega la semana del puente del 15 de agosto donde son fiestas en muchos pueblos, entre ellos en el mío. Y claro, como las fiestas del pueblo de uno no hay, hay que estar y por eso me tomé festiva la segunda mitad de la semana.

Calle Estaño

Antes de entrar en la realidad paralela que son unas fiestas de pueblo, saqué ratos para empezar a mover la organización de una charla de CachiruloValley a inicios de septiembre. También saqué un rato para pegarle un vistazo a oDesk y completar un poco mi perfil, por ahora muy poco tiempo y sigo sin tener opinión de qué tal es como fuente de proyectos, pero conozco a varios freelancers que les funcionan bastante bien estos servicios de intermediación.

En cuanto a proyectos, algún mail respecto a otros, pero en realidad sólo le di una dedicación seria a Nort:

  • Estuve trabajando tanto en la aplicación móvil, puliendo y refactorizando para hacer el merge de la rama, como en la aplicación web comenzando con una nueva feature. Además la semana pasada tocaba hacer demo al cliente.

Buena semana.

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

Ingenieria de Software / Software Engineering / Project Management / Business Process Management

Tracking Projects

August 18, 2014 08:34 PM

Es muy fácil que como PM nos perdamos en el día a día, en lo urgente y no en lo importante pero es vital que los PMs den un seguimiento adecuado a sus proyectos a través de sus principales métricas como son los riesgos. Aquí un buen artículo con algunos tips.


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

Picando Código

RubyConf Argentina 2014 – Entradas Pajarito y Convocatoria a charlas

August 13, 2014 03:22 PM

RubyConf ArgentinaYa están a la venta las entradas Pajarito ($ 650 pesos argentinos) de una de las mejores conferencias de Ruby del universo conocido: RubyConf Argentina. La conferencia se realiza el 24 y 25 de Octubre en el Centro Cultural Konex en Buenos Aires.

RubyConf Argentina es uno de los mayores eventos de sudamérica sobre desarrollo de software, donde más de 450 desarrolladores se reúnen para aprender, discutir y compartir ideas sobre software libre, web, aplicaciones móviles, seguridad, robótica, y mucho más.

La conferencia reune rubistas y no rubistas de todas partes del mundo, y es una de las puertas de entrada más directas a la cariñosa y cálida comunidad Ruby de América Latina. Va a ser la tercera edición a la que voy, y desde un principio la disfruté como si fuera mi navidad. Recomendada ampliamente.

Como comentaba más arriba están disponibles las entradas a precios promocionales que pueden ir comprando acá. Por otro lado, está abierto el llamado a charlas, así que si tienen ganas de presentar algo para hablar en la conferencia, es su oportunidad.

Uruguayos interesados en cruzar el charco para asistir a la conferencia somos varios. Desde la comunidad de rubistas estamos alentando a más gente a unirse a nosotros y sumarse a la ida en masa al Centro Cultural Konex. De repente conseguimos algun descuento en transporte y alojamiento al ser muchos. Así que si consideraban ir a RubyConf Argentina pero tenían dudas, ya no hay excusas, contáctennos, súmense al meetup, y vénganse con nosotros a RubyConf Argentina \o/

Office Space

 

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

Arragonán

Semanas 321 y 322

August 12, 2014 05:26 PM

No, no es que haya estado de vacaciones, que por aquí aún se van a hacer esperar al menos un par de meses; aunque algún día suelto caerá, habiendo compromisos ya se sabe como es la vida del autónomo. Y ahí va nueva retro, quincenal otra vez.

Esta vez empecé en Noja hace 2 semanas, viaje para trabajar en la conceptualización de un nuevo proyecto y definir el alcance de un pequeño MVP inicial, estuve asimilando lo que hace una herramienta offline para pasar parte de su funcionamiento al online. Por el momento no puedo decir gran cosa de la temática, como mínimo hasta Septiembre.

Después estuve en Bilbao un par de días, trabajando en las oficinas de mhop y en las de init. Aprovechando también para ver gente, al ser verano estaba claro que iba a ser más complicado encontrarse con muchos; pero aún nos juntamos unos cuantos del gremio a tomar unos zuritos y unos pintxos.

A la vuelta a Zaragoza y sin mucho descanso, como todos los últimos jueves del mes, había zaragozarb, en esta ocasión con una charla/resumen del Rails Open Space que organizó AspGems. Y el finde estuve de visita en mi pueblo, que necesitaba recuperar tras una semana bastante agotadora… aunque terminé hablando de posibles proyectos.

La siguiente semana fue bastante más tranquila, que los viajes me descolocan bastante, ya no estoy acostumbrado de ir de aquí para allá. Saqué tiempo para pasarme a trabajar un rato por por The Garage Of Code, al fin, que hacía mucho que tenía pendiente pasar a visitar su oficina y asistí a las GeeksTalks de este mes.

Sobre proyectos actuales, aparte del que estuvimos conceptualizando:

  • En mhop trabajé en resolver un par de bugs, implementado algunas pequeñas funcionalidades demandadas desde gestión de contenidos y estuve haciendo modificaciones en la gestión de productos por parte de los diseñadores.
  • Estuvimos viendo los cambios en la nueva landing de minchador y estuve hablando con algunos restaurantes. Desde luego que son malas fechas para los restaurantes con los que he hablado: o están de temporada alta o están cerrados/van a cerrar en Agosto. Que no están por la labor, vamos.
  • El grueso de mi dedicación fue de nuevo para Nort. La mayor parte trabajando en la aplicación móvil, principalmente para acceder a varias características nativas y teniendo que usar varios plugins de Apache Cordova para ello. También me tocó hacer algunos pequeños cambios en la aplicación Grails para ajustar algunas cosas del backend.
  • Dediqué algo de tiempo en sentarme a trabajar en la web de Biera Solutions. Empezar a definir objetivos y hacer algunos bocetos en papel para trabajar algunas ideas.

Buena semana.

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

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

PhpStorm

August 10, 2014 08:14 AM

En contra de lo que su nombre parece indicar, PhpStorm, no es solamente un entorno de desarrollo PHP, sino que además soporta desarrollo web en general. Es decir, combina las WebStorm con funcionalidades específicas para PHP. Parte de la misma base de WebStorm, por lo que mucha de las cosas que ya viéramos se siguen [...]

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

Cuaderno de software

¿Scrum o Kanban?

August 08, 2014 06:23 AM

TL; DR: Scrum y Kanban. Se complementan.

Habitualmente cuando participo en una conversación donde se afirman cosas como “yo prefiero Scrum”, pues yo prefiero “Kanban” lo que realmente se suele estar diciendo es “a mí me gusta hacer sprints”, “pues yo prefiero no hacerlos”. Si rascas un poco, resulta que el “equipo kanban” hace retrospectivas y el “equipo scrum” tiene un panel visualizando el Value Stream Map.

Según voy practicando y profundizando en Scrum, Kanban o lo que sea, voy cambiando mi visión sobre en qué consiste exactamente la técnica. Esto me ocurre a todos los niveles y todo el rato. Y me seguirá ocurriendo hasta el fin de los tiempos. En concreto, ahora mismo de Scrum y Kanban pienso lo siguiente:

kanban

scrum

Si eres de los que todavía mantiene peleas internas(o externas) sobre si aplicar Scrum o aplicar Kanban porque piensas que son diferentes sabores del agilismo, que sepas que desde mi punto de vista son totalmente combinables. Sobre como se relacionan o si son combinables, por supuesto, hay mucho escrito:

 

 

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

Picando Código

Por Mi Barrio – Aplicación para mejorar Montevideo de un clic a la vez

August 07, 2014 04:00 PM

Persiguiendo su objetivo de hacer del mundo un lugar mejor, el grupo de super héroes conocido como Los Veng… D. A. T. A. presentó la aplicación Por Mi Barrio, aplicación basada en el software libre Fix My Street de My Society.

¿Recuerdan todas esas veces que gritaron a los cuatro vientos al encontrar un pozo enorme andando en bicicleta o un caño roto desperdiciando agua a litros o un semáforo que estuvo sin funcionar durante días? Por Mi Barrio es la aplicación que pone al alcance de un clic el poder de hacer algo productivo con esa queja al viento.

Por Mi Barrio

Por Mi Barrio

Del sitio web de D.A.T.A.:

Por Mi Barrio, una plataforma que permitirá a las personas que viven en Montevideo enviar reportes sobre daños, desperfectos, vandalismo y otros problemas de nuestra ciudad desde su computadora o celular.

Es decir, cuando encuentres un problema en tu barrio (un pozo en la calle, problemas de arbolado o de iluminación, contenedores de basura rotos, etc.) vas a poder entrar en pormibarrio.uy desde tu computadora (ceibalitas incluidas) o celular y reportarlo. Para hacer esto, sólo tenés que localizar el problema en un mapa. También se pueden subir fotos y comentarios.

Cuando vuelvas a entrar a la página web vas a poder ver tu reporte marcado en un mapa, así como los de los/as demás usuarios/as. También podrás ver los reportes que la Intendencia de Montevideo (IM) marcó como solucionados y los que todavía son problemas para el barrio.

Por Mi Barrio se conecta al Sistema Único de Reclamos de la IM, por lo que se asegura que los reportes denunciados van a llegar a la división correspondiente de la comuna y permite recibir notificaciones sobre respuestas de la IM. ¿Se dan cuenta el poder que le brinda a los ciudadanos? Al reportar los incidentes, los ciudadanos obtienen total transparencia en el progreso del reporte, teniendo visibilidad sobre el trabajo de su gobierno local. Con herramientas como esta, no hay excusas para no involucrarse y formar parte de la sociedad civil.

El proyecto es parte de una iniciativa a mayor escala, así que probablemente habrán novedades entorno al proyecto y se irán viendo proyectos similares. Cuanto más gente lo use, mejor.

Pueden mantenerse al tanto de las noticias de DATA en su sitio web o su cuenta de Twitter.

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

Picando Código

Middleman: Generador de sitios web estáticos

August 06, 2014 04:00 PM

fernandobriano.com

fernandobriano.com

Vengo usando mi sitio personal como “tarjeta de presentación” desde hace un buen tiempo, para dirigir potenciales relaciones laborales a ese sitio. Hace mucho que venía con ganas de actualizarlo así que volví a arrancar de cero (por tercera o cuarta vez).

El contenido es bastante simple, debía ser un sitio que mostrara parte de mi trabajo y experiencia de manera sencilla y directa. No inclui mi CV. Tengo perfiles en LinkedIn y StackOverflow Careers, por lo que mostrar un CV online implica repetir información que ya está en otros lugares. Con cada cambio debería mantener la información actualizada en varios sitios. Así que agregué los links.

También agregué el link a GitHub, donde se puede ver gran parte del trabajo Open Source que he hecho, y otros perfiles online como Lanyrd o Speakerdeck. Las empresas se están acostumbrando a  que pueden encontrar mucha información de un programador online sin tener que pedir específicamente un archivo PDF con la especificación técnica de la persona.

Sería interesante interactuar con la API de LinkedIn o StackOverflow Careers (si la tiene), para tener un CV actualizado “dinámicamente”. Es algo a pensar, junto a la cantidad indeterminada de veces que pienso en borrar mi perfil de LinkedIn en el día. No me aporta mucho más que Spam de gente que no conozco y con la que nunca tuve relación laboral agregándome con el mensaje por defecto de “Me gustaría agregarte a mi red profesional” o algo así. En un momento pensé empezar a responder a cada una de las “invitaciones” con un simple: “¿Por qué?”, pero seguro encuentro cosas mejores que hacer con mi tiempo.

Desde la parte técnica, aprovecho cada reboot de mi sitio personal para usar al menos una tecnología que no conociera de antes. Mi caso de uso era bastante sencillo:

  • HAML para el HTML (por preferencia personal nomás)
  • Markdown para el contenido (ídem anterior)
  • Contenido internacionalizado para Inglés y Español
  • No voy a actualizar el sitio tan seguido ni tengo tanta información, un CMS o similar es demasiado
  • Tiene que ser rápido – El CSS y (en caso de usarlo) JavaScript debe ser lo mínimo necesario.

Tecnología

Vamos a las decisiones tecnológicas que tomé y el por qué. Para empezar, decidí que iba a usar Cuba y me iba a armar un “mini-cms” como para mantener el sitio actualizado cuando quiera agregar alguna cosa nueva. El sitio era una aplicación Sinatra alojada en Heroku. No usaba base de datos, al ser poco el contenido se encontraba en archivos de texto (yml). Así que empezar de cero con Cuba no iba a cambiar mucho el tema de hosting, podía usar Postgres o alguna otra cosa en Heroku.

A mitad de camino volví a pensar en generadores de sitios estáticos. Ya había hecho algunas pruebas antes con Jekyll, y empecé a leer sobre Middleman. Navegando un poco por la documentación, me decidí a usarlo. Al producir páginas estáticas, podía alojar el sitio en GitHub Pages en vez de Heroku. De esta forma, dependo de un repo menos.

ruby-middleman

Templates

Middleman soporta templates Slim, ERB, HAML y más. También trae soporte para Markdown con distintos motores, así que resolvía dos de las cosas que quería en el sitio. Trae también soporte para partials y Template Helpers que nos facilitan algunas tareas y definir helpers propios es bastante sencillo. En mi caso usé los helpers propios para incluir algunos fragmentos de código Ruby que tenía por ahí para recuperar información de distintos sitios: RubyGems, GitHub y WordPress.

Esto genera una lista “dinámica” obteniendo información de cosas que he publicado (gemas, plugins, repos) y lo muestra en el sitio.

Contenido

Haml es malo para escribir contenido, y prefiero usar Markdown siempre que puedo. La idea era combinar estas dos cosas con la internacionalización. Así que el contenido se encuentra en archivos yml correspondientes a los locales ‘es’ y ‘en’ para español e inglés respectivamente. Al usar i18n, llamamos a los textos con el método t(:clave_del_texto). El siguiente paso era parsear el texto como markdown, por lo que hice un helper parecido llamado text, con el cual renderizo como Markdown lo que me devuelve el método t:

def text(string)
  markdown = Redcarpet::Markdown.new(
                                     Redcarpet::Render::HTML,
                                     autolink: true,
                                     no_intra_emphasis: true,
                                     lax_spacing: true)
  markdown.render(t(string))
end

CSS y JavaScript

El CSS es muy sencillo, menos de 200 líneas aunque inclui el framework SimpleGrid para las grillas y diseño responsivo. Otras veces había usado PureCSS, pero decidí usar algo distinto esta vez. También agregué los íconos de Octicons y Genericons para darle algo más de vida al sitio.

Middleman incluye Sprockets, un sistema de empaquetamiento de recursos (CSS, JavaScript, CoffeeScript). Permite incluir otros archivos en uno, empaquetándolos y minificándolos (opcionalmente) a un solo archivo. De esta forma, puedo incluir simplegrid.css, octicons.css y genericons.css en mi archivo css principal con las siguientes sentencias:

/*
 *= require _simplegrid
 *= require _octicons.css
 *= require _genericons.css
 */

Al agregar el guión bajo antes del nombre de cada archivo, estoy pidiendo que los contenidos de ese css sean concatenados al contenido de mi css para tener todo en un mismo archivo.

Lo mismo se puede hacer con JavaScript. Lo bueno de esto es que a pesar de tener muy poco código, puedo organizarlo en archivos distintos. Y nada de esto afecta al rendimiento final del sitio ya que todo el contenido se va a servir como recursos estáticos generados previamente.

Publicación en GitHub Pages

Una parte que le falta al código es la generación automática de los archivos estáticos de manera periódica. Por ahora estoy usando la gema middleman-gh-pages desarrollada por algunos ex Neo y otros desarrolladores de la comunidad. La funcionalidad básica que provee la gema, es una tarea Rake para poder publicar a la branch gh-pages en GitHub con un único comando:

$ rake publish

Conclusión

Llegué a un proceso de actualización bastante dinámico y el resultado con un sitio estático alojado en GitHub Pages es suficientemente bueno. Cumple su cometido de ser un centro de enlaces a distintos recursos que permitirían a potenciales colegas o contratadores conocer un poco sobre mi perfil laboral.

El resultado final está en fernandobriano.com y el código fuente en GitHub. Cosas para mejorar siempre hay, ya habrá tiempo para eso :)

 

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

Cuaderno de software

El problema al escribir

August 06, 2014 06:20 AM

Lo hablaba ayer con David:

  • mientras no sé, es cuando tengo el cerebro a tope y me apetece escribir. Entonces escribo sobre lo que no sé.
  • cuando ya sé, no me da ninguna vidilla escribir. No escribo sobre lo que realmente sé.
  • si escribo cosas complicadas y sesudas, no explico los conceptos en los que baso, y no se entiende.
  • si escribo sobre los conceptos básicos, siento que el post es demasiado básico como para ser útil….

Y así, todo el día… :-P

Mi conclusión es que prefiero escribir, aunque sea artículos tontainas como éste, pero intentar mantener un flujo continuo de artículos que me ayuden a ir rumiando ideas e ir contrastándolas con la gente…

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

Poesía Binaria

Deadlock, bloqueo mutuo, abrazo mortal o cómo colgar un proceso con esperas infinitas. ☠ ☠ ☠

August 05, 2014 08:49 AM


Es un ejercicio típico, pero que casi siempre se ve teóricamente, pero mira, vamos a traerlo a la práctica. Lo vamos a implementar con semáforos. Como vemos aquí y aquí, los semáforos, entre otras cosas nos servirán para bloquear un proceso o un thread que trata de acceder a un recurso crítico que está siendo usado por otro proceso, un ejemplo típico es un baño público, cuando la puerta no está bloqueada, pasas, la bloqueas, haces lo que tengas que hacer allí, y luego desbloqueas la puerta y te vas. Aquí todo funciona parecido, cuando tienes que acceder a un recurso, miras si el semáforo está abierto, y si es así, lo cierras, utilizas ese recurso y cuando terminas lo abres.
Pero claro, podemos crear todos los semáforos que queramos y tenemos total libertad para hacer que los procesos esperen que los semáforos estén abiertos o los abran, por lo que podemos crear multitud de situaciones.

Pero claro, ¿qué puede pasar si tenemos tres procesos (P1, P2 y P3) y se da el caso en el que P1 esté esperando a P2, P2 esté esperando a P3 y P3 esté esperando a P1? Pues nada, estaremos esperando indefinidamente.
El caso típico es el siguiente:

  • Tenemos dos procesos (P1 y P2)
  • Tenemos dos recursos (R1 y R2) de acceso exclusivo (sólo pueden ser accedidas por un proceso cada vez)
  • P1 quiere acceder a R1 por lo tanto cierra su semáforo
  • P2 quiere acceder a R2 por lo tanto cierra su semáforo
  • P1 quiere acceder también a R2 por lo que espera a que su semáforo esté abierto
  • P2 quiere acceder también a R1 por lo que espera a que su semáforo esté abierto

Como P1 está esperando a que P2 libere el semáforo de R2 y P2 está esperando a que P1 libere el semáforo de R1, los dos se van a quedar indefinidamente así.

Si queremos comprobarlo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <sys/mman.h>
#include <semaphore.h>
#include <string.h>

int main()
{
  sem_t *sem1 = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE,
             MAP_SHARED | MAP_ANONYMOUS, -1, 0);
  sem_t *sem2 = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE,
             MAP_SHARED | MAP_ANONYMOUS, -1, 0);

  int child;

  sem_init (sem1, 1, 1);
  sem_init (sem2, 1, 1);

  child = fork();
  if (child==-1)
    exit(1);
  else if (child==0)
    {
      while(1)
    {
      printf ("[%d] Child waits for sem1...\n", getpid());
      sem_wait(sem1);
      printf ("[%d] Child passes sem1.\n", getpid());
      printf ("[%d] Child waits for sem2...\n", getpid());
      sem_wait(sem2);
      printf ("[%d] Child passes sem2.\n", getpid());
      usleep(100);
      printf ("[%d] Child posts sem2\n", getpid());
      sem_post(sem2);
      printf ("[%d] Child posts sem1\n", getpid());
      sem_post(sem1);
    }
      exit(2);
    }
  else
    {
      while(1)
    {
      printf ("[%d] Main waits for sem2...\n", getpid());
      sem_wait(sem2);
      printf ("[%d] Main passes sem2.\n", getpid());
      printf ("[%d] Main waits for sem1...\n", getpid());
      sem_wait(sem1);
      printf ("[%d] Main passes sem1.\n", getpid());
      usleep(100);
      printf ("[%d] Main posts sem1\n", getpid());
      sem_post(sem1);
      printf ("[%d] Main posts sem2\n", getpid());
      sem_post(sem2);
    }
    }
  while (wait(NULL)>=0);

  munmap(sem1, sizeof(sem_t));
  munmap(sem2, sizeof(sem_t));

  return 0;
}

Si compilamos (con pthread: gcc -o deadlock deadlock.c -lpthread) veremos algo como esto:

$ ./deadlock
[30643] Main waits for sem2…
[30643] Main passes sem2.
[30643] Main waits for sem1…
[30643] Main passes sem1.
[30644] Child waits for sem1…
[30643] Main posts sem1
[30643] Main posts sem2
[30643] Main waits for sem2…
[30643] Main passes sem2.
[30644] Child passes sem1.
[30643] Main waits for sem1…
[30644] Child waits for sem2…

También es verdad que no siempre es tan rápido, a veces pueden darse muchas iteraciones hasta que se produce el bloqueo, otras veces a la primera iteración se produce, depende de cómo de rápidos sean los procesos, pero tarde o temprano se va a dar. Para más información sobre esto, tenemos la página de Wikipedia.

Para dar algo de teoría, en este ejemplo se han cumplido las 4 condiciones necesarias (tienen que cumplirse todas ellas) de Coffman:

  • Exclusión mutua: Los recursos R1 y R2 son exclusivos, sólo pueden ser accedidos por un proceso cada vez
  • Retención y espera: P1 ha adquirido un recurso R1 y lo retiene mientras espera a que R2 (adquirido por P2) se libere
  • No expropiación: P1, por ejemplo, no puede quitarle R2 a P2 ni al revés.
  • Espera circular: P1 está esperando a P2 y P2 espera a P1.

¿Cómo lo arreglamos?
Aquí podemos buscar tantas soluciones como nos dé la imaginación, pero vamos a proponer algunas más típicas:

Guardar el orden de reserva de recursos

Si siempre vamos a utilizar R1 y R2, los pedimos siempre en el mismo orden:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
...
  child = fork();
  if (child==-1)
    exit(1);
  else if (child==0)
    {
      while(1)
    {
      printf ("[%d] Child waits for sem1...\n", getpid());
      sem_wait(sem1);
      printf ("[%d] Child passes sem1.\n", getpid());
      printf ("[%d] Child waits for sem2...\n", getpid());
      sem_wait(sem2);
      printf ("[%d] Child passes sem2.\n", getpid());
      usleep(100);
      printf ("[%d] Child posts sem2\n", getpid());
      sem_post(sem2);
      printf ("[%d] Child posts sem1\n", getpid());
      sem_post(sem1);
    }
      exit(2);
    }
  else
    {
      while(1)
    {
      printf ("[%d] Main waits for sem1...\n", getpid());
      sem_wait(sem1);
      printf ("[%d] Main passes sem1.\n", getpid());
      printf ("[%d] Main waits for sem2...\n", getpid());
      sem_wait(sem2);
      printf ("[%d] Main passes sem2.\n", getpid());
      usleep(100);
      printf ("[%d] Main posts sem2\n", getpid());
      sem_post(sem2);
      printf ("[%d] Main posts sem1\n", getpid());
      sem_post(sem1);
    }
    }
...

No liarla demasiado

Utilizar la mínima cantidad de semáforos posible, si vemos que con sólo uno basta, pues ponemos uno. En este caso sí bastaría con uno, pero habrá casos en los que no se pueda y tendremos que hacer otras cosas…

Si se puede se puede, si no, no

Consiste en utilizar sem_trywait(), si el recurso está ocupado devolverá error, pero no bloqueará. Sólo haciéndolo en uno de los procesos vale, pero claro este proceso entrará menos veces en la sección crítica:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
...
  child = fork();
  if (child==-1)
    exit(1);
  else if (child==0)
    {
      while(1)
    {
      printf ("[%d] Child waits for sem1...\n", getpid());
      sem_wait(sem1);
      printf ("[%d] Child passes sem1.\n", getpid());
      printf ("[%d] Child waits for sem2...\n", getpid());
      try = sem_trywait(sem2);
      if (try==0)
        {
          printf ("[%d] Child passes sem2.\n", getpid());
          usleep(100);
          printf ("[%d] Child posts sem2\n", getpid());
          sem_post(sem2);
        }
      else
        printf ("[%d] sem2 busy\n", getpid());
      printf ("[%d] Child posts sem1\n", getpid());
      sem_post(sem1);
    }
      exit(2);
    }
  else
    {
      while(1)
    {
      printf ("[%d] Main waits for sem2...\n", getpid());
      sem_wait(sem2);
      printf ("[%d] Main passes sem2.\n", getpid());
      printf ("[%d] Main waits for sem1...\n", getpid());
      sem_wait(sem1);
      printf ("[%d] Main passes sem1.\n", getpid());
      usleep(100);
      printf ("[%d] Main posts sem1\n", getpid());
      sem_post(sem1);
      printf ("[%d] Main posts sem2\n", getpid());
      sem_post(sem2);
    }
    }
...

Timeouts

De la misma forma que probamos si estaba disponible el recurso o no, ahora probamos con un timeout, hacemos que el proceso sea capaz de esperar un tiempo a ver si el recurso se libera, aunque pasado ese tiempo dejará de esperar:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
  child = fork();
  if (child==-1)
    exit(1);
  else if (child==0)
    {
      while(1)
    {
      printf ("[%d] Child waits for sem1...\n", getpid());
      sem_wait(sem1);
      printf ("[%d] Child passes sem1.\n", getpid());
      printf ("[%d] Child waits for sem2...\n", getpid());
      timeout.tv_sec=0;
      timeout.tv_nsec=100000;
      try = sem_timedwait(sem2, &timeout);
      if (try==0)
        {
          printf ("[%d] Child passes sem2.\n", getpid());
          usleep(100);
          printf ("[%d] Child posts sem2\n", getpid());
          sem_post(sem2);
        }
      else
        printf ("[%d] sem2 busy\n", getpid());
      printf ("[%d] Child posts sem1\n", getpid());
      sem_post(sem1);
    }
      exit(2);
    }
  else
    {
      while(1)
    {
      printf ("[%d] Main waits for sem2...\n", getpid());
      sem_wait(sem2);
      printf ("[%d] Main passes sem2.\n", getpid());
      printf ("[%d] Main waits for sem1...\n", getpid());
      sem_wait(sem1);
      printf ("[%d] Main passes sem1.\n", getpid());
      usleep(100);
      printf ("[%d] Main posts sem1\n", getpid());
      sem_post(sem1);
      printf ("[%d] Main posts sem2\n", getpid());
      sem_post(sem2);
    }
    }

Aquí con un struct timespect timeout donde ponemos el tiempo en nanosegundos (variable tv_nsec) creamos una espera de un tiempo máximo para el recurso reservado.

Otros algoritmos

Para solucionar esto, dependiendo de los casos tenemos otros algoritmos, que espero dedicar posts próximamente.
Foto: Moosealope (Flickr) CC-by

La entrada Deadlock, bloqueo mutuo, abrazo mortal o cómo colgar un proceso con esperas infinitas. ☠ ☠ ☠ aparece primero en Poesía Binaria.

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

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

La apuesta de Fortran

August 04, 2014 06:56 AM

Si os digo que FORTRAN (Formula Translating System) fue un lenguaje diseñado por IBM en los años 50 para poder realizar programas científicos que resultaran eficientes, probablemente no os estaré contando nada que no sepáis. En aquellos años solamente existía el ensamblador, y Fortran representaba el primer lenguaje más o menos estandarizado de alto nivel. [...]

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

Cuaderno de software

Por qué no voy a usar Chef (por ahora)

August 02, 2014 10:14 AM

Infrastructure as code, mantener todos los cambios en tus servidores bajo control completo, configurar tus servidores escribiendo recetas, tener tu infraestructura en tu sistema de control de versiones, que tus desarrolladores puedan utilizar una máquina igual que la de producción en su equipo para evitar el “en mi máquina funciona”.
Bien, compro. ¿Donde hay que firmar?. Take my money.
Pero no. Por ahora no.

Te invito a hacerte estas preguntas, que yo me hice demasiado tarde:
-¿Cada cuanto tiempo levantas un servidor nuevo?
Nosotros usamos Amazon AWS, si, es cloud, pero eso no quiere decir que andemos escalando y desescalando nuestra arquitectura cada 15 minutos. Además, cuando necesito un servidor igual que el de producción levanto una imagen del propio servidor de producción. Además nuestras aplicaciones no están preparadas para escalar horizontalmente por ahora, nuestros servidores no son servidores stateless.
-¿Cuanto tiempo te lleva configurar un servidor nuevo?
A día de hoy, un servidor para correr un stack LAMP es relativamente trivial, con mantener el fichero de configuración de Apache en un control de versiones tendrías todo bastante avanzado. Para software mas complejo como stacks Java tras un Tomcat y un Apache la cosa no es mucho mas complicada y si lanzas un producto cada 6 meses puede que escribir la receta te lleve mas tiempo.
-¿Cuanto tiene que cambiar tu equipo de desarrollo para que todo esto funcione correctamente?¿Qué les aporta a tus desarrolladores disponer de un entorno igual al de producción en su máquina? y por último ¿podrian levantar un entorno de esas características en sus máquinas?
Si trabajas con lenguajes interpretados y demás (PHP por ejemplo) es muy bonito, levantas una máquina compartes la carpeta en la que va el código apuntas tu IDE a dicha carpeta y voilá, pero ¿y si trabajas con Java? ¿para debuggear como lo haces? puedes levantar el Tomcat en modo debug o abrir el puerto, pero ya estás empezando a modificar la máquina y no se parecerá tanto a la máquina de producción.
Si tu producto es la conjunción de una serie de productos ¿haces levantar al desarrollador tus API, tu servicio de SSO…?
-¿Cuanto te va a costar formar a la gente suficiente para que esto sea sostenible?
Infrastructure as code es un matrimonio en toda regla, te comprometes estrictamente a gestionar tu infraestructura de esta manera ya que sino las incosistencias te volverán loco (hay textos que sugieren que ni siquiera te proporciones acceso SSH a tus propios servidores para evitar tocar a mano).

A día de hoy, estas barreras no me aportan la suficiente mejora sobre lo que tengo hasta ahora, me supone mas problema mantener bajo control los ficheros de configuración de mi aplicación que el software que instalo en mis máquinas. Me ha resultado muy costoso adaptar toda la infraestructura ya existente a “recetas” que pudiesen crearla desde cero y no solo eso, sinó que los servidores que ya he instalado “a mano” tendrian que entrar en dicho ciclo o bien debería levantarlos en paralelo con las nuevas recetas y hacer el switch, por ahora el beneficio no me justifica el riesgo.

Pero ojo, evidentemente y si tanto se oye hablar de ello, por algo será y he visto muy buenas motivaciones para adoptar estas técnicas y tecnologías.
-Imagina que realizas instalaciones en servidores alojados en las instalaciones de tus clientes (appliance), tener perfectamente controladas las versiones y modificaciones que realizas en todos y cada uno, poder propagar los cambios basados en roles u otras características.
-Necesitas levantar máquinas automáticamente en un proveedor de hosting que no te proporcione características como la creación de imágenes personalizadas para poder escalar horizontalmente.
-Si tu stack tecnológico te lo permite para trabajar en local, en uno de nuestros proyectos el stack encajaba muy bien y con esto hemos proporcionado a los desarrolladores una manera de probar en un servidor con la misma configuración que el de producción todo el producto.

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

Cuaderno de software

Mi página web va lenta

August 02, 2014 09:47 AM

IMG_20140802_110438

Repaso en voz alta los diferentes pasos a la hora de servir una web (lo siento pero no soy capaz de dibujar con un ordenador con la misma comodidad que lo hago con papel y boli):

t0: tiempo de envío de la petición desde el navegador al servidor, desde que hacemos click hasta que dicha petición llega al servidor, este factor es ajeno a la web como tal, pero hay que saber identificarlo porque el problema estará en la conexión del usuario y por lo tanto no tendrá que ver con nuestra aplicación directamente.
t1: tiempo de procesado de la petición, primera fase de la petición, recepción de petición, cookies y demás información, procesado de esta, checkeo de la corrección, los factores que pueden influenciar en ella son: código que es demasiado lento o hardware que no soporta el número de peticiones o tipo de peticiones que se reciben.
t2: tiempo para enviar la petición desde el código hasta el sistema de persistencia (generalmente una BBDD). Es habitual que el código y la información no estén en la misma máquina, en ese momento la conectividad entre estas es un punto mas a medir, es un problema de red.
t3: tiempo de procesado de los datos en el sistema de persistencia. ¿Que tipo de consultas hacemos a la BBDD? ¿pedimos sólo lo que necesitamos? ¿está la consulta hecha de la mejor manera? ¿están los datos estructurados de la mejor manera? Si recibo los datos con frecuencia de quince minutos pero solo permito consultarlos por franjas horarias (el datepicker de la interfaz no hila mas fino) ¿tiene sentido almacenar un registro por cada 15 minutos?

timestamp0,16:00,v0
timestamp1,16:15,v1
timestamp2,16:30,v2
timestamp3,16:45,v3

Vs.

timestamp0,16:00,{v0,v1,v2,v3}

En este sencillo ejemplo, en la segunda estructura se “buceará” entre 1/4 del número de registros (extrapolemos el mismo caso para registros minutales o segundales) para obtener la misma información que si se bucease en la primera. Esta decisión está relacionada con las estructuras de la información (inferidas de un entendimiento claro de la solución que queremos dar al cliente), de una consulta correcta al sistema de persistencia y por último del hardware.
t4: devolución de datos al código, aquí entran dos factores, la red, como en el momento del envío de la query y por otro lado el volúmen de datos que se devuelvan (v4), si volvemos al ejemplo del punto t3 el volúmen de datos a transferir será menor. Aquí tendremos que buscar la relación correcta entre lo que cueste conseguir los datos lo mas filtrados posible y el volumen que nos permita transferir el ancho de banda en un tiempo aceptable.
t5: procesado de datos para generar la respuesta, se trata de un problema de código intimamente relacionado con el volumen de datos que haya llegado del sistema de persistencia, habrá ocasiones en las que traer mas datos y procesarlos por código sea mas interesante que traer los datos estrictamente necesarios a costa de haber trasladado demasiada carga al sistema de persistencia, es un problema de código y hardware.
t6: tiempo de devolución de datos, se trata del volumen de información (v6) que se envía al navegador, cuanto menor mejor evidentemente, aquí influye nuestro código y también el ancho de banda.
t7: tiempo de renderizado en el navegador, si enviamos mucha información al navegador en un formato que depués deba ser procesada (una librería de graficado JS a la que servimos listas de puntos) tendremos esa sensación de “la página ha cargado pero no veo nada”.
#: número de consultas al sistema de persistencia que se realizan para poder obtener toda la información del sistema de persistencia, aquí hay que realizar las pertinentes pruebas para cada caso, hay veces que 5 consultas sencillas serán mas rápidas que una consulta compleja (clásicos JOIN en BBDD relacionales que unen tablas de tamaños bestiales para ahorrar hacer unas pocas queries contra tabla única). He marcado este punto en rojo porque aquí hay un problema serio con el código, la utilización de grandes librerias de acceso a datos a veces genera una “niebla” sobre lo que realmente ocurre con nuestra BBDD. Un caso real es el del borrado de todos los hombres de una tabla usuarios que dispone de celda sexo que se realizó obteniendo los id únicos de cada usuario de sexo hombre para realizar el borrado en lugar de un simple borrado por sexo.

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

Picando Código

Defensa personal del correo electrónico

August 01, 2014 02:00 PM

Recupera tu privacidad con GnuPg

Recupera tu privacidad con GnuPg

La vigilancia indiscriminada viola nuestros derechos fundamentales y pone en peligro la libertad de expresión. Esta guía te enseñará una destreza básica de la defensa personal contra la vigilancia: el cifrado del correo electrónico. Una vez la hayas finalizado, serás capaz de enviar y recibir correos electrónicos codificados para evitar que un vigilante o un ladrón que intercepte tu correo electrónico pueda leerlo. Todo lo que necesitas es una computadora con conexión a Internet, una cuenta de correo electrónico y aproximadamente media hora.

Incluso si no tienes nada que esconder, el cifrado ayuda a proteger la privacidad de las personas con las que te comunicas, y les pone las cosas difíciles a los sistemas de vigilancia indiscriminada. Si tienes algo importante que esconder, estás en buena compañía: estas son las mismas herramientas que utilizó Edward Snowden para compartir sus famosos secretos sobre la NSA.

Además de utilizar el cifrado, hacer frente a la vigilancia requiere una lucha política para reducir la cantidad de datos que se recogen sobre nosotros, pero el primer paso imprescindible es protegerte a ti mismo y hacer que la vigilancia de tus comunicaciones sea lo más dificil posible.

Lee el resto de esta guía en el sitio Defensa Personal del correo electrónico y ¡empieza a cifrar tu correo electrónico!

Defensa personal del correo electrónico

Copyright © 2014 Free Software Foundation, Inc. Política de privacidad. Hazte socio.

Fuente: https://emailselfdefense.fsf.org/es/

Las imágenes tienen una licencia Creative Commons Attribution 4.0 (o una versión posterior), y el resto tiene una licencia Creative Commons Attribution-ShareAlike 4.0 (o una versión posterior). — ¿Por qué estas licencias?

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

Cuaderno de software

Análisis parálisis

August 01, 2014 08:31 AM

Escribía el otro día sobre cómo hay que atacar de manera distinta los problemas complejos y los complicados. Con los complicados hay que pensar fuerte antes de ponerte a hacer algo. Con los complejos hay que ir poco a poco haciendo cosas y capturando feedback. Amigos agilistas: no todo es parálisis por análisis. A  veces con problemas realmente complicados hay que pararse y pensar fuerte. Me gusta tanto este video para ilustrarlo, que lo he convertido en post… :-)

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

Cuaderno de software

Speed in software development

August 01, 2014 06:27 AM

Disclaimer: he escrito un resumen a mi bola de un superartículo que he leído http://www.targetprocess.com/articles/speed-in-software-development.html

Sprint, Marathon and intervals

  • Extreme Sprint: no dormir, cafeina a tope. Puedes aguantar un mes empezando a hacer daño a tu salud. Más, si la sacrificas completamente.
  • Moderate Sprint: 8-10 horas diarias. Siempre se anda tarde. Trabajo aburrido. Se puede aguantar años, la productividad va disminuyendo pero nadie se da cuenta.
  • Marathon: 6-8 horas diarias. Tiempo para deporte, familia y amigos. Tiempo para pensar en profundidad en los problemas. Rara vez ocurre, normalmente los managers quieren más y lo intentan conseguir de maneras estúpidas como empujar tareas, “somos héroes”  y sobretrabajo.
  • Intervalos: mezcla de marathon and “fast pace sprint”.

Fast pace sprint: nada de reuniones sobre el futuro, formaciones, actividades de recursos humanos, etc… sólo entregar, probar y documentar código.

Software Speed Model

Verde: aumenta la velocidad. Rojo, la disminuye. Amarillo: existen límites. Flecha verde: aumenta el efecto. Fecha roja: disminuye el efecto.

Skill and Experience

Aumentar las habilidades de los desarrolladores disminuye la complejidad del sistema. La posibilidad de contratar gente ya formada es limitada. La posibilidad de contratar gente y hacerla crecer no. Contrata a gente a la que le guste aprender nuevas cosas. Ayuda a la gente a aprender. Opciones:

  • compra libros
  • envia a conferencias
  • monta una conferencia
  • da tiempo para aprender nuevas cosas (80-20, learning fridays, etc….)
  • proyectos personales, coursera, leer artículos

Trabajar un 20% menos a la semana implica bajar la velocidad. ¿Importa? En modo marathon no. En modo sprint sí. Hay que ver cuando te lo puedes permitir.

Ayuda a la gente a entender mejor el dominio

Evitar que el desarrollador implemente cosas ciegamente sin entederlas. Ayuda a evitar re-work. Ayuda a detectar con mayor rapidez malas soluciones.

Experiencia

No es lo mismo gente con años de experiencia que gente experta en algo (con la habilidad para algo). La clave de la velocidad es la habilidad (skill). Si tienes mucha experiencia en habilidades irrelevantes, no sirve. De todas formas, un developer con 20 años de experiencia, normalmente resolverá las cosas más rápidametne que uno de 5.

System complexity

La complejidad es inherente al software. Tenemos que intentar construir sistemas simples, pero no el más simple. La gente con habilidad hace las cosas menos complejas. La complejidad ralentiza mucho el software.

Deuda técnica

La deuda técnica es una decisión deliberada de no entregar la mejor solución a cambio de entregarlo más rápido. Mal código y malas soluciones no es deuda técnica. La deuda técnica no es siempre mala. Está bien si sabes que, por ir más rápido, luego tienes que pagar y con intereses. Lo malo es cuando la gente obvia el pago, y la deuda aumenta hasta que la situación es insostenible. Si los managers nos aprietan, es nuestra responsabilidad decirles que se está sacrificando por llegar a la fecha límite. La deuda técnica se paga mediante refactoring o reescritura. Llegados a cierto punto, la organización puede estar pagando más por la deuda técnica que por el propio desarrollo.

Refactoring

Refactorizar es imposible sin una buena batería de pruebas automatizadas. ¿Por qué no refactorizamos todo el tiempo? Porque refactorizar es una actividad que no añade valor de negocio. El cliente no recibe nada a cambio. Lo hacemos para reducir la deuda técnica y la complejidad del sistema y porque sabemos a ciencia cierta que no podemos crear un sistema suficientemente bueno al primer intento.

Pruebas automáticas lentas o inestables

La complejidad del sistema hace que las pruebas puedan llegar a ser demasiado lentas. En parte se puede solucionar con la ejecución paralela de las mismas. Es mucho peor cuando tienes pruebas que fallan de manera intermitente. A veces se puede llegar a perder una enorme cantidad de tiempo en intentar encontrar por qué sucede…

Cowboy Coding

A muchos desarrolladores no les gustan los procesos. Les gusta programar libremente saltándoselos. Esto puede estar bien si trabajas solo o en un equipo pequeño. En un desarrollo con más de 20 desarrolladores tiene que haber un proceso bien definido. Y disciplina. Extreme Programming es, por ejemplo, una metodología que exige un montón de disciplina y energía, pero que entrega al final un trabajo de calidad.

Turboboost en el corto plazo

A veces uno puede meter el turbo para llegar a una cita importante sacrificando la calidad. Mientras luego se sepa que hay que pagar la deuda técnica generada.

Fechas límite (deadline)

Las fechas límite nunca tienen que ver con una arquitectura limpia o refactorizar. Tienen que ver con funcionalidad. Nos meten presión y nos hacen programar peor y aumentar la complejidad del sistema. Así de claro. Mezclar fechas límite con una actitud épica es todavía peor. Usar fechas límite a veces puede ser necesarias pero no pueden ser la manera normal de desarrollar.

Desarrollo iterativo y fechas límite

El desarrollo por sprints es desarrollar a base de fechas límite. Y, como consecuencia, puede tener los mismos efectos contraproducentes comentados anteriormente. Al ser sprints pequeños, los efectos también serán pequeños. El desarrollo por sprints puede estar bien, pero no hay que perder de vista el efecto de las fechas límite.

Sobretrabajar

La manera más simple de aumentar la cantidad de funcionalidad entregada es sobretrabajar. A veces no hay otro remedio. Pero intentar solucionar los problemas sobretrabajando hace que cuando el problema termina de explotar, las consecuencias sean peores todavía. Artículo interesante sobre sobretrabajar.

Pasión

La pasión es buena. La gente apasionada se preocupa por su trabajo más. Pero no todo lo que reluce es oro. La gente apasionada tiene problemas para encontrar un equilibrio entre trabajo y vida personal. Puede quemarse antes y acabar deprimida.

Trabajo concentrado y enfocado

El trabajo enfocado y sin interrupciones es clave para que un programador entregue un buen código. Es difícil sino mantener en el cerebro abstracciones de gran tamaño. Repaso a las cosas que influyen en el trabajo concentrado.

Equipos inestables/ Rotación de personal

Tuckman define cuatro estados de un equipo: forming, storming, norming, performing. La auténtica productividad del equipo se produce en la fase de performing. Si se rota a las personas, los equipos vuelven a pasar una y otra vez por las fases de forming, storming y norming. Es difícil desarrollar buenas relaciones si rotas a las personas todo el rato. Puede estar bien reformar equipos que no estén siendo muy productivos. Pero se tarda meses en saberlo porque se puede pasar mucho tiempo en la fase de storming.

Open Space

Si tienes equipos estables es importante que cada equipo de, por ejemplo, seis personas esté en un espacio abierto. Pero si toda la empresa está en un mismo espacio abierto hay demasiado ruido. Lo ideal es tener salas “tamaño equipo”.

IM/Skype/Notifications

Las notificaciones destruyen tu concentración. Y si no le pones atención, se embeben en tu flujo diario. Aunque tengas pocas, pueden destruir la productividad de tu día. Si estás programando, ciérralo todo. Estos canales de comunicación son muy útiles, pero al mismo tiempo muy peligrosos. Y es muy difícil resolver el problema a nivel sistémico.

Multi-tasking

Aunque sea muy fácil decirlo y muy difícil hacerlo, hay que intentar hacer una tarea cada vez y poner toda la concentración en ella, evitando las ineficiencias de los cambios de contexto. La técnica del pomodoro puede ayudar.

Rehacer

Obviamente reduce la velocidad en desarrollar software el tener que rehacer cosas. No podemos evitarlo completamente, pero sí reducirlo al máximo. Ocurre por tres motivos principalmente:

Errores (bugs)

Es imposible evitar tener alguno. Pero es importante encontrarlos rápidamente. El ciclo de feedback tiene que ser rápido y tiene que haber colaboración entre el que desarrolla y el que prueba. Encontrar errores en producción es todavía peor, sobre todo a nivel de comunicación (desarrollador, probador, cliente, usuario….)

Requisitos vagos

Suponen intentar adivinar lo que se quiere hacer. Sin saberlo realmente. A veces porque el Dueño de producto no está disponible. A veces porque es muy difícil especificar por adelantado los detalles.

  • Transición de UX a desarrollo: en el camino se pierde información. O se repiten discusiones ya aclaradas previamente. Formas de mejorar esto:
    • Los desarrolladores participan en la UX desde el principio
    • Antes de implementar una funcionalidad se hace una reunión previa con todo el mundo para tener una misma visión compartida.
    • escribir buenas especificaciones (imposible!)
  •  Especificaciones:

Fallo de demanda (Do the right things)

Los errores son malos pero… ¿qué pasa con las funcionalidades que nadie usa? Todo el tiempo de pensarlas, desarrollarlas y probarlas no sirve para nada. ¿Cómo evitarlo?

  • Canales de comunicación: que los usuarios tengan una manera sencilla de dar feedback.
  • Estadísticas: úsalas para saber si una funcionalidad es popular o no.
  • Ranking de funcionalidades: crea un modelo lineal simple y úsalo para crear un ranking de funcionalidades. Por ejemplo, basándote en uso, votos de usuarios, tamaño, dificultad, frecuencia de uso….
  • UX feedback: prototipos, sketches, a/b testing….

Más gente / Más equipos de desarrollo

Las organizaciones pequeñas tienen mayor “velocidad por unidad” mientras las organizaciones grandes tienen mayor “velocidad global” (pero les cuesta económicamente lo suyo conseguirla). Más gente significa más coordinación, más reuniones, más desperdicio.

Contratar

Contratar a nueva gente puede aumentar la velocidad de la organización a largo plazo. A corto, se pierde tiempo en: entrevistar gente para contratarla, mentorizar a los nuevos para transmitirles conocimiento, etc. Y, además, el propio contratado tardará tiempo en ser totalmente productivo. Si quieres ir rápido a corto plazo, contratando a más gente irás más lento.

Coordinación

Cuanta más jerarquía más desperdicio en coordinación y reuniones. Las organización en redes, de manera plana y con equipos autónomos y multifuncionales ayuda a reducir la coordinación. Nota: la estructura de las organizaciones se transmite a la estructura del software. Una jerarquía flexible tiende a crear software flexible. Sería interesante estudiar cómo son las estructuras de IBM o Atlassian y ver cómo se transmite a su software.

Desperdicio y tareas que no añaden valor

Reuniones

La mayoría de las reuniones apestan. Hay que intentar reducirlas al mínimo. Las organizaciones pequeñas pueden vivir sin reuniones. A partir de cierto tamaño, hacen falta. Existen un montón de libros sobre cómo mejorar las reuniones y… ¿sabes qué? Funcionan. Todas las reuniones deberían tener: facilitación, agenda, gente preparada y resultados.

Para generar algo nuevo, tienes que pasar tiempo pensando.

Deporte en el trabajo

El deporte en el trabajo está estupendamente. Las soluciones creativas no vienen de estar sin levantarse del asiento ocho horas. Está bien levantarse, charlar y hacer algo de ping-pong.

Aprender en el trabajo

Las organizaciones contratan a gente con capacidad para aprender y potencial, pero inexplicablemente no les dan tiempo para hacerlo. El efecto de dejar tiempo de aprendizaje en el trabajo (side-projects, hackatones, libros, conferencias….) no se puede ver a corto plazo. Además, no existe un modelo para cuantificarlo a nivel económico.

Equilibrio entre trabajo y vida personal

Si trabajas más y más duro, acabarás haciéndolo más y más tontamente. Cuando tienes un problema importante es difícil no pensar en él en el trabajo, en casa, en la ducha,… pero eso no puede ser una constante. Un buen manager intentará que los desarrolladores tengan hobbies y aficiones y dediquen tiempo a ello.

Resumiendo

Creo que el estrés está bien en momentos puntuales. La velocidad/productividad en el desarrollo de software es un problema a abordar desde múltiples puntos de vista. Es MUY difícil y no puede reducirse a decir “hay que trabajar más rápido” y centrarse en dejar de hacer cosas y tomar atajos.

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

Blog Bitix

Usar Apache Tapestry en una aplicación «standalone»

July 31, 2014 11:06 AM

Apache Tapestry

Apache Tapestry es un framework de desarrollo para aplicaciones o páginas web en el que habitualmente se emplea el lenguaje Java y se despliega en un servidor de aplicaciones como entorno de ejecución. Pero Tapestry es una pieza de software que se compone de diferentes partes algunas de las cuales pueden ser utilizadas fuera del contexto de una aplicación web. Este es el caso del contenedor de dependencias que proporciona IoC (IoC, «Inversion of Control») en Tapestry, podemos usarlo en una aplicación «standalone», es decir, en un programa que se inicia con el típico «public static void main(String[] args)» de las aplicaciones Java.

El contenedor de dependencias de Tapestry tiene algunas propiedades interesantes como que dos servicios pueden ser mutuamente dependientes y que se puede contribuir configuración a cualquier servicio para cambiar en cierta medida su comportamiento además de otras características que explico más en detalle en el libro PlugIn Tapestry. Para usarlo en una un programa que se ejecuta de la linea de comandos usando el main de una clase Java primeramente deberemos incluir en el proyecto la dependencia sobre tapestry-ioc, si usamos Gradle de la siguiente manera:

<noscript><pre><code>compile 'org.apache.tapestry:tapestry-core:5.4-beta-3' compile 'org.apache.tapestry:tapestry-ioc5.4-beta-3'</code></pre></noscript>

Una vez que tenemos la dependencia en el programa deberemos iniciar el contenedor IoC e indicarle los diferentes módulos que contendrán la definición de los servicios.

<noscript><pre><code>RegistryBuilder builder = new RegistryBuilder(); builder.add(TapestryModule.class, HibernateCoreModule.class, HibernateModule.class, BeanValidatorModule.class, TapestryOfflineModule.class, GeneratorModule.class); builder.add(new SpringModuleDef(&quot;applicationContext.xml&quot;)); Registry registry = builder.build(); registry.performRegistryStartup();</code></pre></noscript>

En este caso he usado Spring para la transacionalidad e Hibernate para la persistencia. Después de esto tenemos la referencia al registro de servicios, podemos obtener cualquiera en base a la interfaz que implementa, en este caso el servicio que implementa la interfaz MainService.

<noscript><pre><code>registry.getService(MainService.class);</code></pre></noscript>

Al final de la aplicación deberemos llamar al método shutdown del registro.

<noscript><pre><code>registry.shutdown();</code></pre></noscript>

Otra cosa que nos puede interesar es poder generar contenido html usando el sistema de plantillas y componentes de Tapestry, ya sea en una aplicación «standalone» o en una aplicación web para enviar el contenido en un correo electrónico o quizá guardarlo en un archivo. Hay muchos sistemas de plantillas, cada framework suele tener uno propio o usar una solución específica como Thymeleaf pero la mayoría usa un modelo push en vez de un modelo pull, en el caso de Tapestry se emplea el modelo pull que tiene algunas ventajas como explico en el artículo anterior. Si usamos una aplicación Tapestry usándolo también para generar el contenido de los correos o cierto contenido estático evitamos tener que aprender una segunda tecnología además de aprovechar todo el código reutilizable que posiblemente hemos desarrollado en algunos componentes. Para generar el contenido estático que generaría una página en Tapestry tenemos el módulo Tapestry Offline. Como no está en los repositorio de maven debemos descargarnos el jar e incluir la dependencia como un archivo.

<noscript><pre><code>compile files('misc/libs/tapestry-offline.jar')</code></pre></noscript>

Para generar una página de Tapestry fuera de una petición web y de un servidor de aplicaciones debemos usar el servicio OfflineComponentRenderer. Su uso sería el siguiente:

<noscript><pre><code>@Override public File generatePage(String page, Object[] context, Map&lt;String, String&gt; params) throws IOException { File file = new File(to, getToPage(page, context, params).getPath()); logger.info(&quot;Generating page «{}» ({}, {})...&quot;, page, file, params.toString()); file.getParentFile().mkdirs(); Writer w = new FileWriter(file); render(page, context, params, Globals.LOCALE, w); w.close(); return file; } private void render(String page, Object[] context, Map&lt;String, String&gt; params, Locale locale, Writer writer) throws IOException { TypeCoercer coercer = Globals.registry.getService(TypeCoercer.class); OfflineComponentRenderer renderer = Globals.registry.getService(&quot;BlogStackOfflineComponentRenderer&quot;, OfflineComponentRenderer.class); EventContext activationContext = new ArrayEventContext(coercer, context); PageRenderRequestParameters requestParams = new PageRenderRequestParameters(page, activationContext, false); DefaultOfflineRequestContext requestContext = new DefaultOfflineRequestContext(); for (Map.Entry&lt;String, String&gt; param : params.entrySet()) { requestContext.setParameter(param.getKey(), param.getValue()); } requestContext.setLocale(locale); renderer.renderPage(writer, requestContext, requestParams); }</code></pre></noscript>

Tengo que decir que al generar la página fuera de una petición web tendremos alguna limitación como solo poder usar assets con el prefijo context. Pero esto por lo menos como he explicado en el caso de Blog Stack no me ha supuesto ningún problema.

Esto quizá no sea lo habitual pero en Blog Stack ambas posibilidades me han resultado de gran utilidad al desarrollar el proyecto. Las posibilidades son muchas por ejemplo podríamos usar alguna combinación de esto mismo con el microframework Spark si nuestra aplicación estuviese más orientada a una API aunque también podríamos usarlo junto con RESTEasy.

Referencia:
Libro PlugIn Tapestry
Documentación sobre Apache Tapestry[apache]: http://httpd.apache.org/

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

proyectos Ágiles

The spirit of Agile - 2 minutes video

July 29, 2014 08:31 PM

This 2' video shows "The spirit of Agile" as a lever for success in the mindset change.

the_spirit_of_agile

 

Credits:

  • Agile Coach: Silvia Sistaré.
  • Concept and Production: Blua Producers and Xavier Albaladejo

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

Arragonán

Semana 320

July 29, 2014 12:19 PM

Esta vez el retraso viene de que la semana la terminé en Noja, quería aprovechar el trayecto en autobús para escribir la retro, pero casualmente coincidí con Fernando y entre unas cosas y otras al final pasé de hacerlo.

Cosas del verano, supongo, esta semana no encuentro nada en especial que destacar más allá del trabajo hecho:

  • En Nort terminé el trabajo de integración con facebook en el backend y empecé a trabajar en la versión móvil (una aplicación híbrida), estudiando el framework javascript que usamos y empezando la integración con la autentificación con facebook en este escenario
  • Tras la primera propuesta del rediseño de la web de minchador (que me moló bastante), tocó tratar algunos cambios y añadidos para poder seguir avanzando.
  • Estuve dedicando algún rato a mhop, cuestiones de organización más que otra cosa, además de preparar el viaje.

Buena semana.

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

Ingenieria de Software / Software Engineering / Project Management / Business Process Management

Del módelo al Ejecutable

July 29, 2014 04:57 AM

Expresso Logic, una interesante propuesta para realizar aplicaciones de manera consistente y rápidas

Modern Analyst, Expresso Logic

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

Variable not found

<Vacaciones>

July 28, 2014 11:50 AM

Pues llegó la mejor época del año, prácticamente la única en la que algunos afortunados podemos alejarnos un poco de los mundos binarios y dedicarnos a otros menesteres seguro más importantes, como disfrutar de la familia y descansar, al menos unos días.

Variable not found quedará a la deriva hasta septiembre, cuando volveremos al ataque con las pilas cargadas y listos para afrontar la nueva temporada :)

¡Feliz verano, amigos!

» 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