Ingenieria de Software / Software Engineering / Project Management / Business Process Management
Microsoft Dynamics CRM Service Update
Enero 31st, 2012 - [Enlace local]
Me da gusto saber que en el próximo Service Update de CRM se podrá accesar a Dynamics CRM con los Navegadores Safari, Firefox y Chrome
En el siguiente link lo nuevo que se presento en el Service Update de Noviembre
» Leer más, comentarios, etc...
Bitácora de Javier Gutiérrez Chamorro (Guti) » Programación
Avances en la informática personal (I)
Enero 31st, 2012 - [Enlace local]
La informática es la disciplina con avance más rápido que ha existido, tanto es así que todos aquellos que seáis de mi generación, habréis podido ser testigos en primera persona de sus orígenes a principios de los años 80, hasta nuestra situación actual en 2012. Bien es cierto que a simple vista la cosa no [...]
Artículos relacionados:
Avances con SMETAR
Informática y coches
Record personal en Operation Wolf
» Leer más, comentarios, etc...
xailer.info (esp)
CheckMenu
Enero 31st, 2012 - [Enlace local]
El control TCheckMenu representa un control tipo menú utilizando botones Checkbox y es prácticamente idéntico en funcionalidad al control TRadioMenu nativo del IDE con la diferencia que aquí podemos seleccionar varias opciones.

Las únicas diferencias a tener en cuenta son dos:
- Se añade una propiedad aChecked que sirve tanto para establecer qué elementos están seleccionados cuando se crea el control y para obtener la lista de elementos que se han seleccionado.
- El evento OnChange( oSender, nIndex, lChecked ) añade un nuevo parámetro lChecked que informa si el elemento que acaba de cambiar está seleccionado o no.
En el ZIP se incluye la DLL y la librería para Xailer 2.5
» Leer más, comentarios, etc...
Variable not found
Enlaces interesantes 69
Enero 31st, 2012 - [Enlace local]
Estos son los enlaces publicados en Variable not found en Facebook y Twitter del 16 al 29 de enero de 2012. Espero que os resulten interesantes. :-)
.Net
- Introducing Dragonfly – another .NET HTTP server
Louis DeJardin - Inside the Concurrent Collections: ConcurrentQueue
Simon Cooper - Using Async for File Access C# Team
- Aggressive Inlining in the CLR 4.5 JIT
Sasha Goldshtein - What is the defining characteristic of a local variable?
Eric Lippert - C#/.NET Little Pitfalls: Stopwatch Ticks are not TimeSpan Ticks
James Michael Hare - Inside the Concurrent Collections: ConcurrentStack
Simon Cooper
Asp.net
- Adding rich Selector support for MVC
Matt Hidinger - Solving Real-world Theming Challenges with MVC4 and Sass
Harvey Kandola - Javascript and CSS Minifying/Bundling with the Microsoft.Web.Optimization Nuget package
Maxime Rouiller - Validaciones propias en ASP.NET MVC
Eduard Tomás - The flowchart of the IE rendering modes
Chun Liu - POP Forums v9.2 posted to CodePlex, with new languages, post voting and the scoring game
Jeff Putz - ASP.NET Response.Redirect
Annie Luxton - Fix: the value ‘x’ is not valid for Foo in ASP.NET MVC
Code Inside Team - Web Deploy – config Transformation
Marc Rubiño - Cómo simular otros navegadores para probar desarrollos Web
José Manuel Alarcón - 10 Things ASP.NET Developers Should Know About Web.config Inheritance and Overrides
Jon Galloway - Cómo obtener rutas absolutas en ASP.NET
José Manuel Alarcón - Push con SingalR
Marc Rubiño - Tracking API usage with Google Analytics
Maarten Balliauw - MVC – get some help
Gregor Suttie
Azure / Cloud
- Release de SQL Azure Import/Export
Ibon Landa - Making Windows Azure Drive Letter Persistent
Shawn Cicoria - Getting Started with Windows Azure
Scott Guthrie
Conceptos
- Gof – Singleton
Sebis
Data access
- What do you want to see in Entity Framework?
Julie Lerman - HeidiSQL: Windows based interface for managing MySQL and Microsoft SQL databases
Ansgar Becker - RaptorDB - The Key Value Store V2
Mehdi Gholam - OraPoco: Trabajando contra Oracle
Javier Torrecilla - Why Entity Framework vNext will be EF5 and nothing else
Diego B. Vega
Html/Css/Javascript
- From jQuery to JavaScript: A Reference
Jeffrey Way - Some Thoughts On Functional JavaScript
Derick Bailey - Find the jQuery Bug #2: Point of No Return
Elijah Manor - JavaScript for C# developers: coercion
Julian M. Bucknall - Modernizr–Ejemplo práctico 2 : Utilizando Border Radius, elemento date y atributo required
Gonzalo Pérez - Server-Sent Events
Remy Sharp - Using HTML5 Web Storage in ASP.NET
Bipin Joshi - Creando objetos y aplicaciones configurables en Javascript
Carlos Benítez - 10 Excellent Free Rich-Text Editors
jQuery4u - SOLID JavaScript- The Dependency Inversion Principle
Derek Greer - Easing Functions in CSS3
Kirupa Chinnathambi - How Wikipedia uses HTML5 to save bandwidth
Jef Claes - The Top 10 Javascript MVC Frameworks Reviewed
Gordon L. Hempton - Using CSS3 Transitions, Transforms and Animation
Rich Bradshaw
Visual Studio/Complementos
- Importing / Exporting Templates and Patterns in ReSharper 6.1
Hadi Hariri - C# + ReSharper = Awesome: Tip #8 – Extract Class From Parameters
Alvin Ashcraft - C# + ReSharper = Awesome: Tip #7–Move String to Resource
Alvin Ashcraft's - StyleCop v4.7.6.0 disponible
Jorge Serrano
Otros
- Breaking CAPTCHA with automated humans
Troy Hunt - Let's make TCP faster
Yuchung Cheng - El "Cargo Cult" de las pequeñas empresas
José Manuel Alarcón - El efecto Mateo y su influencia
José Manuel Alarcón
Publicado en Variable not found
» Leer más, comentarios, etc...
Koalite's blog
Tutorial jQuery Mobile + Knockout (I): Sentando las bases
Enero 30th, 2012 - [Enlace local]
Tras la buena acogida que tuvo el tutorial de nodejs y express, me he decidido a preparar otro tutorial que sirva de introducción para un par de librerías con las que he estado jugando últimamente.
Igual que en el anterior tutorial, quiero dejar claro que esto es sólo una pequeña introducción a dos librerías que me parecen útiles. No se trata de un catálogo de buenas prácticas y habrá muchos puntos que puedan (y deban) ser mejorados.
En este caso vamos a crear una pequeña aplicación web para dispositivos móviles usando jQuery Mobile y Knockout. Como creo que es importante conocer las bases para poder entender lo que estamos haciendo, antes de empezar a implementar nada vamos a presentar a nuestros nuevos amigos.
jQuery Mobile
jQuery Mobile es un framework que nos permite crear aplicaciones para dispositivos móviles. Por tanto, está optimizado para su uso con pantallas de pequeño tamaño e interfaces táctiles encargándose de ajustar el interfaz de usuario de los controles estándar html para que sean más atractivos y manejables en un entorno móvil.
Se ejecuta por completo en el lado cliente, en este caso, el browser del dispositivo. Para emplearlo, debemos añadir lo siguiente a nuestra página web:
Podemos usar la versión descargada o enlazar directamente a una versión online, tal y como explican en la su página de descarga.
jQuery Mobile se basa en la asignación de roles a los distintos elementos html para atribuirles determinadas funciones dentro de la aplicación. A partir de estos roles, se ajusta el aspecto del elemento. Para asignar los roles a los elementos se usa el atributo data-role:
Una aplicación desarrollada con jQuery Mobile se estructura alrededor del concepto de página. Una página no es más que un div que tiene asignado el rol page, como en el ejemplo anterior. En un único documento html podremos tener varias páginas simplemente añadiendo varios divs con el atributo data-role="page", y jQueryMobile se encargará de mostrar en cada momento únicamente el div correspondiente a la página que esté activa.
Además del rol usado para marcar las páginas, existen otros roles muy útiles como header, footer, etc. que permiten representar otros elementos dentro de la página, o listview, button, etc. que se usan para crear controles con los que el usuario puede interactuar.
Si quieres conocer en profundidad las opciones que ofrece jQuery Mobile, te recomiendo que consultes su documentación.
Knockout
Knockout es una librería diseñada para aplicar cómodamente el patrón MVVM en aplicaciones javascript. Al igual que jQuery Mobile se ejecuta por completo en el browser por lo que deberemos incluirla en el código de nuestras páginas:
Para poder trabajar con Knockout es fundamental conocer el patrón Model-View-ViewModel. Resumiéndolo (mucho) podríamos decir que se basa en organizar la aplicación en torno a 3 conceptos:
- Model. Es el modelo completo de la aplicación, donde reside la lógica de negocio y todas esas cosas importantes. Knockout no se mete en esta parte y puedes implementarla como quieras. Lo más habitual es que resida en un servidor y la aplicación se comunique con él a través de AJAX.
- View. La vista, dedicada únicamente a mostrar información. No contiene ningún tipo de lógica, ni siquiera lógica relacionada con el interfaz de usuario, porque para eso está la última parte del trío.
- ViewModel. El modelo de presentación, que se encarga de adaptar el modelo de la aplicación a las necesidades de la vista y contiene además toda la lógica relacionada con el interfaz de usuario, como por ejemplo cuándo se debe habilitar un control o qué hay que hacer cuando se pulsa un botón.
Knockout nos ofrece una manera muy sencilla de enlazar View y ViewModel a través de data binding. Este data binding se hace de forma declarativa usando atributos data-bind:
Las posibilidades que ofrece Knockout para realizar el data binding son de lo más variado y podéis consultarlas en la documentación de Knockout.
Para que funcione esto del data binding es fundamental poder detectar los cambios en los valores de los controles para propagarlos al ViewModel, pero también es necesario poder detectar los cambios en el ViewModel para propagarlos a la vista. En este aspecto Knockout cuenta con su propia implementación del patrón observer, a través de funciones como ko.observable.
¿Cuándo empezamos?
En el siguiente post veremos cómo es la aplicación de ejemplo que vamos a hacer en este tutorial y prepararemos la estructura de páginas de jQuery Mobile que vamos a tener.
Posts relacionados:
- Tutorial node.js + express + jquery (III): Usando jQuery
- Tutorial node.js + express + jquery (IV): Conclusiones y próximos pasos
- Tutorial node.js + express + jquery (I): Creando la aplicación
» Leer más, comentarios, etc...
Escuela De Codigo
CoffeeScript, El primer paso
Enero 30th, 2012 - [Enlace local]
En esta era de la web2.0, en la que toda actividad y aplicación es llevada a la internet, la nube, un lenguaje antes subestimado, se convirtió para sorpresa de algunos, alegría de otros y desdicha de pocos en un fuerte aliado para los desarrolladores, no hablo de HTML ni CSS sino del tercer componente del triunvirato de la web actual: Javascript.
Javascript un lenguaje interpretado, del lado de cliente, que en sus inicios se usaba en las paginas web para crear efectos de copos de nieve y tonterías de ese tipo. Ahora es el lenguaje sin el cual Gmail no fuera posible, facebook solo seria una galería de fotos aburrida y un twitt seguiria siendo el sonido que algunos creen que hacen los pájaros. Javascript se convirtió en un lenguaje muy importante. Pero, sigue manteniendo muchas cosas que aun no se ajustan al nuevo capricho de los desarrolladores actuales:Syntactic Sugar.
Syntactic Sugar se ha hecho muy popular sobre todo (según como lo veo) gracias a Ruby, y es que eso de escribir código sin puntos y coma, corchetes, llaves y paréntesis innecesarios es una buena idea y hay muchos que piensan que esas ideas es bueno llevarlas a otros lados.
y así fue como nació CoffeeScript,un lenguaje de programación que se escribe bonito y genera Javascript de toda la vida.
Instalación
Para instalar Coffeescript, necesitamos primeramente instalar Node.js y npm, una vez ya lo hallas hecho solo ejecuta en tu terminal favorita
npm install -g coffee-script
(El parametro -g es para indicar que es una instalación global que estara disponible para todos los usuarios de tu sistema operativo)
Hola Mundo
Hagamos una prueba para identificar que todo esta instalado correctamente, y de paso explicar como compilar javascript, abre un editor de texto de tu eleccion y escribe.
square = (x) -> x * x
Guarda tu archivo como hola.coffee (Si, .coffee es la extensión de los script CoffeeScript)
y luego ejecuta
coffee -c 'hola.coffee'
Inmediatamente veras un archivo javascript que se genero con el siguiente código
square = function(x) { return x * x; };
y ya tienes un archivo .js de toda la vida que puedes usar sin problema en tus aplicaciones web.
Ahora bien el comando -c es el que nos sirve para compilar nuestros archivos .coffee y convertirlos en Javascript, claro que se vuelve tedioso estar corriendo ese comando por cada vez que escribo y/o modifico en mi archivo, asi que para evitarnos la fatiga de esa tarea, ejecuta
coffee --watch --compile hola.coffee
Y ahora cada vez que modifiques tu programa Coffeescript, este auto-mágicamente generara el compilado.
Un ejemplo practico
Tengo un archivo javascript de un viejo bookmarklet que hice hace un tiempo, como en ese momento no conocia CoffeeScript pues lo hice a Javascript duro y maduro. ¿Porque no lo migramos a algo mas elegante y comentamos las partes mas interesantes? Nada como un ejemplo practico para aprender mejor las cosas, o alguien aprendio a andar en bicicleta por internet??
(Que hace el bookmarklet?…elimina el teclado virtual de la siguiente pagina y permite al usuario utilizar nuevamente el teclado convencional, un banco de mi país penso que era buena idea, a mi me pareció incomodo, así que lo quite
)
El código original lo puedes encontrar aquí
var ifr = false; var formName = 'loginForm';
#Comentarios ifr = off formName = 'loginForm'
Variables
El script empieza definiendo unas cuantas variables,en CoffeeScript para definir variables no es necesario usar la palabra reservada var y en terminos generales los punto y coma no son requeridos.
Comentarios
Los comentarios no son compilados a javascript y se escriben anteponiendo #
Booleanos
Ademas cuando tenemos alguna variable de tipo booleana, podemos utilizar alguno de los alias que el lenguaje nos ofrece para este caso podemos sustituir el false con off o no, para true se utilizan yes o on.
var $ = function(idname) { var doc = ifr ? window.frames.working.document : document; return doc.getElementById(idname) || doc.getElementsByName(idname)[0] || ''; };
$ = (idname) -> doc = if ifr then window.frames.working.document else document doc.getElementById(idname) or doc.getElementsByName(idname)[0] or ''
Funciones
Las funciones se definen siguiendo la estructura nombre = (parametros entre parentesis) -> [cuerpo de la funcion] sino existen parametros se omiten los parentesis, la palabra reservada return se omite, al igual que en Ruby, la ultima sentencia que se ejecuta es el valor que la funcion devuelve. Los parametros pueden tener valores por defecto parametro='valor'.
Sentencias condicionales
Para definir un if corto (condicion?true:false) se utiliza un lenguaje mas natural if condicion then true else false. Es de notar que las llaves y paréntesis tampoco son necesarios.
Operadores Lógicos
Los operadores logicos tambien tienen alias, para el caso de || se puede sustituir con or
for (var i=0; i<usuario.length; i++){ var caracter = usuario[i]; k = k + $(caracter).value; } var letras = new Array(); for (var i=32; i<170; i++){ letras[i] = String.fromCharCode(i); }
for caracter in usuario k = k + $(caracter).value letras = (String.fromCharCode(i) for i in [32..169])
Sentencias repetitivas
El clasico de toda la vida for se abrevia, ya no necesitamos conocer la longitud del arreglo a iterar, ni definir alguna variable auxiliar,CoffeeScript se encarga de todo eso.
Arreglos
Para crear un arreglo basta utilizar nombre = [] aunque para el ejemplo que tenemos creamos un arreglo a partir de una sentencia for y un rango.
Rangos
En el código del bookmarklet necesitaba obtener todas las letras del alfabeto, para lograr eso lo hice con la funcion fromCharCode, que me pide un numero para devolverme el carácter que le corresponde, la opcion en Javascript es crear un loop (for) que inicie en 32 y termine en 169, en CoffeeScript podemos hacer eso haciendo uso de los rangos [inicio..final] . Los rangos son utilizados en las sentencias repetitivas y en la definición de arreglos. Es de notar que si existen dos puntos consecutivos entre los valores de inicio y final significa que el valor inicial es incluido dentro del rango, si vemos tres puntos consecutivos (…) significa que el extremo final del rango es excluido.
El resultado final
Y finalmente!! mi Javascript bookmarklet migrado a CoffeeScript
#declaracion de variables ifr = no; formName = 'loginForm'; #funciones iisIframe = -> window.location.href=='https://www.pcbac.com/PotalaPersonal/home.do'; window.iisIframe = iisIframe #Ojo con los espacios es importante!!! $ = (idname) -> doc = if ifr then window.frames.working.document else document #if else doc.getElementById(idname) or doc.getElementsByName(idname)[0] or '' window.$ = $; createHTMLElement = (id,type) -> _parent = $(id).parentNode _parent.innerHTML = '' _input = document.createElement 'input' _input.setAttribute 'type', type _input.setAttribute 'id', id _input.setAttribute 'name', id _input.setAttribute 'size', '32' _input.setAttribute 'autocomplete', 'off' #los parentesis no son necesarios _input.setAttribute 'class', 'notfocussed' _input.setAttribute 'onblur', if ifr then 'parent.copyText(this);' else 'copyText(this);' _parent.appendChild _input return #coloco esto para que mi funcion no retorne nada window.createHTMLElement = createHTMLElement copyText = (caja) -> usuario = caja.value k = '' for caracter in usuario k = k + $(caracter).value if caja.id=='usernameA' or caja.id=='claveActual' then $('Field1ValueHidden').value = k if caja.id=='passwordA' or caja.id=='nuevaClave' then $('Field2ValueHidden').value = k if caja.id=='confirmacionNuevaClave' then $('Field3ValueHidden').value = k return window.copyText = copyText; ifr=iisIframe() if ifr then formName='cambioClaveForm' firstRowSplit = $(formName).charFirstRowhidden.value secondRowSplit = $(formName).charSecondRowhidden.value thirdRowSplit = $(formName).charThirdRowhidden.value firstRowSplitMi = $(formName).charFirstRowhiddenHMi.value secondRowSplitMi = $(formName).charSecondRowhiddenHMi.value thirdRowSplitMi = $(formName).charThirdRowhiddenHMi.value firstRowSplitMa = $(formName).charFirstRowhiddenHMa.value secondRowSplitMa = $(formName).charSecondRowhiddenHMa.value thirdRowSplitMa = $(formName).charThirdRowhiddenHMa.value firstRow = firstRowSplit.split '|' firstRowMi = firstRowSplitMi.split '|' firstRowMa = firstRowSplitMa.split '|' secondRow = secondRowSplit.split '|' secondRowMi = secondRowSplitMi.split '|' secondRowMa = secondRowSplitMa.split '|' thirdRow = thirdRowSplit.split '|' thirdRowMi = thirdRowSplitMi.split '|' thirdRowMa = thirdRowSplitMa.split '|' todo = [] for i in [firstRow.length - 1..0] by -1 #empezar en -1 todo[firstRow[i].toLowerCase()] = firstRowMi[i];todo[firstRow[i]] = firstRowMa[i]; for i in [secondRow.length - 1..0] by -1 todo[secondRow[i].toLowerCase()] = secondRowMi[i];todo[secondRow[i]] = secondRowMa[i]; for i in [thirdRow.length - 1..0] by -1 todo[thirdRow[i].toLowerCase()] = thirdRowMi[i];todo[thirdRow[i]] = thirdRowMa[i]; for m in [0..2] todo[$(formName).number1[m].value] = $(formName).number1[m].alt; todo[$(formName).number2[m].value] = $(formName).number2[m].alt; todo[$(formName).number3[m].value] = $(formName).number3[m].alt; todo[$(formName).number4.value] = $(formName).number4.alt; for m in [0..9] todo[$(formName).button4[m].value] = $(formName).button4[m].alt; for m in [0..10] todo[$(formName).button5[m].value] = $(formName).button5[m].alt; todo[$(formName).button10[m].value] = $(formName).button10[m].alt; letras = (String.fromCharCode(i) for i in [32..169]) for letra in letras input = document.createElement 'input' input.setAttribute 'type', 'hidden' input.setAttribute 'id', letra input.setAttribute 'value', todo[letra] $(formName).appendChild input if !ifr createHTMLElement('usernameA','text') createHTMLElement('passwordA','password') else createHTMLElement('claveActual','password') createHTMLElement('nuevaClave','password') createHTMLElement('confirmacionNuevaClave','password') $(if ifr then formName else 'forma1').getElementsByTagName("table")[0].getElementsByTagName("tr") [if ifr then 14 else 8].style.display = 'none'
CoffeeScript es mucho mas
Lo que utilice de CoffeeScript para migrar mi bookmarklet no es ni la décima parte de todo lo que este lenguaje nos ofrece, hay mas temas que tratar pero, no caben en un articulo introductorio, espero haber logrado inculcar un poco de curiosidad para que sigas adelante en el estudio de CoffeeScript. Si ese es tu caso, dejo a tu disposición documentación para dar el siguiente paso
Un curso de CoffeeScript en EscueladeCodigo, completamente gratis, ¿te parece buena idea?
» Leer más, comentarios, etc...
Picando Código
¿Y si juntamos a la comunidad de usuarios ArchLinux del Uruguay?
Enero 26th, 2012 - [Enlace local]
Lo que dice el título, ¿y si juntamos un grupo de usuarios ArchLinux en un mismo espacio física esporádicamente y nos unimos a trabajar con algun(os) objetivo(s) en común?
En un principio pensé que la mejor forma de convocar a los usuarios a unirse en grupo era crear una lista de correo, un blog, o algo así. Pero eso son solo herramientas, preferí empezar sin mucha ambición con este post (gracias al principio de KISS). Los invito a dejar un comentario si quieren sumarse a la iniciativa. Hay que ver si hay más interesados, y después entre los que seamos vemos qué se arma ![]()
Se me ocurren varias razones de por qué esto es una buena idea. Una buena parte de lo positivo de ir a una reunión de personas técnicas (hackatón, conferencias y demás) es conocer a otras personas con los mismo intereses. Ni que hablar que las charlas suelen ser bastante interesantes. Si nos entretenemos leyéndonos por foros, redes sociales y blogs, mejor la vamos a pasar conversando mientras tomamos alguna cerveza y comemos alguna pizza.
A continuación listo algunos objetivos/ideas/razones más que me vienen en la cabeza sin caer en nada muy ambicioso.
- Aprender a empaquetar aplicaciones y buscar alguna aplicación que podríamos enviar a AUR. Es un conocimiento que viene bien, y seguramente todos han toqueteado algún PKGBUILD en algún momento. De repente sale algo interesante.
- Ayudar con la traducción de la wiki, si alguien tiene algo de tiempo libre para aportar al proyecto, esta es una buena manera. (más ideas acá)
- Dar a conocer cosas interesantes que hayamos logrado, scripts, personalizaciones, etc. Ayudar con algún problema particular que algun usuario pueda tener con el sistema.
- “Evangelizar” a usuarios de otras distros, ayudarles a darse cuenta que ArchLinux es la mejor distribución de GNU/Linux

- Comprar camisetas de ArchLinux. Al ser muchos, podemos conseguir un buen precio para mandar a hacer camisetas de Arch.
- DRY: No repetirnos. No hay que reinventar la rueda, crear más wikis y demás información repetida. Creo que si en algún momento armamos alguna representación virtual del grupo en internet, habría que limitarse al tema de las reuniones y demás posibles organizaciones que podamos llevar a cabo. Nada de reescribir o copiar y pegar todo el conocimiento que tan bien documentado está en la wiki de Arch.
Si hay convocatoria, coordinamos una fecha y me comprometo a conseguir un lugar para reunirnos por primera vez y ver qué sale. No hay mucha idea o compromiso, simplemente juntarse a ver qué sale.
Para finalizar el post, los dejo con un texto de la wiki:
En Biología, mutualismo es una interacción entre dos organismos en que ambos organismos obtienen beneficio. Este principio puede también ser aplicado a miembros proactivos y motivados de la comunidad de ARCH que quieren estar involucrados y contribuir a su distribución favorita GNU/Linux. Esta participación beneficia no solo a los miembros de la comunidad y sus compañeros Arches, pero también a todos los fans potenciales de Software libre y de codigo abierto
» Leer más, comentarios, etc...
Koalite's blog
Diseño Web Sensible y Grids CSS
Enero 26th, 2012 - [Enlace local]
Ya he dicho en alguna ocasión que me interesa bastante el tema de la experiencia de usuario, aunque luego la parte de diseño gráfico que suele llevar asociada no sea mi fuerte y acabe basándome más en la teoría que en el talento.
En el mundo del diseño web últimamente está muy de moda el Responsive Web Design, que podríamos traducir como diseño sensible o más bien como “diseño que responde bien”. Se trata de intentar diseñar las páginas web para que se adapten correctamente a distintas resoluciones y formatos de pantalla, y es algo que hoy en día cobra una importancia especial con la gran variedad de dispositivos que se usan para navegar por internet.
Para conseguir esto, siempre existe la opción de desarrollar distintas versiones del sitio web adaptadas a cada formato que queramos soportar, pero eso implica un trabajo adicional que no siempre merece la pena y además supone un problema cuando aparecen nuevos formatos que no teníamos previsto.
El responsive design aprovecha las características de CSS3 y media queries para aplicar distintos formatos en función de las características del dispositivo que está accediendo a la página.
Una forma muy extendida de implementar esto es estructurar la página a partir de un grid y maquetar la información ajustándola a ese grid:
Una vez que tenemos la información estructurada, aplicando las técnicas CSS adecuadas es relativamente fácil conseguir adaptarlo al tamaño de pantalla del dispositivo:
En este ejemplo se ve como al reducir el ancho de la pantalla, el contenido se reformatea reduciendo el tamaño de las columnas del grid, llegando incluso a apilar las columnas para pasar a un formato completamente vertical apto para teléfonos móviles. Se puede comprobar fácilmente accediendo a la página y redimensionando la ventana del navegador.
Para ayudarnos a implementar esto, existen muchos frameworks CSS para responsive design que nos facilitan bastante la vida. Algunos están basados en grids fluidos, en los cuales la anchura de las columnas se ajusta automáticamente al tamaño de la pantalla, y otros en grids fijos, que mantienen constante la anchura de las columnas pero varían el número de columnas en función del tamaño de la pantalla. Entre los frameworks más conocidos están:
Personalmente me parece una idea bastante buena, pero hay puntos que no acaban de gustarme. Me parece que se sacrifica parte del contenido semántico del documento en favor de la maquetación, algo que ya ocurría hace unos cuantos años con el abuso de las tablas. Ahora parece que, mientras se usen divs en lugar de tablas, todo vale.
Por otra parte, casi todos estos sistemas utilizan clases CSS que no tiene valor semántico, sólo tienen valor para formatear la información. En un mundo ideal, las clases CSS que aparecen en el documento HTML no deberían definir el cómo (formato) sino el qué (intención), deberían ser algo declarativo.
Por ejemplo, si en una página queremos marcar el importe total de una compra, deberíamos marcarlo como y luego asignar en la hoja de estilo a la clase total-amount una fuente negrita, más grande o lo que queramos. Con este tipo de frameworks se fomenta más usar algo de la forma , penalizando la estructura semántica del documento. Es lo mismo que ocurre al utilizar otros frameworks de diseño web como jquery-ui o jquery-mobile.
Una excepción a esto es Semantic Grid System, que intenta no manchar el documento html con sus clases CSS. Para ello, aplica sus estilos mediante mixins con LESS, SCSS o Stylus.
En cualquier caso, las ventajas que aportan el uso de este tipo de frameworks son considerables, por lo que a veces resulta mejor ser más pragmático y aprovecharlos. A fin de cuentas, lo que realmente importa es aportar valor al usuario/negocio, y para ello estos frameworks pueden ser de mucha ayuda.
No hay posts relacionados.
» Leer más, comentarios, etc...
Arragonán
Don’t Censor Me!
Enero 26th, 2012 - [Enlace local]

Via Pablo Jimeno
» Leer más, comentarios, etc...
xailer.info (esp)
Error.log
Enero 25th, 2012 - [Enlace local]
Cuando lanzamos una aplicación desde el IDE y aparece un error en tiempo de ejecución sucede que, por motivos que van desde el cansancio o la falta de concentración hasta directamente porque se ha producido un error no recuperable (recursión, GPF, etc.), se cierra la aplicación sin darnos tiempo a anotar en qué lugar del código estaba el error.

Para evitar tener que reproducir otra vez cada uno de los pasos para llegar al error usaremos este plugin que añade una nueva opción al menú Ver del IDE que permite mostrar la información de error completa o resumida así como borrar el archivo del disco cuando ya no es necesario.

Desde la vista error.log es posible copiar la información del error al portapapeles en el mismo formato en que se está mostrando, completa o resumida, para, por ejemplo, enviarla por correo:

El archivo para descargar: ErrorLog
El plugin sólo funciona con Xailer 2.5 y Xailer 2.5.1
» Leer más, comentarios, etc...
Picando Código
Disponible Oil Rush 1.00 :)
Enero 25th, 2012 - [Enlace local]
El excelente juego de estrategia naval en tiempo real Oil Rush (clic en el enlace para leer mi reseña) está disponible en su versión 1.00. Aquellos que lo preordenamos lo podemos descargar ya desde Unigine Online Store.
Se está trabajando en versiones para Steam, Desura y Ubuntu Software. Éstas estarán disponibles en uno o dos días.
La versión 1.00 nos trae el tan esperado modo de campaña para un jugador. Pre ordené el juego en marzo del año pasado, y desde entonces he ido viendo cómo evoluciona poco a poco con cada nueva versión. Ahora me toca el turno de hacer la campaña y ver qué han estado preparando los desarrolladores para nosotros…
Es un juego bastante importante en lo que respecta al mundillo de videojuegos en plataformas GNU/Linux. Fue construido sobre el motor Unigine que da la oportunidad de realizar unos gráficos 3D impresionantes, corriendo de forma nativa en nuestro querido sistema.
Con suerte el juego tenga éxito, así lo espero. Esto abriría más el mercado de videojuegos en GNU/Linux, dándole la publicidad necesaria a su motor para que otras compañías lo tengan en cuenta a la hora de desarrollar sus juegos.
Ya estoy descargando esta nueva versión, y más tarde tendré la oportunidad de probarlo. Ahí les contaré qué me pareció. Mientras les dejo algunas fotos de versiones anteriores para que se hagan una idea de los excelentes gráficos del juego:
Oil Rush 0.66
Oil Rush 0.82
» Leer más, comentarios, etc...
Variable not found
Libro: Dependency injection in .NET
Enero 25th, 2012 - [Enlace local]
La inyección de dependencias es uno de esos conceptos rodeados de misterio que parecen reservados a gurús, arquitectos, y otros profesionales de gama alta, y aplicables exclusivamente en proyectos mastodóndicos.
Y nada más lejos de la realidad: DI se basa en principios relativamente simples, e incluso diría intuitivos, para lograr evitar el acoplamiento entre componentes, es aplicable en todo tipo y tamaño de aplicaciones, y por tanto todas ellas pueden beneficiarse de las ventajas que aporta, como la simplicidad, mantenibilidad, extensibilidad, o facilidad para la realización de pruebas unitarias.
Pero, sinceramente, jamás pensé que el tema que pudiera dar tanto de sí como para escribir un libro. Por eso me ha sorprendido la lectura, por cortesía de Auges, del libro “Dependency Injection in .NET”, escrito por por Mark Seemann y publicado por la editorial Manning, donde he podido comprobar que mis conocimientos sobre inyección de dependencias, aunque válidos, eran bastante superficiales.
El libro se estructura en cuatro grandes bloques a través de los cuales se realiza un completo recorrido guiado por los conceptos, utilización y herramientas para aplicar DI:
- “Putting Dependency Injection on the map” contiene tres capítulos introductorios, útiles para poner en contexto el patrón y las ventajas que conlleva su uso y describir los conceptos fundamentales utilizados: dependencias, tipos, tiempo de vida, intercepción, contenedores, y muchos otros.
- “DI catalog” es una completa relación de patrones de uso de la inyección de dependencias, antipatrones o malos usos que podemos hacer de la misma, y refactorizaciones que podemos utilizar para solucionar escenarios frecuentes.
- “DIY DI” describe técnicas asociadas a la ID, como la composición de objetos, la gestión del ciclo de vida, y la intercepción de llamadas.
- “DI containers” es un completo bloque donde se describe el uso de los principales contenedores disponibles para la plataforma .NET: Castle Windsor, StructureMap, Spring.NET, Autofac, Unity y MEF.
Como puntos negativos, que está disponible exclusivamente en inglés, y que algunos capítulos se hacen algo densos y requieren varias pasadas para poder asimilar las ideas transmitidas.
Enlace: http://www.manning.com/seemann/
Publicado en: Variable not found.
» Leer más, comentarios, etc...
Arragonán
Taller Spring I/O 2012: Modulariza tus aplicaciones Grails
Enero 25th, 2012 - [Enlace local]
Este año volveré a estar por el Spring I/O (16 y 17 de Febrero 2012 en Madrid), en esta ocasión dirigiendo el taller Modulariza tus aplicaciones Grails :
Gracias a los plugins de grails liberados a la comunidad, podemos aprovechar el esfuerzo hecho por otros desarrolladores y reutilizar el trabajo que han hecho. El sistema de plugins de grails da múltiples puntos de extensión para la plataforma: permite añadir comandos nuevos a la CLI, servicios, clases de dominio, extender dinámicamente algunos comportamientos… En el taller sacaremos partido del sistema de plugins de grails para reutilizar trabajo entre distintas de nuestras aplicaciones, veremos algunos ejemplos y desarrollaremos un plugin a modo de ejemplo.

Básicamente, mostraremos de forma práctica como reutilizar código en nuestros proyectos del día a día, más allá de liberar plugins que sólo tengan sentido ser liberados para el resto de la comunidad.
Este año volverán a ser 2 días de charlas y talleres, un eventazo a un precio de risa. Como podéis ver en la agenda, hay buena cantidad y calidad de ponentes, incluida alguna rockstar internacional entre ellos.
Cualquiera que trabaje o le interesen tecnologías alrededor de los ecosistemas Spring, Grails o Groovy debería asistir a este evento; o también a quienes les interesan cosas relacionadas con Mongodb, Scala, ElasticSearch, RabbitMQ o incluso temas de cloud computing.
Pero seguro que lo mejor está por los pasillos, durante los cafés y las comidas… o, por descontado, en la fiestaca del jueves
.
Nos vemos en el Spring I/O!
» Leer más, comentarios, etc...
Variable not found
SignalR (II): Conexiones persistentes
Enero 24th, 2012 - [Enlace local]
Hace poco estuvimos viendo por aquí conceptos básicos sobre SignalR, el componente que nos permite crear espectaculares aplicaciones en las que múltiples usuarios pueden estar colaborando de forma simultánea, asíncrona, y en tiempo real.
Entre otras cosas, comentábamos que SignalR crea una capa de abstracciones sobre una conexión virtual permanente entre cliente y servidor, sobre la que podemos trabajar de diferentes formas:
- mediante conexiones persistentes, la opción de menor nivel, que proporciona mecanismos de notificación de conexión y desconexión de clientes, así como para recibir y enviar mensajes asíncronos a clientes conectados, tanto de forma individual como colectiva.
- mediante el uso de “hubs”, que ofrece una interfaz de desarrollo mucho más sencilla, con una integración entre cliente y servidor que parece pura magia, y que seguro será la opción más utilizada por su potencia y facilidad de uso.
Bueno, pues vamos al tema: emplearemos esta vía para implementar una funcionalidad bastante simple, pero nada trivial utilizando las herramientas habituales de ASP.NET: mostrar en una página, en tiempo real, información sobre los usuarios que están llegando a ella, los que la abandonan y el número de usuarios que hay conectados justo en ese momento, en tiempo real. Para ello haremos lo siguiente:
- En el lado servidor, implementaremos un servicio (endpoint) SignalR, que es el que procesará las conexiones y desconexiones de clientes, y enviará información actualizada por las conexiones abiertas.
- Registraremos este endpoint durante la inicialización de la aplicación, asociándole una URL de acceso a las funcionalidades del servicio.
- En el lado cliente implementaremos la conexión con el servicio, capturaremos la información que nos vaya enviando y la mostraremos en la página en forma de log.
Ya en el post anterior de la serie vimos cómo descargar e instalar SignalR en un proyecto, así que vamos a suponer que ese paso ya lo hemos realizado previamente.
1. Implementación del endpoint
El endpoint, o servicio SignalR, que vamos a implementar utilizando el enfoque de conexión persistente es simplemente una clase que hereda deSignalR.PersistentConnection, en la que podemos sobrescribir los métodos que necesitemos para implementar nuestras funcionalidades. En ella encontramos métodos como OnConnected(), OnDisconnect(), OnReceived(), y bastantes más, que nos permiten tomar el control cuando se producen determinados eventos de interés en la conexión: public class VisitorsService : PersistentConnection
{
protected override void OnConnected(HttpContextBase context, string clientId) { ... }
protected override void OnDisconnect(string clientId) { ... }
protected override void OnReceived(string clientId, string data) { ... }
// [...]
}
Observad que el interfaz es bastante similar a la que encontramos al trabajar directamente con sockets: podemos introducir lógica cuando un nuevo cliente se conecte sobrescribiendo el método OnConnected(), cuando se desconecte, haciendo lo propio con OnDisconnect(), o cuando el cliente envíe algún tipo de mensaje al servidor, que ejecutará la funcionalidad implementada en OnReceived().De la misma forma, la clase base
PersistentConnection ofrece mecanismos para enviar mensajes directos a un cliente, a grupos de ellos, o a todos los clientes conectados.Volviendo al sistema que estamos desarrollando, básicamente para alcanzar nuestros objetivos necesitamos:
- tomar el control en el momento en que se produce una nueva conexión (método
OnConnected), momento en que enviaremos al resto de clientes un mensaje con información sobre el cliente conectado y el total de conexiones activas. - tomar el control en el momento en que se produce la desconexión de un cliente (método
OnDisconnect()), para notificar al resto y actualizarles el número de clientes conectados.
1.1. Notificando a los clientes las nuevas conexiones
Cuando se realiza una nueva conexión al servicio, es decir, la llegada de un nuevo cliente, SignalR invocará al métodoOnConnected() del endpoint suministrándole el contexto de la petición HTTP actual, y un “ClientId”. El primero nos puede ser muy interesante para acceder a información de la petición (como el navegador, IP, cookies, información de autenticación, etc.), y el segundo es un identificador único generado por SignalR para realizar el seguimiento de la conexión.Implementamos nuestro método y lo comentamos justo a continuación:
protected override void OnConnected(HttpContextBase context, string clientId)
{
var clientDescription = getClientDescription(context);
_clients.TryAdd(clientId, clientDescription);
string text = clientDescription + " arrived.";
var msg = new NotificationMessage(text, _clients.Count);
Connection.Broadcast(msg);
}
Lo primero que hacemos en la implementación del método es obtener una descripción textual del cliente (que puede ser el nombre del usuario autenticado, o su IP), utilizando el método getClientDescription(), que veremos más adelante. Esta descripción, asociada al ClientId, es almacenada en el diccionario estático _clients, lo que nos permitirá conocer en todo momento los clientes conectados.Justo después componemos el mensaje y realizamos el envío a todos los usuarios conectados invocando el método
Broadcast() de la propiedad de instancia Connection, que nos da acceso al canal virtual abierto entre clientes y servidor. El parámetro que recibe este método es de tipo object, y viajará serializado en formato JSON hasta cada uno de los clientes conectados; en este caso, hemos creado una clase llamada NotificationMessage que contiene toda la información que necesitamos suministrarles:public class NotificationMessage
{
public NotificationMessage(string message, int onlineUsers)
{
OnlineUsers = onlineUsers;
Message = message;
}
public string Date
{
get { return System.DateTime.Now.ToLongTimeString(); }
}
public string Message { get; set; }
public int OnlineUsers { get; set; }
}
Es conveniente tener en cuenta, sin embargo, que es posible enviar cualquier tipo de objeto: tipos propios (como en el ejemplo anterior), objetos anónimos, primitivos, o lo que se nos ocurra. Simplemente será serializado como JSON y llegará al cliente de forma directa (más adelante veremos cómo).Los miembros auxiliares utilizados en el código anterior son los siguientes:
private static ConcurrentDictionary<string, string> _clients =
new ConcurrentDictionary<string, string>();
private static string getClientDescription(HttpContextBase context)
{
var browser = context.Request.Browser.Browser + " " +
context.Request.Browser.Version;
var name = context.Request.IsAuthenticated ?
"User " + context.User.Identity.Name :
"IP " + context.Request.UserHostAddress;
return name + " (" + browser + ")";
}
Observad que el diccionario donde almacenamos la información sobre las conexiones ha sido definido como ConcurrentDictionary para evitar problemas de concurrencia durante las actualizaciones, y es estático para que su información sea compartida entre todas las instancias del servicio.1.2. Notificando a los clientes las desconexiones
Cuando SignalR detecta que un cliente se ha desconectado, invocará al método virtualOnDisconnect() del endpoint, lo cual nos permite introducir lógica de gestión del evento. En nuestro caso, simplemente necesitamos eliminar al cliente del diccionario donde los estamos almacenando, De la misma forma, debemos controlar las desconexiones para notificar este hecho a los clientes aún conectados, para lo que sobrescribimos el método
OnDisconnect(): protected override void OnDisconnect(string clientId)
{
string text, clientDescription;
if (_clients.TryRemove(clientId, out clientDescription))
text = clientDescription + " is leaving.";
else
text = "Unknown user leaving.";
var msg = new NotificationMessage(text, _clients.Count);
Connection.Broadcast(msg);
}
En este método recibimos el ClientId que SignalR asignó al cliente en el momento de iniciar la conexión; lo único que hacemos es buscarlo en el diccionario de clientes donde los estamos almacenando, eliminarlo, y enviar un mensaje broadcast al resto de usuarios indicando la desconexión que se ha producido.Cuando implementéis funcionalidades en la desconexión, tened en cuenta que SignalR tarda unos segundos en darse cuenta de las desconexiones (recordad que con el transporte utilizado por defecto se trata de una conexión persistente virtual) por lo que puede aparecer un leve retraso en las notificaciones. Estos tiempos, en cualquier caso, pueden ser configurados (en el proyecto de demostración podéis ver cómo hacerlo).
[Actualización]: como bien indica Arturo en un comentario del post, para que las desconexiones sean notificadas correctamente es necesario utilizar IIS o IIS Express. Con Cassini (el servidor web integrado en VS) no funcionará bien este mecanismo.
1.3. Algunas observaciones adicionales
Al principio de comenzar a jugar con conexiones persistentes de SignalR, una de las cosas que pueden llamar la atención es que si en la implementación del métodoOnConnected() enviamos un broadcast a todos los usuarios conectados, el usuario actual (el que ha provocado la llamada a OnConnected) no recibirá el mensaje; o en otras palabras, el broadcast llegará a todos los clientes excepto al que acaba de realizar la conexión.Desconozco si se trata de un comportamiento por diseño, si es algo que se modificará en posteriores revisiones de SignalR (recordemos que en estos momentos es todavía una versión preliminar), o si simplemente se trata de un nombre para el método poco afortunado, pues en mi opinión da a entender que la conexión ya ha sido realizada y, por tanto, el broadcast debería llegarle también.
Pero en cualquier caso, en la implementación del proyecto de pruebas que podéis descargar al final de este post veréis cómo lo he solucionado incluyendo una llamada explícita (“ping”) desde el cliente al servidor para forzar el envío de un mensaje de actualización justo después de completarse la conexión. Conceptualmente, lo que se hace es:
- desde el cliente, una vez se ha realizado la conexión, realizar un envío de datos al servidor, algo similar a un “ping”,
- en el método
OnReceived()del servidor, capturar el mensaje enviado desde el cliente y responderle de forma directa con la información que nos interese hacerle llegar, que podría ser un mensaje de bienvenida y, como en otras ocasiones, el número de usuarios conectados:protected override void OnReceived(string clientId, string data) { var msg = new NotificationMessage("Hi!", _clients.Count); Send(clientId, msg); }
2. Registro de ruta
Una vez tenemos el servicio implementado, debemos registrar en el sistema de routing de ASP.NET una URL a través de la cual será posible acceder al mismo. El lugar idóneo para hacerlo, como siempre que se trata de cargar la tabla de rutas, es en el global.asax, para que se ejecute durante la inicialización de la aplicación.Por ejemplo, en una aplicación ASP.NET MVC podría ser algo así:
public static void RegisterSignalrConnections(RouteCollection routes)
{
routes.MapConnection<VisitorsService>("Visitors", "VisitorsService/{*operation}");
}
protected void Application_Start()
{
RegisterSignalrConnections(RouteTable.Routes);
[...]
}
Observad que lo único que estamos haciendo es añadir a la tabla de rutas una entrada en la que asociamos el servicio, en este caso nuestra clase VisitorsService, a la dirección “VisitorsService/{*operation}”, que será la URL de acceso al mismo. El primer parámetro que enviamos al método
MapConnection() es simplemente el nombre de la entrada en la tabla de rutas, no tiene demasiada importancia.3. Implementación del cliente web
La implementación de clientes web para las conexiones persistentes desarrolladas con SignalR es bastante simple, y comienza incluyendo en la página o vista una referencia hacia la biblioteca cliente de este componente:<script src="@Url.Content("~/Scripts/jquery.signalR.js")" type="text/javascript"></script>
Como siempre, esta inclusión puede realizarse a nivel de página, o bien en la Master o Layout si queremos aplicarlo a todas las vistas del sistema.Nota: si queremos dar soporte a clientes antiguos que no soportan deserialización JSON de forma nativa (por ejemplo, IE7), será necesario descargar desde Nuget la biblioteca de scripts json2.js y referenciarla en la página antes de la carga de SignalR.js. En caso contrario, se lanzará una excepción con el error:Centrándonos en nuestra aplicación, el marcado HTML será tan simple como el que se muestra a continuación, lo único que hacemos es dejar un “hueco” en el que introduciremos los mensajes que se vayan recibiendo del servidor:
“SignalR: No JSON parser found. Please ensure json2.js is referenced before the SignalR.js file if you need to support clients without native JSON parsing support, e.g. IE<8”
<h2>Log</h2> <div id="log"></div>A continuación, necesitamos implementar el código de script que realice las siguientes tareas:
- iniciar la conexión con el endpoint,
- tras ello, enviar un “ping” para recibir el mensaje de bienvenida (recordad lo que os comentaba previamente de que el broadcast no se recibe por el cliente que inicia la conexión),
- mostrar en el log la información recibida del servidor.
<script type="text/javascript">
$(function () {
var conn = $.connection("VisitorsService");
conn.received(function (data) {
var text = data.Date + " - " + data.Message + " " +
data.OnlineUsers + " users online.";
$('#log').prepend("<div>" + text + "</div>");
});
conn.start(function () {
conn.send("ping");
});
});
</script>
Lo comentamos muy rápidamente:- en la variable
connobtenemos una referencia hacia el endpoint, identificado por el nombre de la conexión persistente, en este caso,VisitorsService. - sobre ella, definimos la función
received(), que será invocada cuando el servidor envíe información. El parámetro que recibe la función anónima es la información enviada desde el servidor, que, recordaréis, en este caso se trataba en objetos de tipoNotificationMessage. Dado que la serialización y deserialización se realizan de forma automática, podemos acceder directamente a sus miembros, como podéis ver en el código para montar el mensaje e introducirlo en el log. - por último, iniciamos la conexión invocando al método
start()de la conexión. Observad que este método admite un callback que será llamado cuando la conexión se haya establecido, momento que aprovechamos para enviar el “ping” al servidor que nos permitirá recibir el mensaje de bienvenida.
Si tenéis un ratillo, no dejéis de descargar el proyecto de prueba y jugar un rato con él. Y sobre todo, observad las pocas líneas de código que hemos tenido que emplear para resolver esta funcionalidad y comparadlo con lo que supondría implementarla de forma artesana, con las técnicas tradicionales.
Descargar proyecto de prueba.
En el próximo post de la serie veremos cómo utilizar los Hubs de SignalR, un planteamiento con una abstracción aún mayor sobre la conexión y una integración entre cliente y servidor simplemente espectacular.
Publicado en Variable not found.
» Leer más, comentarios, etc...
Najaraba.com: Software libre, metodologías ágiles y más.
Nueva etapa profesional: la inspiración
Enero 23rd, 2012 - [Enlace local]
No sería capaz de reflejar mejor estos últimos cinco años trabajando en Biko de cómo ya los ha reflejado Jessi en su blog. Va de personas que son felices en su trabajo. Porque el desarrollo de software no es trabajar con ordenadores y picar código. El desarrollo de software es mucho más: son personas haciendo cosas grandes que disfrutan con lo que hacen, y sobre todo, con quien lo hacen. Este
» Leer más, comentarios, etc...
Koalite's blog
Demasiada abstracción
Enero 23rd, 2012 - [Enlace local]
Hay veces que llegamos a un punto en que intentamos abstraer demasiado las cosas y acabamos teniendo lo que se suele llamar una leaky abstraction. Se trata de casos en los cuales el mecanismo de abstracción no es efectivo, aquello que queremos abstraer acaba traspasando la capa de abstración y lo único que conseguimos es una complicación innecesaria.
Recientemente he padecido un caso claro de esto usando la API de consultas QueryOver de NHibernate. QueryOver está diseñado como una implementación del patrón Query Object aprovechando expresiones lambda para hacer static reflection y conseguir así que el API sea type-safe y refactor friendly.
QueryOver intenta abstraer el acceso a la base datos, pero a la vez trata de mantener toda la potencia del SQL, por lo que en cuanto las consultas se complicando un poco acaba siendo un lío y la ganancia que tenemos por ser type-safe y refactor friendly no compensa la pérdida de legibilidad.
Veamos un ejemplo concreto bastante simpe. Supongamos que tenemos el típico modelo de clientes y pedidos y queremos lanzar una consulta para obtener el número de pedidos y el importe total pedido por cada cliente. La implementación con QueryOver es algo así:
Customer customer = null; var stats = s.QueryOver() .JoinAlias(x => x.Customer, () => customer) .SelectList(lst => lst .SelectGroup(() => customer.Id) .SelectGroup(() => customer.Name) .SelectSum(x => x.Total) .SelectCount(x => x.Id)) .List
El resultado es bastante feo. Para poder hacer el equivalente al inner join de forma type-safe, tenemos que declarar una variable de tipo Customer que usamos únicamente como alias para usarla luego en las expresiones lambda. Además, para construir la lista de columnas a devolver se usa un builder (lst) que simplifica un poco las cosas pero no acaba de resultar claro.
Si la misma consulta la lanzamos con el equivalente HQL, el lenguaje de consultas de NHibernate, tenemos:
var stats = s.CreateQuery(@"select c.Id, c.Name, sum(o.Total), count(o.Id)
from Order o right join o.Customer c
group by c.Id, c.Name")
.List
Para cualquiera que esté acostumbrado a manejar SQL, está claro que la consulta resulta mucho más legible. Es cierto que no es type-safe no refactor friendly, pero en mi opinión la legibilidad lo compensa.
Parece que nuestra tendencia natural como desarrolladores es siempre abstraerlo todo, pero a veces hay que tener cuidado porque puede que estemos causando más problemas de los que solucionamos.
No hay posts relacionados.
» Leer más, comentarios, etc...
Escuela De Codigo
GitHub, para el que empieza con Git
Enero 23rd, 2012 - [Enlace local]
La semana pasada vimos una corta y puntual introducción a Git, solo lo necesario para el que no sabe nada de control de versiones deje de vivir en la era del oscurantismo y pase a ser parte del cada dia mas grande, grupo de iluminados que hacen de su vida de desarrollador mas facil, utilizando Git. Pues bien hoy en dia no se puede mencionar Git sin decir GitHub. ¿Que es? ¿Como se sirve? ¿Con que lo aderezo? En este articulo conoceremos GitHub y lo mucho que nos puede ayudar.
¿Que es GitHub?
GitHub es un sitio web para alojar proyectos utilizando el sistema de control de versiones Git.
¿Necesitas alojar tu proyecto en algun repositorio Git que no sea en tu computadora? ¿No quieres perder tu tiempo configurando un servidor remoto como repositorio de Git? Entonces GitHub es para ti, un sitio web donde todos tus proyectos que utilicen Git estaran bien resguardados.
Seria muy injusto decir que GitHub solo es un simple sitio web para guardar repositorios Git. Porque la verdad es que es mucho mas que eso,es una “red social” donde los desarrolladores compartimos nuestro codigo fuente con otros. Todos los repositorios en GitHub son open source (todos los que no son de pago) asi que podemos descargarlos, clonarlos,enviar parches, corregir el codigo de otro, que otros nos envien sus cambios, etc, etc.
De esa forma no solo compartimos nuestro código, sino que lo exponemos a una audiencia de profesionales (como nosotros) para que lo puedan evaluar, corregir y mejorar
Para empezar, registrate en GitHub
Ingresa a https://github.com/plans , elige el plan gratuito, llena el formulario (bastante simple no tendras problemas) y ya estas registrado!
Mi primer repositorio
Vamos a estrenarnos dentro de GitHub, para eso ya debemos tener correctamente configurado Git, ¿No lo has hecho?? Tomate unos minutos para leer este articulo antes de continuar
Crea un nuevo repositorio
GitHub es tan bueno con nosotros, que inmediatamente despues de crear el repositorio nos indica como debemos proceder, asi que hagamos lo que dice
Sube el código
Antes que nada, crea en tu computadora la carpeta donde tendras el código fuente, abre una terminal y escribe
mkdir Hola-Gato
y muevete dentro de la carpeta recien creada
cd Hola-Gato
inicializa el repositorio Git
git init
Los repositorios en GitHub tienen un archivo muy importante, el README, dentro de este archivo se colocan instrucciones que quieres que los desarrolladores lean desde que entran a ver tu repositorio, asi que no olvidemos crearlo. Utiliza Markdown para escribir en el.
touch README
Ahora que ya tienes un archivo en tu repositorio, lo agregamos
git add README
y ejecutamos nuestro primer commit
git commit -m “Primer commit en el proyecto”
Hasta este momento todo lo que hemos hecho, seria como cualquier proyecto en el que usemos Git, todo local, para relacionar nuestro código fuente con el repositorio remoto que recien hemos creado en GitHub debemos ejecutar lo siguiente
git remote add origin git@github.com:escueladecodigo/Hola-Gato.git
y finalmente subimos el codigo a GitHub
git push -u origin master
Ahora cuando demos en el enlace Continue veremos algo como lo siguiente
Ahora ya tienes tu primer repositorio en GitHub, listo para que cualquiera lo vea, lo clone, haga forks, te envié mejoras, etc, etc. Solo llénalo un poco con tu código, no creo que un repositorio con un solo archivo README sea muy llamativo para otros desarrolladores
GitHub cuenta con tantas funcionalidades; resaltado de sintaxis, seguir desarrolladores, clonar repositorios, etc, etc. Por el momento dejare que tu curiosidad trabaje un poco y explores todo lo que Git junto con GitHub puede ofrecerte. En artículos posteriores iremos desglosando cada una de esas opciones, conociéndolas bien y sacandoles el máximo provecho posible. Así que no te pierdas los próximos artículos, te ayudaran no solo a conocer Git sino a usarlo como un ninja!
» Leer más, comentarios, etc...
xperiments.es
(English) i5hare project launched.
Enero 22nd, 2012 - [Enlace local]
Disculpa, pero esta entrada está disponible sólo en English.
» Leer más, comentarios, etc...
xperiments.es
(English) StageWebViewBridge Update
Enero 22nd, 2012 - [Enlace local]
Disculpa, pero esta entrada está disponible sólo en English.
» Leer más, comentarios, etc...
El blog de pico.dev
Errores de precisión, redondeo y representación con float y double
Enero 21st, 2012 - [Enlace local]

Supongamos que tenemos una cantidad de dinero tal que 100,05 a la que aplicamos un 10% de descuento y posteriormente un 5% en concepto de impuestos. Las líneas de código que calculan esto son:
import java.text.NumberFormat;
double amount = 100.05;
double discount = amount * 0.10;
double total = amount - discount;
double tax = total * 0.05;
double taxedTotal = tax + total;
NumberFormat money = NumberFormat.getCurrencyInstance();
System.out.println("Subtotal: "+ money.format(amount));
System.out.println("Discount: " + money.format(discount));
System.out.println("Total: " + money.format(total));
System.out.println("Tax: " + money.format(tax));
System.out.println("Tax+Total: " + money.format(taxedTotal));
Y el resultado es:
Subtotal: 100,05 €
Discount: 10,00 €
Total: 90,04 €
Tax: 4,50 €
Tax+Total: 94,55 €
Si nos fijamos en la suma de total más impuestos hay una diferencia de 0.01 y si presentamos un desglose de precios como este a un usuario puede que este piense que hay algún error en el cálculo, le genere desconfianza y no haga la compra en el peor de los casos. Viendo los valores sin los redondeos que hace NumberFormat tenemos:
Subtotal: 100.05
Discount: 10.005
Total: 90.045
Tax: 4.50225
Tax+Total: 94.54725
Los redondeos que hace NumberFormat es HALF_EVEN por defecto, de modo que cuando un decimal está equidistante a las dos partes se redondea a la parte par por lo que con una precisión de dos decimales:
Discount: 10.005 se redondea a 10.00
Total: 90.045 se redondea a 90.04
Tax: 4.50225 se redondea a 4.50
Tax+Total: 94.54725 se redondea a 94.55
En este caso se trata de un problema de redondeo pero ahora supongamos que tenemos una cantidad de 0,70 céntimos a la que no aplicamos un descuento pero si el procentaje de impuestos del 5%. Tendríamos:
import java.text.NumberFormat;
double amount = 0.70;
double tax = amount * 0.05;
double taxedTotal = tax + amount;
NumberFormat money = NumberFormat.getCurrencyInstance();
System.out.println("Subtotal: "+ money.format(amount));
System.out.println("Tax: " + money.format(tax));
System.out.println("Tax+Total: " + money.format(taxedTotal));
Subtotal: 0,70 €
Tax: 0,03 €
Tax+Total: 0,74 €
Nos encontramos otra vez con la diferencia de 0.01. Vemos los valores sin redondear por NumberFormat:
Subtotal: 0.7
Tax: 0.034999999999999996
Tax+Total: 0.735
Aquí se ve que el resultado de ciertas operaciones aritméticas entre datos double (o float) son almacenadas por una computadora con errores de precisión, 0.70 * 0.05 (debería ser 0.035).
Para evitar estos errores debemos utilizar la clase BigDecimal que pemite almacenar números con una precisión en la práctica infinita en base 10, realizar los cálculos como los humanos esperan, en base diez, y hacer los redondeos de precisión. Aplicando una precisión de dos decimales a los números y usando BigDecimal tenemos:
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
RoundingMode RM = RoundingMode.HALF_EVEN;
BigDecimal amount = new BigDecimal("100.05");
BigDecimal discountPercent = new BigDecimal("0.10");
BigDecimal discount = amount.multiply(discountPercent).setScale(2, RM);
BigDecimal total = amount.subtract(discount).setScale(2, RM);
BigDecimal taxPercent = new BigDecimal("0.05");
BigDecimal tax = total.multiply(taxPercent).setScale(2, RM);
BigDecimal taxedTotal = total.add(tax).setScale(2, RM);
NumberFormat money = NumberFormat.getCurrencyInstance();
System.out.println("Subtotal : " + money.format(amount));
System.out.println("Discount : " + money.format(discount));
System.out.println("Total : " + money.format(total));
System.out.println("Tax : " + money.format(tax));
System.out.println("Tax+Total: " + money.format(taxedTotal));
Ahora los precios si están correctos:
Subtotal : 100,05 €
Discount : 10,00 €
Total : 90,05 €
Tax : 4,50 €
Tax+Total: 94,55 €
Para el otro caso en el que teníamos un error de precisión:
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
RoundingMode RM = RoundingMode.HALF_EVEN;
BigDecimal amount = new BigDecimal("0.70");
BigDecimal taxPercent = new BigDecimal("0.05");
BigDecimal tax = amount.multiply(taxPercent).setScale(2, RM);
BigDecimal taxedTotal = tax.add(amount).setScale(2, RM);
NumberFormat money = NumberFormat.getCurrencyInstance();
System.out.println("Subtotal: "+ money.format(amount));
System.out.println("Tax: " + money.format(tax));
System.out.println("Tax+Total: " + money.format(taxedTotal));
Subtotal: 0,70 €
Tax: 0,04 €
Tax+Total: 0,74 €
Referencia:
http://www.javamexico.org/blogs/luxspes/por_que_usar_bigdecimal_y_no_double_para_calculos_aritmeticos_financieros
http://speleotrove.com/decimal/decifaq1.html#tzeros
http://www.mkyong.com/java/how-do-calculate-monetary-values-in-java-double-vs-bigdecimal/
http://blogs.oracle.com/CoreJavaTechTips/entry/the_need_for_bigdecimal
http://stackoverflow.com/questions/7539/please-explain-the-use-of-java-math-mathcontext/7561#7561
http://en.wikipedia.org/wiki/Floating_point
» Leer más, comentarios, etc...
Bitácora de Javier Gutiérrez Chamorro (Guti) » Programación
Código nativo y dispositivos móviles
Enero 21st, 2012 - [Enlace local]
El panorama actual de dispositivos móviles, ha quedado, podríamos decir que reducido a iOS de Apple, Android de Google, y Windows Phone de Microsoft (con el permiso del marginal TabletOS de RIM). La evolución ha llevado a que el código bytecode sea el que domine estas plataformas. Java para Android, y .NET para Windows Phone. [...]
Artículos relacionados:
Rendimiento de dispositivos móviles
Office 2007 no es nativo x64
Código automodificable en PHP
» Leer más, comentarios, etc...
Javier Pérez
¿Eres inteligente? Relación entre el cociente intelectual y comportamientos e ideas del ser humano
Enero 20th, 2012 - [Enlace local]
Tendencia al suicidio = Menos inteligente
Un estudio realizado por investigadores de varias universidades del mundo, sobre informes médicos de 24 años referentes a más de un millón de hombres, relaciona el cociente intelectual con la falta de tendencia al suicidio. Es decir, que las personas con más tendencias suicidas suelen tener menor cociente intelectual, sin capacidad para enfrentarse a los problemas o eventos traumáticos.
Conservador y religioso = Menos inteligente
Los más inteligentes suelen tender a probar cosas nuevas. 14.000 adolescentes norteamericanos evaluados en 2001 y 2002 dan como resultado esta relación entre ser conservador y la falta de inteligencia.
Usar Internet Explorer = Menos inteligente
Un estudio muy controvertido y cuya veracidad o autoridad está en entredicho, relaciona el uso del navegador de Microsoft, Internet Explorer, y la falta de cociente intelectual.
Consumir drogas = Más inteligente
El estudio sobre esta relación comenzó en 1970, del Estudio Británico de Cohorte, realizando un seguimiento a miles de niños (5-16 años) durante décadas hasta que cumplieron los 30 años. Este estudio venía a demostrar también que los más inteligentes son más propensos a probar y experimentar cosas nuevas.
Hermano mayor = Más inteligente
Este estudio revelaría que los hermanos mayores son estadística y significativamente más inteligentes que sus hermanos pequeños (análisis de 241.310 hombres de 18-19 años). Se concluye además que por ese motivo los hermanos pequeños suelen ser más simpáticos, porque tratan de competir con su hermano mayor por otras vías.
Te gusta música clásica = Más inteligente
Un estudiante de doctorado del Instituto de Tecnología de California ideó un sistema para calcular una estadística que relacionara los gustos musicales con el nivel intelectual, en base a los datos de Facebook de estudiantes de diferentes universidades americanas, contrastándolos con sus notas académicas. El resultado fue que los que decían que Beethoven era su músico preferido eran los más inteligentes, y los menos inteligentes los que les gustaba el RAP o el reguetón.
Hombre fiel y ateo = Más inteligente
Este estudio también hace incapié en la falta de fé religiosa, además de en la fidelidad en la pareja, como síntoma de más inteligencia, estadísticamente hablando.
Cerebro en desarrollo = ???
Y si aún no ha terminado la edad de desarrollo cerebral (hasta los 18-20 años), ten en cuenta que tu cociente intelectual aún puede variar, y no necesariamente a más inteligente…

» Leer más, comentarios, etc...
Bitácora de Javier Gutiérrez Chamorro (Guti) » Programación
Java 8, Eclipse 4.2 y Netbeans 7.1
Enero 19th, 2012 - [Enlace local]
Sin ser un gran defensor de Java a pesar de haberlo tocado bastante durante sus comienzos, debo reconocer que a día de hoy, Java es una plataforma madura, que le ha llevado a tener un rendimiento aceptable (teniendo en cuenta que es bytecode), y un nivel de estabilidad elevado. El garbage collector funciona correctamente, podría [...]
Artículos relacionados:
Eclipse solar
Sieve en Java
La historia de Java se parece al descubrimiento de América
» Leer más, comentarios, etc...
Koalite's blog
EventHandlers con jQuery 1.7: on() vs click()
Enero 19th, 2012 - [Enlace local]
En la última versión de jQuery han intentado unificar las APIs de manejo de eventos en los métodos on y off. Estos métodos sustituyen a los antiguos bind(), delegate() y live().
Si comparamos el uso de on() con el de atajos que ya existían, como click(), tenemos el siguiente código:
// Asignar un manejador de eventos usando click
$("#header a").click(function() {
// manejar el evento
});
// Asignar un manejador de eventos usando on
$("#header a").on("click", function() {
// manejar el evento
});
Estas dos construcciones son equivalentes, pero on() permite hacer muchas más cosas. Una de las cosas que más me gusta es que permite usar un mismo manejador de eventos para múltiples elementos html suscribiendo el manejador a un elemento padre. Para ver lo que significa este lío de frase, es mejor ver un ejemplo. Supongamos que tenemos este código:
Si por algún oscuro motivo queremos asignar el mismo manejador de eventos a todos los elementos , podemos hacerlo de la siguiente forma:
$("#content").click("click", "a", function() {
// manejar el evento
// $(this) apunta al que ha generado el evento
});
Esto tiene varias ventajas:
- Sólo se crea una única función, independientemente del número de elementos
que tengamos, reduciendo el consumo de recursos. - Es válido para elementos que no existen todavía. Si apareciese un nuevo elemento
dentro del, automáticamente estaríamos manejando su eventoclick. Esto es especialmente útil cuando generamos html dinámicamente.Nota para los que usamos demasiado C#
Si, al igual que yo, usas mucho C# u otro lenguaje estático, es posible que se te haga raro este tipo de API. En C#, la diferencia entre usar un API como
element.click()y otra comoelement.on("click",...)es que la primera es type-safe y refactor-friendly, mientas que la segunda se basa en el uso de un magic string.Sin embargo, no hay que olvidarse que esto es Javascript y es dinámico. Es igual de “seguro” (o inseguro, según se mire), escribir
person.namequeperson["name"], por lo que el uso de magic strings es algo normal, frecuente y que hay que ver como una característica del lenguaje de la que aprovecharnos, no como una limitación.Posts relacionados:
» Leer más, comentarios, etc...
Escuela De Codigo
Side Project, es bueno trabajar en algo propio.
Enero 19th, 2012 - [Enlace local]
Un Side Project, es en palabras simples, un proyecto, invento, experimento que hago sencillamente porque tengo las ganas y el tiempo para hacerlo. ¿Porque trabajar en algo que aparentemente no nos dara ningún beneficio ya que nadie nos paga por hacerlo? Es lo que descubriremos en este articulo. La rutina matara tu pasión por programar
Llega un momento en la vida de todo desarrollador, que se levanta una mañana y se da cuenta que esta haciendo exactamente lo mismo que el día anterior, y que el día siguiente hara lo mismo, y la siguiente semana sera igual y peor aun es posible que el siguiente mes la mayor variación con la que se encuentre sera…posiblemente nada. Los programadores también caemos en rutinas, y para mi al menos, no hay peor rutina que la que implica: programar en el mismo lenguaje, en la misma plataforma, en el mismo IDE, en el mismo sistema operativo, resolviendo los mismos problemas con las mismas soluciones. Es un completo fastidio!!! Asi como la rutina mata el amor entre una pareja, también matara tu amor por tu trabajo, por programar. Y no queremos eso ¿cierto?
Vuelve al primer amor, trabaja en un Side Project
Si en tu trabajo son como autómatas siguiendo un manual escrito en piedra, sin ninguna posibilidad de cambiar algo, y si ahí se programa en Java así se hara toda la vida hasta que un nuevo profeta diga que hay que usar otra cosa. Dejame decirte que la única posibilidad para romper tu rutina, es creando, uno o varios Side Project, tu sabes, pequeños proyectos en paralelo que llevas por diversión, por curiosidad, cosas que programas solo para experimentar, para probar ese nuevo framework, esa nueva librería, ser atrevido.
La esencia de un Side Project es básicamente crear una pieza de software con el único proposito de ser el amo y señor de nuestro minúsculo universo, hacer las cosas como yo digo, como yo creo que es correcto, como yo quisiera que fuera correcto. Hacer algo con mis propias manos, sin que nadie me diga como hacerlo, sin cumplir requerimientos, sin seguir ordenes!! mas que las que me dicta mi propia mente.
¿Quieres probar esa nueva librería que en el trabajo y en los proyectos de la universidad no te dejan? Hazlo!!! Es TU proyecto ¿Quien te va a decir que no?
¿Quieres probar esa nueva metodología de desarrollo que tanto lees en sitios web y blogs? Hazlo!!! Es TU proyecto. Recuerda eres el amo y maestro.
Cuando tenemos una fin de semana espectacular, el lunes que regresamos a trabajar no se siente tan mal. Lo mismo es cuando has trabajado en un proyecto propio. Regresar a la rutina se hace mas llevadero.
¿Y que gano con hacer un Side Project?
Básicamente:
- Salir de tu aburrida rutina como programador! Si ya estas harto de programar lo mismo un día tras otro. Pues si tienes un proyecto personal podrás hacer lo que se te venga en gana. No rutinas aburridas.
- Experimentación, si eres de los que tiene miedo de hacer algo con el codigo de la empresa por temor a arruinarlo todo, en tus proyectos no tienes de que preocuparte, si algo falla, no se destruira el mundo no te preocupes.
- Aprendizaje, con los errores cometidos, viene la sabiduría. Aprenderas mucho de como hacer algo o como no hacerlo.
- A tu manera, todo lo harás siguiendo las ordenes de una tan sola persona: tu.
- Algo mas para tu curriculum, si lo que hagas te parece muy bueno, porque no hacerlo publico y mostrarlo a todo mundo.
Ahora ya lo sabes, olvídate por un segundo de tus clientes, de tu trabajo. Deja de pelear guerras ajenas por un momento y construye algo propio. Diviértete, experimenta, aprende y quien sabe si lo que hagas sea el siguiente Twitter, uno nunca lo sabe.










