Noticias Weblogs Código

Variable not found

Inicialización de propiedades en C# 6.0

September 16, 2014 07:19 AM

Novedades de C# 6.0Hace algún tiempo comentamos alguna de las novedades que se incluirán en la próxima versión de C#, concretamente el nuevo operador de navegación segura “?.”, pero la cosa no acaba aquí: se avecinan un buen número de cambios que prometen seguir mejorando nuestro lenguaje favorito :-)

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

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



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



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

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

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



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



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



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

Publicado en Variable not found.

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

Picando Código

Captain Marvel: First Contact

September 15, 2014 03:00 PM

Captain Marvel – First Contact

Hace poco caí con la serie Captain Marvel a cargo de Peter David. Me gusta lo que leí de Hulk por el autor, y su Aquaman es un despelote. Fue quien hizo que Aquaman perdiera un brazo y lo reemplazara con un harpón, aparte de un cambio estético importante que es el que imagino para Jason Momoa en la película Batman V Superman :D. Varias de sus historias con Hulk son de las mejores historias escritas sobre el personaje.

Me enteré que Peter David también había llevado adelante Captain Marvel, no el de la Distinguida Competencia (que ahora cambió su nombre a Shazam!), sino el de Marvel Comics. Han habido muchos/as Capitanes Marvel, fueron todo una familia Marvel (en ese primer universo), y en el universo Marvel empezó siendo un alienígena de la raza Kree llamado Mar-Vell, el manto pasó por varias mujeres y hombres terrícolas y extraterrestres, y la Capitana Marvel actual es Carol Danvers (a no confundir con Ms. Marvel: Kamala Khan).

Si no conocen toda la historia con los superhéroes Marvel y les resulta medio confuso, no se preocupen, nada de esto es tan importante a la hora de leer este cómic. Aunque sí se disfruta más teniendo un poco de idea, si les interesa pueden arrancar por buscar Captain Marvel en Wikipedia y adentrarse en una aventura de horas siguiendo enlaces y leyendo artículos (¿hay un nombre para esa situación?).

Captain Marvel Vs. Hulk

Captain Marvel Vs. Hulk

A modo de introducción resumida, esta instancia de Captain Marvel es el hijo del Captain Marvel original (Mar-Vell, el Kree), se llama Genis-Vell y está unido a Rick Jones (el amigo de Bruce Banner responsable del accidente con la bomba gamma que lo transformó en Hulk, entre otras cosas) a través de dos brazaletes que al golpearlos intercambia a Rick y Genis-Vell de nuestro plano de existencia a la Zona Negativa (o por lo menos así lo plantea al principio) y viceversa. Ya en la época de la guerra Kree-Skrull Rick Jones tenía una relación así con Mar-Vell, por lo que no es casualidad.

La serie arrancó como spin-off de Avengers Forever, y tuvo una tirada inicial de 35 números. Luego se relanzó desde el número 1 (manteniendo la numeración original en la tapa también) y Peter David cambió completamente el tono. Estos números fueron los primeros que leí (a partir del #36, renumerado como #1) y me convencieron de conseguir todas las ediciones compiladas.

Lo que me atrajo enseguida fue el camino oscuro por el que empieza a transitar la personalidad del personaje. Me hizo acordar a Irredeemable de Mark Waid. Decidí empezar desde el principio, y tras investigar cómo se organizaba la cronología, volví atrás a Captain Marvel: First Contact.

Captain Marvel... ¿Shazam?

Captain Marvel… ¿Shazam?

Captain Marvel – First Contact incluye los números 1 al 6 y el #0. Es completamente distinto a lo que había leído en el #1 (36), pero no me arrepiento de haberlo obtenido también.

Para sacarlo del medio capaz, salta con el tema de Shazam! y Captain Marvel en el #0 de una forma bastante divertida, y creo que no se vuelve a mencionar. La página que incluyo a la izquierda de estos párrafos es la de la situación en cuestión y es buena representando la relación de los personajes de acá en más. El tono humorístico se mantiene con algunos guiños y hasta podría decirse “rompimiento de la cuarta pared”.

Las historias son bastante entretenidas, Rick y el Capi van desarrollando su relación -a las caídas en un principio. Mientras Rick intenta poner en orden su vida y arreglar las cosas con su esposa Marlo, el Capi aprende a usar su conciencia cósmica (el poder de saber todo lo que va a pasar y está pasando a escala universal, que también tiene Silver Surfer y otros personajes de cómics).

Marlo, la mujer de Rick, tiene sus propias aventuras y desventuras, haciéndola una parte importante de la historia. Trabaja en una tienda de cómics donde se dan algunos de esos chistes “internos” que comentaba.

Para animar todavía más las cosas aparecen otros personajes conocidos del universo Marvel como Hulk, Wendigo, Moondragon y Drax El Destructor.

Moondragon (Peter David) sobre la evolución

Moondragon (Peter David) sobre la evolución

También aparece el mundo atómico donde se desarrollan las historias que pueden leer en el compilado Hulk: Heart of the Atom, que leí hace poco y comenté en Multiverseros:

Hulk: Heart of the Atom es una compilación de varios números relacionados al mundo de K’ai, un planeta sub-atómico donde Hulk se enamora de Jarella. Hay historias de distintos niveles pero en general me gustó bastante. Me encanta Hulk y estas historias muestran distintas perspectivas de su personalidad y motivaciones, y presentan varios personajes del universo Hulkiano. Es una compilación interesante de parte de su historia, recomendado para amantes de Hulk.

Estas historias son mucho más livianas de lo que esperaba tras leer lo Waideano que comentaba más arriba, pero son bastante divertidas. El arte a cargo de ChrisCross es bueno, no es un despelote y tiene sus altos y bajos, pero está bastante bien y acompaña al estilo de la serie.

No encontré que los números entre 7 al 35 estuvieran coleccionados en tomos, pero me encantaría poder leer cómo sigue. Mientras tanto lo siguiente en mi lista es saltar a Captain Marvel: Nothing to Lose que empieza con la renumeración del #36 a #1 y arranca la historia oscura “Irredimieable”. Vamos a ver qué tal.

Si les interesa Captain Marvel, han leído historias de Hulk de Peter David y les gustaron, creo que les puede gustar este tomo. Igual tengo un poco más de expectativa por lo que se viene, pero me llevé una grata sorpresa con First Contact.

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

Variable not found

Enlaces interesantes 169

September 15, 2014 07:06 AM

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

<Spam>Por cierto, aprovecho para informaros de que si estáis interesados en aprender ASP.NET MVC u otras tecnologías, en CampusMVP han lanzado para este mes una oferta que no podréis rechazar ;-)</Spam>

.Net

ASP.NET

Azure / Cloud

Data access

Html/Css/Javascript

Visual Studio/Complementos/Herramientas

Cross-platform

Otros

Publicado en Variable not found

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

Koalite

Crear un componente con ReactJS

September 15, 2014 05:06 AM

En el anterior post explicaba cuál es el enfoque de ReactJS para construir interfaces de usuario. Después de sentar las bases de la filosofía que hay detrás de ReactJS, en este post vamos a ver un pequeño ejemplo que nos permita hacernos una idea más clara que cómo se utiliza ReactJS.

El componente de ejemplo

El componente de ejemplo que vamos a construir está formado por una lista cervezas en la que podemos ir incrementando la cantidad de cervezas ingeridas y nos mostrará el total consumido hasta el momento. El aspecto será algo así:

react-sample

Lo primero que necesitamos es decidir de qué forma vamos a organizar la información que vamos a mostrar, decidiendo qué componentes vamos a crear y qué información será inmutable (propiedades) en cada componente y qué información será mutable (estado) en cada componente.

En este caso, podemos tener un componente que llamaremos BeerItem que represente cada elemento de lista. Este componente recibirá como propiedades inmutables el nombre de la cerveza a mostrar, el número de veces que se ha consumido, y la función callback que se invocará al tomarnos una cerveza más.

Además, tendremos un componente, BeerList que encapsula la lista de cervezas y la cuenta total. Esta información es mutable para este componente y, por tanto, formará parte de su estado. Cada vez que se incremente la cuenta de una cerveza, se modificará el estado de este componente y, por tanto, se provocará un nuevo renderizado del componente actualizando el DOM generado.

Creado los componentes

Un componente en ReactJS es un objeto javascript que contiene una serie de funciones y propiedades que son gestionadas por ReactJS. Para crear un componente, se debe utilizar la función React.createClass. Nuestro componente para mostrar un elemento de lista es el siguiente:

var BeerItem = React.createClass({
  incCount: function() {
    this.props.addOne(this.props.beer);
  },
  render: function() {
    return <li>[{this.props.count}] {this.props.beer} <button onClick={this.incCount}>Una más</button></li>;
  }
});

En el objeto que pasamos a createClass estamos definiendo la función render que se encarga de generar el DOM asociado al componente y una función adicional incCount que usa el componente para gestionar el evento asociado al click del botón.

Para acceder a las propiedades inmutables recibidas por el componente debemos usar this.props. Estas propiedades las recibe el componente en el momento de crearlo, cosa que haríamos con un código similar a éste:

<BeerItem beer="Mahou 5 estrellas" count=4 addOne=someFuncToAddOneBeer />

Lo más llamativo de todo esto es esa especie de pseudohtml que aparece mezclado con el código de javascript y que se usa como valor de retorno de la función render. Este pseudohtml es lo que ReactJS llama JSX, Javascript XML y ayuda a definir el DOM de una forma más cómoda. ReactJS cuenta con herramientas para convertir esta sintaxis a funciones Javascript “puras”, y aunque podemos hacer eso manualmente, en general resulta más claro usar JSX para definir los componentes.

La transformación se puede realizar directamente en el browser o en un proceso de precompilación en el servidor, lo que permite ahorrar tiempo de ejecución en el cliente y reutilizar las plantillas ya compiladas.

Ahora que tenemos el componente para mostrar una cerveza, vamos cómo es el componente que muestra la lista completa:

var BeerList = React.createClass({
  getInitialState : function() {
    return {
      beers: [
        {name: "Mahou 5 estrellas", count: 0},
        {name: "Cibeles Imperial IPA", count: 0},
        {name: "Chimay Triple", count: 0}
      ]
    };
  },

  addOne : function(beerName) {
    var beers = this.state.beers,
      beer = beers.filter(function(x) { 
        return x.name === beerName;
      })[0];

    beer.count ++;

    this.setState({beers: beers});
  },

  render: function() {
    var total, beerItems;

    total = this.state.beers.reduce(function(acc, x) {
      return acc + x.count;
    }, 0);

    beerItems = this.state.beers.map(function(x) {
      return <BeerItem beer={x.name} count={x.count} addOne={this.addOne} />;
    }, this);

    return <div><p>Llevas {total} cervezas</p><ul>{beerItems}</ul></div>;
  }
});

Este componente mantiene estado mutable, por lo que aparece la función getInitialState, que devuelve el estado inicial, y se utiliza la función setState para actualizar el estado. Cada vez que se invoca la función setState ReactJS se encarga de volver a llamar a la función render para volver a generar el DOM.

En su función render se están creando componentes de tipo BeerItem como los que hemos definido antes para representar cada elemento de la lista, y estamos asignándoles sus propiedades (información inmutable) a través de atributos del JSX. Como se puede ver, la forma de “comunicar” los componentes hijos con el componente padre es a través de una función callback, addOne, que se pasa como una propiedad más del hijo.

Si os fijáis, cada vez que se incrementa la cuenta de una cerveza se actualiza el estado, lo que fuerza a regenerar el DOM de todas las cervezas. Recordad que en realidad ReactJS trabaja generando un DOM virtual que luego compara con el DOM real para lanzar los mínimos cambios necesarios, por lo que esto no supone un problema de rendimiento. A cambio, cuando estamos en el método render tenemos toda la información (estado y propiedades) disponible, por lo que es muy sencillo razonar sobre ella y tomar las decisiones de renderizado adecuadas.

Por último, para empezar a mostrar un componente de ReactJS en una página debemos usar la función React.renderComponent indicando el componente a mostrar y el elemento HTML en el que vamos a insertar el DOM generado por el componente:

React.renderComponent(, document.getElementById('content'));

Podéis jugar con el código completo del ejemplo en este fiddle.

Resumen

Crear componentes de ReactJS es bastante sencillo, aunque hay que tener claro qué tipo de información queremos que sea mutable e inmutable en cada componente y cual es la jerarquía de componentes que queremos montar. Esto puede resultar algo confuso al principio, especialmente si estás acostumbrado al uso de patrón MVVM donde toda la información es mutable y la comunicación entre componentes se puede realizar en cualquier dirección y no sólo de padres a hijos.

Aunque no sea obligatorio, usar JSX es muy recomendable para generar el DOM porque mejora mucho la legibilidad. Lo malo es que eso hace necesario recurrir a herramientas externas para convertir el JSX a javascript puro, y eso complica un poco la experiencia de desarrollo. Aun así, en el próximo post veremos como podemos preparar un flujo de trabajo que nos simplifique la vida.

Posts relacionados:

  1. ReactJS: un enfoque diferente
  2. Crear modelos más ricos sin tipos enumerados
  3. Crear modelos más ricos quitando lógica de los servicios

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

proyectos Ágiles

The spirit of Agile - 2 minutes video

September 13, 2014 03:07 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...

Picando Código

¡Feliz día de los Programadores!

September 13, 2014 03:04 PM

Como todos los días 256 del año, hoy se celebra el día de los programadores.

$ irb
2.1.2 :001 > Time.now.yday
 => 256

Esto que ya es una tradición por el blog, desde 2007 festejo todos los años el día con un post: Posts sobre el Día de los Programadores. Todos los años aprovecho la ocasión para comentar en qué ando programando.

Code Monkeys

Desde que me fui de Neo, estuve un tiempo de vacaciones, programando poca cosa cada tanto. Pero en agosto volví al mundo laboral, ahora como programador contractor para LivePress, un producto de live-blogging basado en WordPress. Tiene mucho de JavaScript, algo de PHP y algunas cosas más. Estoy bastante contento con el trabajo, la modalidad de trabajar desde casa (o desde cualquier otro lado donde haya internet) te da mucha libertad, es desafiante e interesante como para mantenerme entretenido y hay buena comunicación con el cliente.

También desde el año pasado programé varios proyectos de código abierto, la mayoría los publiqué por acá como ricojson, volumerb, gibil, y algunas cosas más. Si bien no son proyectos super útiles, me entretengo programándolos y son una buena forma de mantenerme en práctica. Tengo algunos proyectitos más que todavía no he publicado por ahí porque están sin terminar, pero es cuestión de otro fin de semana de proyectos :D

No puedo decir que esté usando alguna tecnología nueva, pero sí aprendiendo cada vez más JavaScript y metiéndome en ese mundillo (aunque esto viene pasando desde hace ya unos años). Pero cada vez me acerco más a poder decir que me siento cómodo con el lenguaje (aunque Ruby sigue siendo mi lenguaje favorito). También a medida que pasa el tiempo estoy cada vez más cómodo con Emacs y la línea de comando, voy usando de a poco cosas nuevas que voy aprendiendo que me hacen más productivo a la hora de interactuar con la computadora y programar.

Estimados lectores y lectoras que programan, ¡feliz día! ¿En qué están programando estos días? ¿Qué tecnologías nuevas han empezado a usar o aprender?

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

Blog Bitix

Compilar y cargar de forma dinámica una clase Java

September 12, 2014 05:49 PM

Java

Desde la versión 1.6 del JDK de Java disponemos de una API para acceder al compilador desde un programa Java. En el ejemplo de este artículo utilizaré varias clases de esa API para conseguir compilar un archivo con la definición de una clase Java. En posteriores entradas comentaré un ejemplo práctico y muy útil con el que podemos sacar provecho de esta funcionalidad. Las clases que necesitaremos de esa API son:

  • JavaCompiler que es la interfaz para acceder al compilador desde un programa Java.
  • JavaFileManager que es una abstracción para gestionar los archivos fuente y las clases. Usaremos uno propio llamado ClassFileManager.
  • SimpleJavaFileObject clase que contiene el código fuente Java.

Y también necesitaremos redefinir algunas:

  • La clase ClassFileManager que extiende ForwardingJavaFileManager y se encargará de cargar los objetos JavaClassObject con un ClassLoader.
  • La clase JavaClassObject que extiende SimpleJavaFileObject y contendrá el código bytecode generado en memoria por el compilador.
  • CharSequenceJavaFileObject clase que extiende SimpleJavaFileObject y que contiene el código fuente en un objeto de tipo CharSequence.
  • La interfaz Configuracion es la interfaz que debe cumplir la clase Java que compilaremos, cargaremos de forma dinámica en la aplicación y posteriormente invocaremos sus métodos.

En el javadoc de las clases hay una descripción más amplia de cada una de ellas.

En el siguiente código suponiendo que disponemos en la variable source de un código Java a compilar y de la que crearemos mas tarde una instancia de la clase que define podemos hacerlo de la forma indicada continuación. Antes de mostrar el código código la clase a compilar y a cargar de forma dinámica en este ejemplo debe cumplir el contrato definido en una determinada interfaz de modo que una vez compilada y cargada sepamos que métodos podemos invocar de esa clase. En este caso el código fuente de la clase a compilar está hardcodeada en un String en el propio programa pero perfectamente podría haber obtenido su contenido de un archivo del disco duro o de una base de datos.

<noscript><pre><code>package io.github.picodotdev.blogbitix.config; import java.util.ArrayList; import java.util.List; import javax.tools.JavaCompiler; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; import javax.tools.ToolProvider; public class Main1 { public static void main(String[] args) throws Exception { // Definir la clase String[] sources = new String[] { &quot;package io.github.picodotdev.blogbitix.config;&quot;, &quot;import java.util.HashMap;&quot;, &quot;import java.util.Map;&quot;, &quot;public class AppConfiguracion implements Configuracion {&quot;, &quot;private static Map config;&quot;, &quot;static {&quot;, &quot;config = new HashMap();&quot;, &quot;config.put(\&quot;propiedad\&quot;, 11);&quot;, &quot;}&quot;, &quot;public Map get() {&quot;, &quot;return config;&quot;, &quot;}&quot;, &quot;}&quot; }; String source = join(sources); String name = &quot;io.github.picodotdev.blogbitix.config.AppConfiguracion&quot;; // Compilar la clase JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); JavaFileManager manager = new ClassFileManager(compiler.getStandardFileManager(null, null, null)); List&lt;JavaFileObject&gt; files = new ArrayList&lt;JavaFileObject&gt;(); files.add(new CharSequenceJavaFileObject(name, source)); compiler.getTask(new NullWriter(), manager, null, null, null, files).call(); // Cargar e instanciar la clase Configuracion configuracion = (Configuracion) manager.getClassLoader(null).loadClass(name).newInstance(); // Invocar un método de la clase System.out.println(configuracion.get()); } private static String join(String[] s) { StringBuffer sb = new StringBuffer(); for (int i = 0; i &lt; s.length; i++) { sb.append(s[i]); } return sb.toString(); } }</code></pre></noscript>
<noscript><pre><code>package io.github.picodotdev.blogbitix.config; import java.util.Map; public interface Configuracion { Map get(); }</code></pre></noscript>

Con este ejemplo puede intuirse el ejemplo práctico que comentaré que no es más que utilizar código Java para definir la configuración de una aplicación, esto tiene varias ventajas sobre utilizar un xml u otro tipo de formato de archivo de configuración de la aplicación (una de ellas que utilizando un IDE el compilador nos informará de errores y nos ofrecerá asistencia al escribir código). Esta idea junto con la idea de monitorizar un archivo para ver si se han producido cambios en él y recargarlo puede darnos como resultado una funcionalidad en la que la configuración se basa en código Java y que la configuración pueda recargarse de forma dinámica, si la aplicación donde se utiliza es una aplicación de un servidor de aplicaciones podríamos cambiar la configuración sin tener que reiniciar la aplicación.

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

En el siguiente artículo comentaré como monitorizar un archivo en Java para ver si se han producido cambios en él. Y basándome en estos dos artículos comentaré como disponer de un archivo de configuración que se recargue al detectase cambios en él.

Referencia:
Dynamic in-memory compilation

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

Navegapolis

¿La Casa Blanca se desmarca de CMMI?

September 12, 2014 04:34 PM

¿CMMI?CMMI es un modelo para mejorar y evaluar la madurez de las empresas de software y la capacidad de sus procesos. La Administración americana lo puso en marcha (entonces como CMM) en los 80 a través de SEI para tener un medio con el que evaluar la fiabilidad de sus proveedores de software.

En los 90, las críticas hacia los modelos de procesos generaron su antítesis: la agillidad que los consideraba inapropiados, e incluso contraproducentes para el desarrollo de software.

Desde entonces hay dos tendencias estratégicas distintas para lograr la excelencia en proyectos de software: basar la calidad en la capacidad de los procesos, o basarla en el talento de las personas.

a) La calidad de un sistema de software es consecuencia de la calidad de los procesos empleados en su desarrollo. La evaluación de los procesos (CMMI, ISO 15504, Spice...) es la estrategia adecuada para determinar el nivel de calidad que ofrece la empresa.

b) La calidad de un sistema de software depende principalmente del talento de las personas. Contar con los mejores profesionales y un clima de trabajo adecuado es una garantía de éxito más fiable que la capacidad de los procesos de trabajo que tenga institucionalizados la empresa.

Aplicar las dos estrategias simultáneamente: procesos + talento es también una opción pero a menudo más quimérica que realista cuando se trata de sistemas de software innovadores, porque los procesos combinan bien con el trabajo disciplinado, pero no tanto con el talento creativo. De hecho la primera reacción al combinarlos fue el Manifiesto Ágil.

 
cmmi vs agile
 
 
Observando lo ocurrido con el proyecto healtcare.gob y las decisiones de la Casa Blanca en el último año:
 

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

Picando Código

Día del Futuro – Es la gente construyendo Montevideo Abierto

September 09, 2014 03:30 PM

Este jueves voy a participar en un evento de D.A.T.A. y la Intendencia de Montevideo en el marco de Día del Futuro:

Día del Futuro

Día del Futuro

Vamos a charlar sobre tecnologías, datos abiertos, usos y demás. Vamos a tomar café, conversar y discutir maneras de hacer del mundo (empezando por Montevideo) un lugar mejor con tecnología y esos temas.  ¡Están invitados!

Jueves 11 de Setiembre – 16:00
Intendencia de Montevideo – Sala Dorada (piso 1 y ½).

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

Variable not found

Enlaces interesantes 168

September 08, 2014 07:15 AM

Enlaces interesantesPues era prácticamente ayer cuando dejaba en pausa el blog por la cercanía de las vacaciones, y ya estamos por aquí otra vez listos para la nueva temporada. Y no, no es que me haya pegado más de un mes de descanso (¡quién pudiera!), más bien casi ha sido al contrario: un verano bastante liado y muy pocos días de desconexión efectiva... pero bueno, contento y entusiasmado por la temporada tan apasionante y repleta de novedades que tenemos por delante :-)

Y para celebrar el retorno como la ocasión merece, ahí van unos cuantos enlaces cosechados durante la semana pasada, que, como siempre, espero que os resulten interesantes.

Eventos

.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

ReactJS: un enfoque diferente

September 08, 2014 05:06 AM

En los últimos años el auge de las aplicaciones basadas en HTML5 y Javascript ha sido imparable, y si a este lo unimos que Javascript no ofrece un conjunto de librerías estándar que dicte una forma canónica de hacer las cosas (como sí ocurre en otras plataformas como .NET o Java), es natural que este auge haya venido acompañado de la aparición de muchas librerías y frameworks para desarrollar este tipo de aplicaciones.

logo-reactjs

ReactJS es otra librería más diseñada para ayudarnos a desarrollar aplicaciones SPA, con una fuerte carga de interactividad en el cliente gracias al uso de Javascript. Ha sido desarrollada por Facebook y está publicada como Open Source con una licencia Apache 2.0.

Lo interesante de ReactJS es que aporta un enfoque distinto al que podemos ver en otras herramientas como KnockoutJS o AngularJS de las que ya hemos hablado por aquí en alguna ocasión.

OJO: este es un post de contar cosas, no de ver código. Si estás buscando eso, te sugiero que consultes la documentación de ReactJS o busques algún tutorial. Si quieres comprender mejor la filosofía que hay detrás de ReactJS, tal vez este post pueda ayudarte.

Una cuestión de alcance

Lo primero que debemos saber de ReactJS es que se trata de una librería para desarrollar interfaces de usuario. No estamos hablando de un framework todo incluido como AngularJS, Durandal o Ember, sino más bien de algo similar a KnockoutJS, al menos en cuanto a alcance.

ReactJS nos permitirá desarrollar el interfaz de usuario de una aplicación web, la V en un patrón MVC o MVVM, pero no incluye cosas como routing, acceso a servicios rest, inyección de dependencias, sistema de módulos, etc. A cambio, tampoco nos impone muchas restricciones sobre la forma de usarla, por lo que podemos mezclarla con otras librerías para conseguir el resto de funcionalidades.

Es bastante frecuente ver ReactJS usado en combinación con otras librerías. Hay quien ha integrado AngularJS y ReactJS (por motivos que ya veremos más adelante), y es habitual ver soluciones basadas en ReactJS y Backbone, una mezcla especialmente interesante puesto que Backbone aporta todo lo que le falta a ReactJS y no tiene un sistema de vistas propio.

El problema que trata de resolver ReactJS, al igual que todas estas librerías (o partes de estos frameworks), es el de construir un interfaz de usuario rico que permita mostrar en pantalla información sobre un modelo e interactuar con él. Esto es algo que puede complicarse rápidamente cuando tenemos mucha información a mostrar sobre distintos controles y necesitamos mantener sincronizada la información mostrada con el estado de los controles cada vez que se produce algún cambio.

La corriente general

Si pensamos en los frameworks y librerías más utilizados, AngularJS, Ember, Knockout, Durandal, etc., todos tratan de resolver el problema aplicando el patrón Model-View-ViewModel y un sistema de databinding bidireccional que se encargue de sincronizar automáticamente la vista y el viewmodel. Para ello suelen contar con algún mecanismo para definir declarativamente esos bindings y ahorrarnos mucho código.

El problema de este enfoque es que resulta muy difícil saber de antemano las implicaciones que tiene cada cambio. Al responder a una acción del usuario se provocan cambios en el modelo, que se propagan a distintos “controles” cuyo valores pueden cambiar, provocando nuevos cambios en el modelo y así sucesivamente, convirtiéndose en la fiesta loca de los rebotes:

Flujo de información MVVM

Cualquiera que haya trabajado con AngularJS se habrá encontrado alguna vez con el error “10 $digest() iterations reached” que indica que los rebotes entre modelo e interfaz de usuario no consiguen estabilizarse.

Este comportamiento hace que sea más complicado razonar sobre el flujo de información dentro de la aplicación y predecir el orden en que se acabarán ejecutando las cosas.

El enfoque alternativo

El planteamiento que realiza ReactJS es completamente distinto. ReactJS utiliza un sistema de databinding unidireccional, en el cual los controles son generados a partir de la información del modelo, pero la actualización del modelo se realiza de forma explícita.

Para montar este sistema, cada componente (control) de ReactJS cuenta con un método render que es el responsable de generar el HTML correspondiente al componente. Durante este proceso de generación, es posible enganchar manejadores de eventos a los elementos HTML para detectar cambios y actuar sobre el modelo. Cuando se producen cambios que afectan al estado interno del componente, éste se vuelve a renderizar por completo, no sólo aquellas partes el componente que han cambiado.

A simple vista, esto puede parecer sumamente ineficiente, pero aquí entra en juego una de las características de ReactJS que además lo convierte en una librería extremadamente eficiente: el Virtual DOM.

En lugar de generar directamente elementos HTML y modificar el DOM, que es una operación muy lenta, los componentes de ReactJS generan (renderizan) un modelo del DOM en memoria. Una vez generado el Virtual DOM completo, ReactJS se encarga de buscar las diferencias entre el DOM real y el virtual y realizar únicamente las modificaciones necesarias sobre el DOM real.

Esto implica un mayor consumo de memoria porque hay que mantener el Virtual DOM, pero generalmente no suele ser un problema y la mejora de rendimiento lo compensa. De hecho hay casos en los que compensa integrar este modelo con otros frameworks como AngularJS por la mejora de rendimiento que se consigue.

Para acabar de cuadrarlo todo, ReactJS mantiene una distinción muy clara entre dos tipos de información, las propiedades (props) del componente y el estado (state) del componente.

Las propiedades del componente están formadas por información que es inmutable para el componente. Esta información se recibe a través del objeto props en el momento de construir el componente y el componente puede asumir que no será modificada en ningún momento durante su ciclo de vida.

Se trata de información que el componente no “posee”, por lo que será otro componente el responsable de modificarla. Cuando esa modificación se produzca, el dueño de la información reconstruirá nuevamente todo su Virtual DOM asociado, incluyendo sus componentes hijos que serán creados desde cero con la nueva información. Es por ello que podemos asumir que durante el ciclo de vida de un componente, es decir, desde que se crea hasta que se destruye, esta información es inmutable.

El estado del componente se almacena en la propiedad state y está formado por aquella información que sí es gestionada y modificada directamente por el componente. Cada vez que se realiza un cambio en el estado del componente como respuesta a una acción del usuario (o a algún otro factor externo), ReactJS se encarga de renderizar nuevamente el componente por completo. Puesto que un componente puede contener otros componentes, en el proceso de renderizado se volverán a crear estos componentes hijos con la nueva información. Es posible (y habitual) que el estado mutable de un componente sean propiedades inmutables de sus componentes hijos.

En el siguiente esquema podemos ver cómo se genera la jerarquía la componentes y cómo se propaga la información de unos a otros:

Flujo de información reactjs

La información siempre fluye de componentes padres a componentes hijos, un componente hijo no puede modificar directamente el estado de un componente padre. Esto hace que sea más fácil razonar sobre el comportamiento general de la aplicación y las implicaciones de cada cambio realizado sobre el modelo y sobre el DOM.

Hay muchas situaciones en las que tenemos que notificar cambios en un componente hacia su padre. Para esos casos la solución es simple: incluir dentro de las propiedades inmutables que recibe el hijo al ser creado una función callback del padre que será invocada en el momento oportuno. De esta forma tratamos todo de forma homogénea y la función callback no es más que otro elemento más de las propiedades inmutables que recibe el componente al ser creado. Esto además nos ahorra recurrir a otro tipo de mecanismos, como eventos, con los cuales es más complicado seguir el flujo de ejecución.

A priori esta distintición entre estado mutable e inmutable puede parecer confusa, pero si lo piensas un poco es bastante más clara que otros sistemas como el anidamiento/aislamiento/copia de $scopes que hace AngularJS para solucionar el mismo problema.

Conclusiones

Como decía antes no soy ningún experto en ReactJS, así que no veas estas conclusiones como una verdad absoluta, sino como mi opinión personal en este momento sobre esta librería.

El alcance limitado de ReactJS puede ser un punto a favor o en contra, dependiendo de lo que estés buscando. Cuando empecé a analizar AngularJS ya avisaba de que si hacías una aplicación con AngularJS, te casabas con AngularJS, y un tiempo después eso se acabó convirtiendo en un problema.

Sin embargo, si no quieres tener que buscar componentes por separado e integrarlos tú mismo, recurrir a soluciones tipo “todo incluido” puede ser una buena salida, aunque hay que valorar los riesgos de ambas opciones (que los tienen).

En mi opinión, utilizar librerías específicas para cada responsabilidad de la aplicación es una buena estrategia a medio plazo, ya que permite cambiarlas por separado en caso de ser necesario y evita que acabes acoplando todo tu código a la filosofía de una librería concreta.

Esto es algo muy natural en plataformas como .NET, donde el acceso a datos te lo proporciona una librería, la capa de presentación otra, la inyección de dependencias otra, y así sucesivamente, pero en Javascript parece que hay una tendencia mayor a buscar la solución todo incluido.

El enfoque que tiene ReactJS para la gestión de la información en la vista me parece muy atractivo. Durante mucho tiempo utilicé un enfoque similar en aplicaciones de escritorio aplicando variaciones del patrón MVP (Model-View-Presenter) y siempre me resultó más fácil de seguir que el código basando en eventos y rebotes del patrón MVVM, aunque no cabe duda de que en esto hay un componente personal importante.

Además, con el tiempo he ido apreciando cada vez más el valor de la inmutabilidad y lo mucho que ayuda a razonar sobre un sistema, por lo que la separación que hace ReactJS entre lo que podemos considerar inmutable y lo que podemos considerar mutable en cada contexto (componente) me parece un acierto.

En próximos posts seguramente profundizaré un poco más en ReactJS y lleguemos a ver algo de código, pero como siempre, prefiero sentar las bases antes en empezar a trastear.

Posts relacionados:

  1. Datomic, una base de datos diferente

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

Blog Bitix

Procesador de documentos LyX

September 07, 2014 01:00 AM

LyX

Hace unos días publiqué una nueva edición del libro PlugIn Tapestry, sobre el framework Apache Tapestry para el desarrollo de páginas y aplicaciones web con Java. En este artículo quiero recoger las herramientas que utilicé para escribirlo y algunas cosas básicas a conocer para tener un libro con un aspecto decente y más prefesional. Son cosas muy básicas pero que a mi me costo un poco poco encontrarlas para conseguir lo que quería, quizá a alguien le sirvan.

Herramientas

Empecé evaluando la herramienta más adecuada para escribir el libro, en un principio empecé con Google Docs, también con LibreOffice, sin embargo, al final descubrí LyX y fué el que empleé. ¿Por que LyX? Porque al contrario de Google Docs y LibreOffice que son procesadores de textos LyX es un procesador de documentos ¿que significa esto? Que con LyX te centras casi exclusivamente en escribir el contenido del libro no de estar formateándolo. Como procesador de documentos hace que no tengas tanto control sobre los estilos pero a la vez hace que todo el libro tenga un formato homogéneo y no tengas que «microgestionar» el estilo de cada elemento, en un documento grande de más de 250 páginas es muy útil y te evita casi todo el trabajo de mantener la coherencia en los estilos, ahorrándole a uno mucho tiempo.

LyX

LyX es una herramienta que funciona excelentemente, mucho mejor que LibreOffice según mi experiencia y tiene más posibilidades que Google Docs. LyX tiene varias funcionalidades que nos serán muy útiles como la creación de índices (también para figuras, cuadros, …), inclusión de figuras y referencias que permiten a un término hacer referencia a otra parte del libro, inlcuir los listados de código en archivos externos, …

Una de las primeras cosas que deberemos hacer es indicarle a LyX la clase de documento que pretendemos escribir a partir del cual se establecerán los estilos y opciones que LyX nos ofrecerá, también las secciones que dispondremos. Con la clase de documento book tendremos secciones numeradas y no numeradas, la diferencia es que además de unas tener numeración y otras no es que las numeradas aparecerán en el índice y las no numeradas no. Para ello seleccionamos Documento > Configuración.

Entre las mismas opciones podemos seleccionar las tipografías, el diseño de la página (A4, A5, …), los márgenes y una parte importe donde podremos modificar varios aspectos del documento, el preámbulo LaTeX, lo difícil de esta sección es saber cuales son las opciones podemos escribir en él pero si necesitamos modificar algo probablemente debamos insertarlo en esta sección. Un posible contenido es el siguiente donde defino y modifico el color de los hiperenlaces del libro y las opciones por defecto de los listados.

<noscript><pre><code>\usepackage{listings} \definecolor{tapestry}{RGB}{86, 157, 2} \definecolor{gris}{RGB}{200, 200, 200} \lstset{language=java,tabsize=4,breaklines=true,frame=single,rulecolor={\color{gris}}} \hypersetup{linkcolor=tapestry,citecolor=tapestry,urlcolor=tapestry}</code></pre></noscript>

Otras opciones deberemos incluirlas como código Tex al principio (Insertar > Código Tex) del documento, para establecer cuál es la palabra a emplear para nombrar los capítulos, figuras y listados que por defecto aparecerán en inglés en vez de español (Chapter 1 en vez de Capítulo 1). Este es el primer recuadro en rojo de la imagen LyX.

Con LyX si necesitamos reorganizar los capítulos o secciones es muy simple, para ello abrimos el panel del esquema, seleccionamos la sección o capítulo y pulsamos sobre las flechas de ordenación.

Fuente del documento

Podemos modificar la fuente del documento en Documento > Configuración > Tipografías. La fuente del elemento Romana será la que se use para la mayoría de elementos del documento.

Encabezados y pies de página

En Documento > Configuración > Diseño de página podemos establecer si queremos encabezados y pies de página en los que se incluye el número de página. Tenemos a nuestra disposición de varios tipos.

Referencias

Las referencias permiten hacer referencia a otra parte del documento donde el concepto esté explicado de forma más completa. Las referencias son creadas en dos pasos, primero toda sección del documento a la que queramos hacer referencia deberemos asignarle una etiqueta Insertar > Etiqueta.

Una vez que disponemos la etiqueta podemos insertar una referencia a ella en cualquier otra parte del documento con Insertar > Referencia cruzada. Disponemos de varios formatos para la referencia como texto al que hace la referencia o como la página en la que se encuentra.

Listados de código

Si el libro versa sobre un téma técnico y queremos mostrar listados de código tenemos dos opciones incrustar el código dentro del texto en LyX o hacer que se incluyan desde un archivo externo. En mi caso prefiero la segunda ya que de este modo si en algún momento queremos hacer alguna corrección a algún listado me parece más fácil hacerlo en el archivo externo que en el propio LyX, además el documento LyX queda más sencillo que con listados de código.

Para insertar un listado de código como documento externo debemos usar la opción Insertar > Archivo > Documento hijo, seleccionamos el archivo, en tipo de inclusión seleccionamos Listado de código y con el parámetro language=Java podemos hacer que LyX proporcione resaltado de sintaxis según el lenguaje del listado, en este caso Java.

Portada

Con LyX no podremos crear una portada atractiva dado lo limitado que estamos para modificar los estilos. Sin embargo, podemos incluir las páginas de un pdf externo a nuestro ducmento LyX. Este pdf externo lo podemos crear con la herramienta que queramos LibreOffice o Inskape. Con la opción Insertar > Archivo > Material externo podemos insertar todas las páginas del documento o solo las que queramos.

Corrector ortográfico

Parte de la revisión consiste en corregir los posibles fallos ortográficos que cometamos, LyX incluye un corrector ortográfico. Para hacer uso de él deberemos instalar los diccionarios, en Arch Linux instalaremos los paquetes aspell y aspell-es. Una vez instados podemos hacer uso del corrector con Herramientas > Corrector ortográfico, una vez iniciada la revisión podremos ir corrigiendo las palabras que no se encuentren en el diccionario.

Versiones en formato de libro electrónico (pdf, epub y mobi)

En un principio no lo tuve en cuenta pero con LyX es posible generar muy fácilmente además de la versión pdf, la versión epub y mobi del libro con la ayuda de Calibre. La versión de libro electrónico en formato epub y mobi es muy útil para los usuarios que posean un lector de ebooks como el Kindle o cualquier otro, el pdf también se puede leer en un ebook pero una página del pdf no entrará de forma completa en la pantalla y obligaremos al usuario a hacer varios cambios de página.

Una vez que tenemos nuestro documento podemos exportarlo a diferentes formatos, uno de ellos es pdf para ello seleccionamos la opción Archivo > Export > PDF (LuaTeX). Para las versiones en libro electrónico deberemos exportar primeramente a formato LyXHTML una vez tenemos el libro en este formato comprimimos en un archivo zip todos los archivos que forman parte del libro (los genera en la misma ubicación del archivo .lyx). Este zip lo importamos en nuestra biblioteca de Calibre y a continuación lo empleamos para hacer la conversión a formato epub y luego a mobi. Con esto ya tenemos la versión en formato electrónico de nuestro libro que podrá ser leído de forma más cómoda en un libro electrónico.

Con LyX le podemos ofrecer al usuario la versión del libro que prefiera sin mucho trabajo por nuestra parte.

Revisión, difusión y publicidad

Para finalizar diré que escribir un libro es un trabajo que consume mucho tiempo y esfuerzo y aunque parezca que no escribir el contenido del libro puede no ser la parte más costosa, revisarlo me costó tanto como escribirlo así como el hacer la aplicación con los ejemplos, la página en la que la alojaría y el marketing para darlo a conocer lo máximo posible publicándolo en webs en las que sus usuarios podrían estar interesados, en este caso en JavaHispano, Barrapunto, en este blog y en los varios planetas en los que este blog puede publicar sus entradas.

Referencia:
Introducción a LaTeX/XeTeX/LyX

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

Picando Código

Guardianes de la Galaxia

September 05, 2014 04:30 PM

Guardians Of The Galaxy

El martes pasado fui al cine a ver por segunda vez Guardianes de la Galaxia, y aprovecho para escribir al respecto. Seguramente ya se habrán enterado que es una de las películas más taquilleras del año, rompiendo varios récords de venta en el mundo. Si no la vieron, se están perdiendo una buena película.

Parece que Marvel encontró la fórmula para hacer el tipo de películas que yo quiero ver. Cada nueva entrega dentro de su universo cinematográfico me gusta más. Ya Captain America: The Winter Soldier había superado mis expectativas, pero Guardians Of The Galaxy me dejó más que sorprendido, pasando a mi lista de películas preferidas (no solo de Marvel).

Guardians Of The Galaxy

No es un título más en la creciente lista de cine de superhéroes. Es mas bien una película de aventuras, acción y ciencia ficción centrada en un grupo de antihéroes en el espacio. Combina de forma armoniosa estos géneros con bastante humor y la dósis justa no empalagosa de drama.

Los personajes son geniales, me hicieron encariñarme en el poco tiempo que dura la película. Me gustó cómo fue interpretado cada uno de ellos y las interacciones que se daban. Dudo que haya podido existir una elección mejor del elenco, todo se da de manera tan fluída y eficiente que no le cambiaría nada (veremos si sale una versión extendida con todavía más escenas más adelante). Son el tipo de personajes que me gustaría ver en una serie semanal de ciencia ficción en televisión dirigidos por Joss… Bueno, se entiende.

¿Sutileza? No, no van a encontrar ni un poquito de eso acá. La película incluye lo que en mi libro, es una de las mejores escenas en la historia del cine:

Rocket & Groot

La primera vez que salí de verla, hice el comentario “Es la Star Wars de esta década”, refiriéndome a la sensación que me había dejado. Tenemos naves espaciales peleando en mundos intergalácticos, seres alienígenas, una historia atrapante y divertida, y bastante sentimiento esparcido por los distintos componentes que la conforman. Ojalá los nuevos episodios de Star Wars vayan por este lado y no por el de las precuelas…

La música es un protagonista más, con una banda sonora de temas de los años 70 que combina muy bien con el ambiente espacial futurista. También hay canciones de las “épicas” de películas del estilo, y están equilibradas acompañando a la acción, pero el cassette de temas pop de Peter Quill…-perdón, Star-Lord- se lleva el premio. Veo que en el espacio encontraron una alternativa a las pilas, no creo que Quill se haya llevado un suministro de por vida de baterías AA al espacio, y recuerden que los walkman tienen piezas mecánicas así que gastan bastante.

No necesitan saber nada de antemano ni haber visto otra de las películas de Marvel para entender qué está pasando. Personalmente no conocía a los personajes principales más que de alguna aparición mínima como secundarios en algún cómic. Pero me dió cierta emoción escuchar en el cine que se hable de los Kree y Ronan el Acusador. Me encantó cómo llevaron a Thanos a la pantalla grande. Se ve como un tipo jodido, se impone, y da la sensación de que “todavía no vimos nada”. Va mi apuesta que Avengers 3 va a estar basada en Infinity Gauntlet con la intersección del universo cósmico de Marvel y los héroes de la tierra (no es una apuesta tan arriesgada a esta altura, se veía venir tras la escena post-créditos de Avengers y se confirma ahora con las Gemas del Infinito).

Mi recomendación final: véanla, ríanse, lloren (un poquito nomás) ¡y disfruten!

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

Picando Código

Videos de la JSConf Uruguay 2014

September 05, 2014 02:30 PM

JSConf Uruguay

JSConf Uruguay

Ya se están subiendo a YouTube los videos de la JSConf Uruguay 2014, realizada el pasado mes de marzo. Entre los videos van a encontrar charlas de Douglas Crockford, Jeremy Ashkenas, Angel Java López y más.

Pueden ir viéndolos en el canal de YouTube de la conferencia. Todavía no están subidas todas las charlas, pero anunciaron que van a ir subiendo más.

Con Pablo Terradillos y Pablo Cúbico, Mozillians argentinos, hicimos un taller sobre desarrollo de aplicaciones para Firefox OS. Creo que los talleres no fueron grabados, así que no creo que haya video. Estén atentos al canal de YouTube o sigan a @JSConfUY en Twitter para enterarse cuando haya novedades.

Si no pudieron ir y se quedaron con las ganas, estén atentos a JSConf Buenos Aires a realizarse a fines de noviembre. Todavía no hay muchos oradores anunciados, pero está abierto el llamado a charlas. En una de esas cruzo el charco en noviembre y me mando hasta ahí.

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

xailer.info

Lanzamiento de Xailer 3.3

September 05, 2014 08:16 AM

Estimados usuarios de Xailer,

Tenemos el placer de anunciaros una nueva versión de Xailer que incluye un montón de novedades y mejoras, a destacar las siguientes:

    • General:
      • Potencial GPF en modo multithread
      • Correción en el pintado del background de controles
      • Perdidas de memoria esporádicas
    • IDE:
      • Creación de controles de usuario
      • TLabelExNuevo editor de propiedades
      • En sistemas multi-proyecto permitir enlazar ficheros de recursos de los proyectos hijos en el proyecto padre
      • Al ‘publicar proyecto’, comprimir todos y cada uno de los recursos que aparezcan en los ficheros .rc
      • Asistente para ordenación de controles por posición
      • Debugger: Mejor soporte de hashes y matrices
      • TTabControl: Permitir insertar pestañas en controles heredados
      • Editor:Actualizado a Scintilla 3.4.2
      • Editor:Soporte de PHP, JavaScript y HTML
      • Intellisense:Mostrar funciones de clase con distinta imagen
      • Intellisense:Mostrar lista con Ctrl+Sp aunque el simbolo haya sido resuelto
      • Editor DBF: Error en edición de tipos numéricos con decimales
      • Restaurar las ventanas despues de ejecutar en el mismo orden en que estaban
    • DataControls
      • TDbfDataset: Nuevo parámetro lScoped en método SetRelation
      • TMySQL: Soporte de tipos float con notación científica
      • TMySQL: Tipos MEMO y BLOB en DbStruct no estaban diferenciados
      • TWebDataSource: Nuevos métodos UpdateFile y DeleteFile
      • TWebDataSource: Error en operaciones de BulkExecute
      • TSqlite: Actualizada librería a la versión 3.8.4.3
    • Controles
      • TControl: Nuevas propiedades nAlignMarginLeft, nAlignMarginTop, nAlignMarginRight y nAlignMarginBottom
      • TFolderPage: Perdida de memoria
      • TFolderPage: El evento OnChangeFocus no se disparaba cuando cambiaba la página
      • TFlatBtn: Nueva propiedad nClrTextHot
      • TBrowse: Error de ajuste de ancho de la columna cuando ésta tiene varias líneas
      • TMenuItem: Error si el evento OnCheckState devolvía NIL
      • TPicture: Nueva propiedad nTimeFrame para Gifs animados que indica el tiempo de espera entre frames de la imagen
      • TEdit: Nuevo método Replace idéntico al existente en TMemo
      • TLabelEx: Soporte de color con formato <#rrggbb>
      • TPicture: Parametro nBgColor adicional en método MakeThumbnail()
    • Clases
      • TZipArchive: Error en lPathRelative
      • TCanvas: Nuevo método Polygon
      • TIni: Nuevo parámetro lTrim en método SetEntry
      • TSysImageList: Perdidas de memoria
    • Fast-Report
      • TFastReport: Nueva propiedad lLoadOnDemand
      • TFastReport: Soporte de códigos QR
      • TFastReport: Nuevos métodos: ClearVariables, VariablesList y CategoryList
      • TFastReport: Nuevo método SetFormatSettings
      • TFastReport: Preview incompleto cuando se lanzaba después de haber entrado en modo diseño
      • TFastReport: Error en carga de datasets vacios en modo diseño
      • TFastReport: Error en establecimiento de variables de categoría Xailer
      • TFastReport: Error en establecimiento de valores antes de que se cargara la DLL
      • TFRDataset: Nueva propiedad lLoadOnDemand
      • TFRDataset: Error con determinados tipos de ADS
      • TFRPreview: Nueva propiedad lBtnClose
      • TFRPreview: Nuevos métodos Close() y PreviewClose()
    • Funciones
      • Nueva función XA_Is_Win8()
      • GPF en StrEncodeEscape() cuando se usaba como primer parámetro una cadena vacía
      • Nueva función Polygon()
      • Nueva función EnumResourceNames( <hModule>, <cType> | <nType> ) –> aResourceNames
    • Ejemplos
      • Nuevo ejemplo de FastReport

Os recordamos que para poder usar esta nueva versión hay que tener una suscripción activa de Xailer y que exige realizar de nuevo el registro de todas sus instalaciones. Todos los usuarios con suscripción activa deben haber recibido un E-mail con la nueva información de registro, pero en cualquier caso puede volver hacer el registro directamente desde la opción de menú Ayuda-Registrar el producto.

En caso de no tener una suscripción activa sólo podrá utilizar Xailer 3.3. en modo DEMO y por lo tanto deberá instalarla en un distinto directorio.

Un saludo

[El equipo de Xailer]

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

Navegapolis

Gestión y procesos en empresas de software

September 04, 2014 07:14 PM

cubo Descargar Descargar el artículo en formato pdf.

Introducción

Es tanta la información de estándares, modelos, marcos y prácticas para desarrollo de software, que apostar por uno u otro puede acabar siendo más una decisión guiada por conformidad con la mayoría, que por conocimiento y  evaluación de las opciones existentes. Para ayudar en esta decisión este artículo dibuja el marco general de los modelos de procesos y prácticas de la industria del software: CMMI, ISO 15504, Scrum, Extreme Programming, DSDM, MSF, RUP, PMI, etc. en una síntesis ejecutiva que muestra los principios de los principales modelos, sus fortalezas y debilidades.

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

Picando Código

Nintendo Wii U

September 04, 2014 03:00 PM

Desde hace poco más de un año soy el feliz poseedor de un Nintendo Wii U. La consola fue anunciada en el E3 de 2011, y desde su lanzamiento ha pasado por varias etapas buenas y malas. Las expectativas de venta de Nintendo no fueron alcanzadas, llevando a varios cambios en marketing, estrategias y demás. Pero este post no es para hablar de esos temas, sino mas bien de lo que ha sido mi experiencia hasta ahora con mi Wii U.

Cuando compré el sistema no había tenido la oportunidad de probar uno antes, confié ciegamente en la gran N que poco me ha defraudado en el pasado. Lo primero que noté fue que el Gamepad es mucho más liviano de lo que imaginaba. Además es super cómodo usarlo para jugar y la pantalla táctil agrega formas interesantes de interactuar con los juegos.

Wii U Gamepad

Desde que la tengo han habido varias actualizaciones de firmware, y el uso en general es bastante rápido y cómodo. Es genial el menú de acceso rápido a los juegos (que apareció en una actualización este año), con el cual prendemos el Wii U desde el control y podemos arrancar a jugar a algo sin pasar por la pantalla de inicio del sistema.

Los juegos

Uno de los primeros juegos que disfruté mucho fue Batman: Arkham City – Armored Edition. Situado en el universo de Batman: Arkham, la historia nos permite asumir el rol del vengador ancapotado en un ambiente open world en Arkham City. Los gráficos son espectaculares y en muchas etapas del juego sentí la necesidad de afirmar en voz alta: “I am Batman!” con la voz de Abed Nadir imitando al Batman de Christian Bale.

Combina elementos del estilo aventura, beat ‘em up y sigilio. Todavía hoy es de los juegos que mejor aprovecha el Gamepad haciendo uso de la pantalla táctil y los sensores de movimiento. De destacar el trabajo en las actuaciones de las voces de los personajes, estando presentes Kevin Conroy y Mark Hamill en los papeles de Batman y Joker respectivamente (tradicional en el universo animado de DC).

Batman: Arkham City Armored Edition

Batman: Arkham City Armored Edition

Si bien ya terminé la historia principial, es un juego que en cualquier momento vuelvo a jugar para completar alguna de las tantas misiones laterales. Además es divertido planear por Arkham City golpeando malechores y descubriendo secretos. También salió en Wii U Batman: Arkham Origins, dentro de la misma serie. Se consigue a un precio bastante barato, así que podría llegar a mi colección eventualmente.

Para jugar con amigos no hay como Nintendoland (que venía incluido con la consola) y Mario Kart 8. Demás está decir que Mario Kart 8 es un juego casi perfecto, tanto para jugar contra la computadora como con un grupo de amigos. Mantiene el nivel incomparable de instancias anteriores de la franquicia, agregando la capacidad gráfica del Wii U y nuevas características, personajes y un diseño de pistas impresionante.

Si no recuerdo mal, es el primer juego de Nintendo que incluyó DLC (contenido descargable). En principio con nuevos autos Mercedes-Benz en descarga gratuita. Pero también dos paquetes pagos de DLC (a un precio bastante razonable) que agregan en total 16 pistas, 6 personajes y 8 vehículos nuevos.

Mario Kart 8

Mario Kart 8

Competir por Internet me ha ayudado a darme cuenta de algo: Soy relativamente bueno jugando Mario Kart. Son años de experiencia… Más arriba escribía que es casi perfecto por un solo pequeño detalle: el modo batalla. En versiones anteriores existían pistas especiales hechas a medida para reventarse los globitos con contrincantes. En esta ocasión, son las mismas pistas que se usan para carreras, por lo que es más bien una carrera con modo “eliminación” que lo que venía siendo el modo batalla hasta entonces.

En cuanto a Nintendoland, es un juego que mucha gente pasa por alto. En cierta forma es al Wii U lo que Wii Sports fue al Wii: un prototipo para mostrar cómo explotar las capacidades del sistema. Hace uso del Gamepad y los controles Wiimote de formas bastante creativas (como lanzar shurikens a la televisión deslizando la mano por la pantalla táctil del Gamepad) en varios mini juegos basados en las franquicias de Nintendo.

A pesar de eso, me ha brindado muchísimas horas de diversión con amigos. Los juegos de Pikmin Adventures, Metroid Blast, Luigi’s Ghost Mansion (el fantasma violín para los amigos), Mario Chase y Animal Crossing: Sweet Day son ideales para jugar con más gente y pasar horas divirtiéndose.

Por último comentar Super Mario 3D World, otro de los grandes títulos para Wii U. El juego es una mezcla perfecta de elementos clásicos que apelan a la nostalgia de quienes crecimos jugando juegos de Mario con características nuevas que lo hacen genial. El apartado gráfico es espectacular y el diseño de niveles y jugabilidad es impresionante. Podemos jugar con Mario, Luigi, la Princesa Peach, Toad y algun personaje más si avanzamos mucho.

Super Mario 3D World

Super Mario 3D World

Los días después de haberlo recibido ansiaba terminar de trabajar para ponerme a jugar al Nintendo e ir descubriendo los nuevos mundos del juego. Esa sensación que no tenía desde hace unos cuantos años :) Tras terminar la historia principal, volví a jugarlo hace poco para intentar obtener todas las estrellas del juego (al estilo Super Mario 64, podemos “darlo vuelta” sin tener todas las estrellas). Me volví a enganchar al desbloquear un par de mundos nuevos que mejor no comentar por si alguien todavía no jugó y lo piensa jugar. Así que en estos días retomo nuevamente…

Conclusión

La sensación general del Wii U es que renovó las ganas  de jugar al Nintendo. Entre los nuevos juegos y la compatibilidad completa con el Wii y sus títulos, abrió las puertas para que me pusiera al día con un montón de cosas.

Es sumamente divertido para jugar solo y con amigos. Ya retomé la tradición “juntarse a jugar Mario Kart” que tenía en la época del Nintendo 64, y nunca faltan un par de partidas de alguno de los minijuegos en Nintendoland. Mas allá de las estrategias de marketing, el estado del mercado de los videojuegos y demás, Nintendo sigue sabiendo cómo hacer buenos juegos para que la gente se divierta y pase bien. Veo el valor y entiendo la decisión de Nintendo de darle más importancia a las instancias multi-jugador cuando se hacen desde el mismo sillón y no a través de Internet.

Se vienen un montón de juegos nuevos interesantes: Hyrule Warrios este mes, Super Smash Bros. Wii U, Splatoon y nuevos títulos en las sagas Starfox y The Legend Of Zelda para el año que viene. Con los que ya hay, incluyendo toda la biblioteca de títulos de Wii, hay diversión de sobra. Pero con más de un título nuevo por mes de acá al año que viene, seguro hay Wii U para rato y para todos los gustos.

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

Arragonán

Semana 325

September 02, 2014 12:15 AM

Esta semana fue bastante productiva, con la mezcla que aún siendo agosto la gente anda a medio gas y que tenía la semana bastante bien organizada (raro en mi :P), hasta me pude escapar una tarde de piscineo. Cosa que se agradecía en una semana calurosa como la pasada.

El jueves tuvimos quedada, un tanto furtiva, de Agile Aragón. Supongo que, de nuevo, por las fechas y porque tampoco se pretendía hacer algo más allá que tomar unas cervezas en petit comité no tuvo mucho quórum; aunque me dio que pensar que a nivel de comunidad quizás deberíamos usar más los canales existentes para comunicar mejor estos eventos un tanto espontáneos y que pueda venir más gente.

Finalmente la propuesta enviada la semana pasada no salió, es algo dentro de lo habitual, pero en esta ocasión se nos comunicó en 2-3 días.

Aprovecho para comentar mi experiencia con esto, por si a alguien le sirve: El tema de aceptación de propuestas se asimila mucho a los procesos de selección de personal. Se queda un poco en el aire y lo normal es que no se comunique que una propuesta ha sido rechazada, como cuando te hacen una entrevista y te dicen que ya te llamaremos. Aunque a diferencia de muchos procesos de selección que pueden llevar bastantes semanas, por norma general, si no se me acepta una propuesta en 1-2 semanas la doy por rechazada y me olvido de ella.

En lo que sí estamos:

  • En mhop estuve en cuestiones de soporte para el resto del equipo, pero nada de desarrollo.
  • En Nort estuve trabajando tanto en la aplicación web grails como en la móvil híbrida con cordova. Trabajando en cambios de frontend metiendo mucho rollo ajax a alguna interfaz, en temas relacionados con integración con facebook y en resolver algunos bugs.
  • No es que trabajara mucho en minchador, pero estuvimos viendo el diseño casi-definitivo de la nueva landing. Poco a poco se ve más cerca el poder hacerla pública.

Buena semana.

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

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

Casio FX-82ES Plus

September 01, 2014 11:29 AM

Desde la Casio fx-17, me han gustado las calculadoras, en especial las científicas de Casio. No debemos olvidar que Casio fueron los creadores de la primera calculadora eléctrica en 1957 (14-A), y posteriormente en 1972 de la conocida Mini CM-602, que miniaturizando sus componentes supondría un éxito de ventas en todo el mundo. En mi [...]

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

Koalite

No subestimes el poder de un log

September 01, 2014 05:06 AM

Desarrollar software sería mucho más fácil (aunque tal vez menos divertido) si todo funcionase siempre. La realidad es que, por muchos tests automátizados que escribas y muchos motivos que tengas para cuidar la calidad del software, antes o después, te encontrarás con problemas de lo más exótico que jamás hubieses pensado que podrían llegar a producirse.

Si tienes suerte, darás con un usuario muy colaborador que te proporcionará una lista exacta de los pasos necesarios para reproducir el problema, podrás reproducirlo en un entorno de desarrollo y, usando toda tu artillería pesada de depuradores, monitores, sniffers y demás, conseguirás solucionarlo.

Si vives en el mundo real, es probable que muchos de esos problemas se produzcan en condiciones extrañas, con usuarios que “no saben que han hecho, pero la aplicación falla”, y sean muy difíciles de diagnosticar (no digamos ya de reproducir en un entorno de desarrollo).

Para estos casos, hay una herramienta que, por su simplicidad, resulta muy útil: un buen log.

Existen muchas formas de obtener información sobre el comportamiento de una aplicación una vez que llega a producción. Por ejemplo, puedes conseguir estadísticas de uso, puedes guardar información de errores o puedes mantener un histórico con las acciones realizadas por los usuarios con fines de auditoría. Todo esto lo puedes hacer de forma “artesanal” o integrándolo con sistemas más potentes y estandarizados como contadores de rendimiento, eventos de windows, syslogs, etc.

Teniendo en cuenta que existen todos estos sistemas que permiten mantener enormes históricos y realizar complejas consultas y análisis, ¿tiene sentido escribir un triste log en un fichero de texto?

El poder de la simplicidad

La ventaja fundamental de un fichero de log frente a sistemas más potentes es su simplicidad.

Generar un fichero de texto plano es fácil desde cualquier lenguaje de programación, no requiere desplegar servicios externos (o usar servicios de terceros) para almacenar la información, se puede consultar con cualquier editor de texto en cualquier dispositivo y se puede compartir de mil formas diferentes, desde un email hasta una memoria USB.

Esto permite que generar un log suponga una inversión inicial muy baja y no tengamos que dedicar mucho esfuerzo a montar una infraestructura más potente hasta que no sea necesaria (vamos, YAGNI y todas esas siglas que molan tanto).

No obstante, con el paso del tiempo, es posible que merezca la pena automatizar ciertos procesos relativos a la obtención de los logs. Por ejemplo, puede ser interesante poder realizar un envío automático de logs desde la aplicación (o con una herramienta externa, por si la aplicación ni siquiere arranca), solicitar remotamente el envío de esos logs para equipos que no están siempre conectados, o al menos ayudar al usuario a preparar un zip con los logs que luego pueda copiar a una memoria USB.

Aprovechar esta simplicidad no quiere decir que dejemos de lado otros mecanismos más potentes. Por suerte, la mayoría de librerías de logging disponibles permiten enviar información a distintos almacenes, y por el mismo precio que generamos nuestro humilde fichero de log podemos ir alimentando una base de datos, el visor de sucesos de windows o un syslog.

Qué información debe contener un buen log

La utilidad de un log va a depender directamente de la calidad de la información que contenga. Si partimos de la base de que nuestro objetivo fundamental con el log es resolver problemas, parece claro que la información que debemos incluir en el log es aquella información que nos gustaría tener cuando ocurra un problema.

El log debe contener información relevante para la aplicación, que nos permita saber qué está ocurriendo en todo momento en la aplicación, por ejemplo, cuando si estuviésemos hablando de un cliente de twitter, un log debería poder mostrar los intentos de enviar un tweet que hace el usuario o el número de tweets descargados cada vez que se conecta al servidor.

Junto a este tipo de información, también puede resultar útil almacenar información del entorno de ejecución: versiones de aplicación, sistema operativo y plataforma (CLR, JRE, etc.), usuario de sistema que ejecuta la aplicación, ruta de ejecución, etc. Además, podemos incluir una monitorización cada cierto tiempo para controlar aspectos como la cantidad de memoria disponible, el nivel de batería (si procede), si hay conexión disponible o no…

Todo esto depende mucho del tipo de aplicación, pero a veces es necesario contar con esta información para tener un cierto contexto que nos ayude a comprender por qué se produjo ese OutOfMemoryException o por qué dejó de responder la resolución DNS.

A la hora de presentar esta información en el log debemos tener en cuenta que debe ser fácilmente legible para un humano (probablemente nosotros) y sería de agradecer que fuese más o menos sencillo buscar cosas en él desde un editor de texto normal, ya sea con subcadenas o con expresiones regulares.

Merece la pena dedicar un poco de tiempo a formatear correctamente los mensajes en el log para que sean homogéneos y realmente nos ayuden a seguir lo que está pasando en la aplicación.

Es especialmente importante registrar en el log la forma en que se desarrollan procesos desatendidos. Volviendo al cliente de twitter, si va a estar actualizando datos en background, es importante registrar esos intentos de actualización para poder diagnosticar problemas cuando el usuario nos diga “no recibo nuevos tweets” y tengamos que decidir si es que se ha colgado la hebra que los actualiza, hemos dejado de recibir notificaciones push, no hay cobertura, el servidor está caído, o realmente no hay ningún tweet que recibir.

Otro punto en el que un buen log puede salvarnos muchas horas de depuración es en la integración con sistemas externos. Tener información del tiempo que tardan en respondernos o la información que se intercambia con ellos (en la medida de lo posible) puede ser vital a la hora de decidir si el problema está en el sistema externo o en nuestra aplicación (sí, nuestras aplicaciones también puedes tener problemas).

Qué información NO pertenece a un log

Hay información que no pertenece a un fichero de log (aunque podamos incluirla en él), sino que forma parte de los requisitos propios de la aplicación. Por ejemplo, si nuestra aplicación debe mantener un histórico de qué usuario modifica qué productos, eso deberá tratarse de forma adecuada en la aplicación y no sólo como entradas en el log.

Podemos tener casos en que necesitamos tener información para realizar una monitorización proactiva del sistema (memoria en uso, peticiones por segundo, etc.). En ese caso esta información deberá estar disponible por otros medios más adecuados que un log, que no deja de ser una herramienta reactiva, es decir, para cuando ya ha ocurrido el problema.

Por último, tampoco debemos incluir en el log toda la información de llamadas a métodos que se realizan en la aplicación. Esto, que es muy tentador cuando uno empieza a jugar con AOP y cosas como PostSharp, en realidad forma parte de una traza, no de un log, y en el log lo más que puede hacer es generar ruido y dificultarnos encontrar la información relevante para el problema que necesitamos resolver.

Conclusiones

Cuando no tenemos la opción de engancharnos a un depurador para ver qué está pasando con una aplicación que da problemas, utilizar un simple fichero de log puede ser extremadamente útil para resolver el problema.

A la hora de generar el log debemos definir claramente qué tipo de información necesitamos guardar en él y hacerlo de forma ordenada para que, cuando sea necesario revisarlo, realmente resulte útil y no sea una amalgama sin sentido llena de ruido e información redundante.

Al final, la última línea de soporte somos nosotros, y cuando llega el momento de solucionar un problema, contar con las herramientas adecuadas puede ser la diferencia entre resolver un problema en un rato o sufrirlo durante días.

No hay posts relacionados.

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

Blog Bitix

Actualización del libro PlugIn Tapestry

August 29, 2014 10:16 PM

Apache Tapestry

Hace un poco más de una año publiqué el libro PlugIn Tapestry que como su nombre ya adelanta versa sobre el framework Apache Tapestry para el desarrollo de aplicaciones y páginas web con Java. Casi 300 páginas de documentación que describen este framework, como usarlo y va más allá explicando como realizar algunas de las tareas comunes que es necesario hacer en casi todas las aplicaciones web independientemente del framework que elijamos pero en este caso visto desde el punto de vista de Tapestry.

En esta actualización he revisado capítulos como el Inicio rápido para empezar a desarrollar en unos pocos minutos, la sección que trata sobre Plantillas para dar a las páginas un aspecto común, la sección que trata sobre unas Convenciones para los archivos de literales, ampliada la sección de Principios en la que se detalla cuales son las ideas y objetivos por los que se rige el framework, también reescrita la sección de Integración con Spring, una de las librerías más usadas y que facilita el desarrollo enormemente.

Pero además he incluido nuevo contenido que he publicado en diferentes artículos en mi bitácora desde la plublicación original del libro. Estos han sido Como ejecutar Apache Tapestry en un servidor de aplicaciones JBoss o Wildfly, explicada la página Dashboard que nos permite obtener información interesante mientras desarrollamos como que páginas y componentes incluye la aplicación o las estadísticas de Hibernate, explicadas las diferencias del modelo «pull» en el que se basa Tapestry del modelo «push» en el que se basan la mayoría de frameworks orientados a acciones independientemente del lenguaje (Grails, Django, Symfony, ASP.NET MVC), como servir los recursos estáticos desde una red de contenidos (CDN, Content Delivery Network), la anotación Cached que permite evitar invocaciones a métodos devolviendo el resultado obtenido en la primera invocación, como usar Tapestry en una aplicación de forma «standalone» fuera del contexto de un servidor de aplicaciones, la anotación Secure y como añadir más seguridad usando el protocolo seguro HTTPS y finalmente añadido un nuevo formato en el que se puede leer el libro, HTML, además de PDF y los formatos para libro electrónico EPUB y MOBI.

¡Y luego compártelo!

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

Blog Bitix

Doble barra de botones con Apache Tapestry

August 29, 2014 11:04 AM

Apache Tapestry

Por motivos de usabiliad en algunas páginas se incluyen dos barra de botones, una antes de una larga sección y otra después. El motivo de la doble barra de botones inicial es que no sea necesario hacer «scroll» hasta el final de la página para acceder a los botones y realizar la acción que permitan. Por el contrario, inlcuir la barra de botones al final de la página permite que una vez seleccionados los elementos o revisado el contenido de la sección hacer disponibles las acciones que es probable que se quieran realizar.

Dependiendo del framework web que utilicemos podremos hacerlo de una o varias formas pero de lo que estamos seguros es que copiar y pegar haciendo que el código esté duplicado no es una buena idea por los problemas de mantenimiento que puede suponer. Pero crear una pequeña plantilla o archivo exclusivo para incluir la barra de botones tampoco es la solución ideal, ¿por que? pues porque creando un archivo específico con la botonera puede que nos ocasione un problema que denominaré de «microgestión», es decir, nos obliga a crear un montón de pequeños archivos pequeñitos y hacer referencia o utilizar el mecanismo de inclusión que dispongamos para usar el contenido en unos de otros. En una aplicación grande esta microgestión si nos vemos obligados a ella puede llegar a ser molesta al desarrollar cuanto menos.

¿Como se puede evitar? En el framework Apache Tapestry la doble botonera puede hacerse de varias formas una de ellas es crear un componente pero esto nos obliga a crear un archivo para la clase java y probablemente tambien un archivo de plantilla con el contenido html causando el problema de la microgestión. Pero en Tapestry también podemos hacer uso del componente block que sirve para incluir en él cierto contenido y el componente delegate que sirve para emitir el contenido entre otras cosas de un componente block. Usando estos dos componentes podemos evitar la microgestión definiendo todo en un mismo archivo, además al tener todo en un mismo archivo el código será más fácilmente legible, quedándonos en un ejemplo de la siguiente forma:

<noscript><pre><code>&lt;!DOCTYPE html&gt; &lt;html t:type=&quot;layout&quot; titulo=&quot;Administración de productos&quot; xmlns:t=&quot;http://tapestry.apache.org/schema/tapestry_5_3.xsd&quot; xmlns:p=&quot;tapestry:parameter&quot;&gt; ... &lt;t:block id=&quot;edicionBlock&quot;&gt; &lt;t:remove&gt; En otros frameworks la lógica para obtener el título del bloque según se trate de un alta o una modificación, probablemente se hiciese metiendo lógica en la plantilla de presentación, dado que Tapestry permite llamar a métodos de la clase Java asociada al componente es mejor dejar esa lógica en el código Java de esta manera la plantilla será más sencilla y clara además de aprovecharnos del compilador. labels es un método definido en la página admin.producto que devuelve un mapa. &lt;/t:remove&gt; &lt;h1&gt;${labels.get('titulo')}&lt;/h1&gt; &lt;t:form t:id=&quot;form&quot; context=&quot;producto.id&quot; validate=&quot;producto&quot; clientValidation=&quot;none&quot; class=&quot;well&quot; role=&quot;form&quot;&gt; &lt;t:errors class=&quot;literal:alert alert-danger&quot; /&gt; &lt;t:delegate to=&quot;botonesEdicionBlock&quot;/&gt; &lt;div style=&quot;margin-top: 10px;&quot;&gt; &lt;div class=&quot;form-group&quot;&gt; &lt;t:label for=&quot;nombre&quot; /&gt; &lt;div class=&quot;controls&quot;&gt; &lt;input t:type=&quot;textfield&quot; t:id=&quot;nombre&quot; value=&quot;producto.nombre&quot; size=&quot;100&quot; label=&quot;Nombre&quot; /&gt; &lt;/div&gt; &lt;/div&gt; &lt;div class=&quot;form-group&quot;&gt; &lt;t:label for=&quot;descripcion&quot; /&gt; &lt;div class=&quot;controls&quot;&gt; &lt;input t:type=&quot;textarea&quot; t:id=&quot;descripcion&quot; value=&quot;producto.descripcion&quot; label=&quot;Descripción&quot; /&gt; &lt;/div&gt; &lt;/div&gt; &lt;div class=&quot;form-group&quot;&gt; &lt;t:label for=&quot;cantidad&quot; /&gt; &lt;div class=&quot;controls&quot;&gt; &lt;input t:type=&quot;textfield&quot; t:id=&quot;cantidad&quot; value=&quot;producto.cantidad&quot; size=&quot;4&quot; label=&quot;Cantidad&quot; class=&quot;numeric&quot;/&gt; &lt;/div&gt; &lt;/div&gt; &lt;div class=&quot;form-group&quot;&gt; &lt;t:label for=&quot;fecha&quot; /&gt; &lt;div class=&quot;controls&quot;&gt; &lt;div class=&quot;input-group&quot;&gt; &lt;input t:type=&quot;textfield&quot; t:id=&quot;fecha&quot; type=&quot;date&quot; value=&quot;producto.fecha&quot; label=&quot;Fecha&quot; /&gt; &lt;span class=&quot;input-group-addon&quot;&gt;&lt;span class=&quot;glyphicon glyphicon-calendar&quot;&gt;&lt;/span&gt;&lt;/span&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;t:delegate to=&quot;botonesEdicionBlock&quot;/&gt; &lt;/t:form&gt; &lt;/t:block&gt; &lt;t:block id=&quot;botonesEdicionBlock&quot;&gt; &lt;div class=&quot;btn-toolbar&quot;&gt; &lt;input t:type=&quot;submit&quot; class=&quot;btn btn-primary&quot; value=&quot;prop:labels.get('guardar')&quot; role=&quot;button&quot;/&gt; &lt;t:if test=&quot;producto.id&quot;&gt; &lt;a t:type=&quot;eventlink&quot; event=&quot;eliminar&quot; context=&quot;producto.id&quot; role=&quot;button&quot; class=&quot;btn btn-danger&quot; style=&quot;color: white;&quot;&gt;Eliminar&lt;/a&gt; &lt;/t:if&gt; &lt;input t:type=&quot;submit&quot; class=&quot;btn btn-danger&quot; value=&quot;Cancelar&quot; mode=&quot;cancel&quot; role=&quot;button&quot;/&gt; &lt;/div&gt; &lt;/t:block&gt; &lt;/html&gt;</code></pre></noscript>

En Grails por poner un ejemplo de un framework que no usa el concepto de componentes la forma habitual de hacerlo es usando un g:include y con ello teniendo microgestión. Pero retorciendo un poco (creo) en este caso el uso de Grails podemos emplear la etiqueta g:set para establecer el contenido de la botonera y emitir su contenido dos veces en el gsp.

<noscript><pre><code>... &lt;g:set var=&quot;botonesEdicionBlock&quot;&gt; &lt;div class=&quot;btn-toolbar&quot;&gt; &lt;input type=&quot;submit&quot; class=&quot;btn btn-primary&quot; value=&quot;${message(code: 'guardar')}&quot; role=&quot;button&quot;/&gt; &lt;g:if test=&quot;${producto.id}&quot;&gt; &lt;a action=&quot;eliminar&quot; params=&quot;${[id: producto.id]}&quot; role=&quot;button&quot; class=&quot;btn btn-danger&quot; style=&quot;color: white;&quot;&gt;Eliminar&lt;/a&gt; &lt;/t:if&gt; &lt;input type=&quot;submit&quot; class=&quot;btn btn-danger&quot; value=&quot;{message(code: 'guardar')}&quot; role=&quot;button&quot;/&gt; &lt;/div&gt; &lt;/g:set&gt; &lt;g:form ...&gt; ... ${botonesEdicionBlock} &lt;div style=&quot;margin-top: 10px;&quot;&gt; ... &lt;/div&gt; ${botonesEdicionBlock} &lt;/t:form&gt;</code></pre></noscript>

El código completo de este ejemplo del caso de Tapestry está en un repositorio de GitHub. Si estás interesado en conocer más en profundidad como funciona Tapestry y sus múltiples «killer features», bastantes mucho más importantes que lo explicado en este artículo, puedes descargarte el libro PlugIn Tapestry que he escrito, de forma gratuita, sin registros, y en varios formatos ¿que más puedes pedir?. Y si te interesa el tema puedes suscribirte al canal RSS de esta bitácora para no perderte nada del nuevo contenido que publique, no solo sobre Tapestry, sino también sobre Java, Linux, …

Referencia:
Libro PlugIn Tapestry
Más artículos sobre Apache Tapestry

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

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')) || {};

      if (this.chart) {
        this.chart.destroy();
        delete this.chart;
      }

      this.chart = new Chart(ctx)[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 (y IV): Configurando el Data Binding
  3. Tutorial jQuery Mobile + Knockout (I): Sentando las bases

» 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...

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