20 dic 2011

GWT: eventos touch


GWT me recuerda a Django, si bien la documentación es muy extensa tiene multitud de trucos y tips que 
leyendo solamente el Javadoc son imposibles de descubrir, el manejo de eventos touch es un ejemplo perfecto por lo que creí oportuno escribir esta micro-guia para manejar esas situaciones. Los dispositivos táctiles como tablets y smartphones son medios de acceso cada vez más habituales a nuestras aplicaciones web por tanto no podemos quedarnos solamente con los eventos relacionados al mouse, algo tan común como mostrar un mensaje al hacer mouseover sobre un elemento de la interfaz simplemente no funciona.
GWT tiene clases especificas relacionadas al touch así que vamos a ver como utilizarlas, básicamente manejaremos los eventos TouchStartEvent, TouchMoveEvent y TouchEndEvent a través de sus handlers TouchStartHandler, TouchMoveHandler y TouchEndHandler, los resultados puedes verlos en el video: 




El ejemplo es muy sencillo, como vemos en el código en el método onModuleLoad está el manejo de los eventos, añadí clear() solo para limpiar los estilos y poder cambiar el fondo del panel que implementa el touch. El gran truco para que funcione es añadir la línea event.preventDefault(), esta cancela la propagación del evento disparado y permite que la aplicación detecte los siguientes, si no lo especificamos la aplicación no puede distinguir cundo pasamos de uno a otro y se queda con el primero detectado, lamentablemente esto no lo vi por ningún lado en la documentación ya que te envía a la Safari Touch Event Documentation donde seguramente no encuentres muchos ejemplos de GWT :)


public class Touch_test implements EntryPoint {

 // utilizamos un FocusPanel para detectar los eventos y un Label para mostrar su nombre  
 private final FocusPanel fpanel = new FocusPanel();
 private final Label lbl = new Label("evento: ");


 // limpiamos los estilos para mostrar cada evento con un color diferente
 private void clear() {
  fpanel.removeStyleName("back_red");
  fpanel.removeStyleName("back_gray");
 }

 
 public void onModuleLoad() {
  
  // le damos alto, ancho y un borde  
  fpanel.setStyleName("fPanel");
  
  // detectamos el evento TouchStartEvent 
  fpanel.addTouchStartHandler(new TouchStartHandler() {
   @Override
   public void onTouchStart(TouchStartEvent event) {
    event.preventDefault(); // IMPORTANTE!!

    lbl.setText("evento: touch");
    clear();
    fpanel.addStyleName("back_red"); // coloreamos de rojo el panel
   }
  });
  
  // detectamos el evento TouchMoveEvent
  fpanel.addTouchMoveHandler(new TouchMoveHandler() {
   @Override
   public void onTouchMove(TouchMoveEvent event) {
    event.preventDefault(); // IMPORTANTE!!

    lbl.setText("evento: move");
    clear();
    fpanel.addStyleName("back_gray"); // coloreamos de gris el panel
   }
  });
  
  // detectamos el evento TouchEndEvent
  fpanel.addTouchEndHandler(new TouchEndHandler() {
   @Override
   public void onTouchEnd(TouchEndEvent event) {
    event.preventDefault(); // IMPORTANTE!!

    lbl.setText("evento: end");
    clear();  // dejamos si estilos el panel
   }
  });

  RootPanel.get().add(lbl);
  RootPanel.get().add(fpanel);
 
 }
}




Los estilos son solo para darle un toque visual:

.fPanel {
 height:200px; 
 width:200px;
 border: solid 1px #CCC;
}

.back_red{
 background-color:red; 
}

.back_gray{
 background-color: #CCC; 
}


Es bastante simple, lo que quiero destacar es asegurarse de agregarle la dichosa línea event.preventDefault() y funciona bastante bien, lo probé en un iPad y un smartphone con Android y en ambos responde de forma similar, otra cosita que sumar a nuestro arsenal de desarrollo.



14 dic 2011

Por qué iOS es más fluido que Android

No soy de compartir enlaces sin agregar algo más pero este vale la pena, nada de subjetividades, puro argumento técnico, sin más les recomiendo Por qué iOS es más fluido que Android


24 nov 2011

Redirigiendo peticiones en Apache


Esta es una de esas tareas sencillas que donde se complique un poco prepárate para perder más tiempo del que pensabas. Cuando buscamos redirigir peticiones con Apache, más si no implica reescribir direcciones o algo complejo, una de la opciones más simple es utilizar un archivo .htaccess en el directorio que nos interesa modificar el comportamiento, el tema es que no basta solo con eso ya que hay una pequeña serie de cosas a tener configuradas para que funcione.
La solución básica como comentaba es utilizar este tipo de archivos que contienen directivas para modificar el comportamiento del servidor, Apache verifica su existencia antes de responder habiendo infinidad de opciones desde simples como no listar los archivos en un directorio hasta cosas más elaboradas como sustituir partes de una URL, manejar errores y demás.

En este caso la directiva que nos interesa se llama Redirect, siendo su sintaxis:

Redirect 301 /Directorio/old_index.php http://localhost/Directorio/new_index.php


Aquí Redirect es la directiva que especifica redirigir la petición y la acompañamos con los códigos de estado, estos si bien generalmente los pasamos de largo son bastante importantes teniendo cada uno un significado particular y es buena cosa conocerlos, aunque parezca que el resultado sea el mismo son fundamentales para que los navegadores puedan "comprender" el estado de un recurso, en este caso utilizamos uno de la serie 3xx que comprende las redirecciones, 301 significa que el recurso fue Movido permanentemente.
Luego colocamos la ruta del archivo original que ya no será accesible y separada la nueva dirección completa, es decir incluyendo el http://, el archivo se coloca en el directorio raíz o podemos incluirlo en el directorio específico donde se encuentre el archivo a excluir, lo importante es esté en nuestra ruta de búsqueda para que Apache lo tenga en cuenta (más adelante el porque es importante su ubicación).
Bien, ahora accedemos a http://localhost/Directorio/old_index.php y debemos ser redirigidos a http://localhost/Directorio/new_index.php, pero.... nada sucede, algo anda mal... y bueno, a prepararse para googlear un rato :)

El tema es que algunas de estas directivas hacen uso de funcionalidades de módulos de Apache, por lo que tenemos que verificar también que el módulo este primero disponible, y segundo, habilitado. En este caso es el llamado mod_alias, que viene incluido por defecto en Apache, así que a verificar si lo tenemos habilitado, en Ubuntu tipeamos en la terminal:

a2enmod alias

este comando y su contrapartida a2dismod son para habilitar (en-abled)  o desahabiliar (dis-abled) módulos, obtenemos:

Module alias already enabled

significa que ya lo tenemos y está habilitado, bien, no es problema  de módulos, que más verifico?
Lo siguiente a tener en cuenta son los archivo de configuración de Apache, supuestamente el httpd.conf pero en mi caso esta en blanco así que los buscamos en el directorio sites-enabled (en Ubuntu bajo /etc/apache2/sites-enabled), esta estructura es similar a la de módulos, los disponibles en mods-available y los activos en mods-enabled. En este caso tenemos los sites-available y los sites-enabled (son simplemente links), vamos a este último ya que posee los específicamente habilitados. En mi caso solo tengo un sito habilitado pero este archivo varía de una instalación a otra, buscamos algo como:

 
<Directory /var/www/>
  AllowOverride none
  Order allow,deny
  allow from all
</Directory>

Aquí esta el culpable, entre todas las opciones disponibles tenemos la infame AllowOverride, según la documentación "AllowOverride controls what directives may be placed in .htaccess files.", observamos que tiene un rotundo None, ahora sí, de ahí que no funcione el .htaccess que colocamos, lo sustituimos por un "All" y reiniciamos el servidor. Efectivamente ahora sí las peticiones son redirigidas a la nueva ruta, si examinamos el request con Firebug o similares vemos:

  Request URL:http://localhost/Directorio/
  Request Method:GET
  Status Code:301 Moved Permanently

siendo redirigidos a la nueva ruta, hay que tener en cuenta que también podemos especificar que directorios queremos habilitar y no todo el sitio (como en mi caso <Directory /var/www/>) y de ahí la importancia de donde colocaremos el .htaccess, también para con None/All hay más opciones, ahi depende de cuanto queramos customizar el server. Es sencillo pero como decía hay que verificar un par de cosas en caso de que no ande, si luego de esta corta guía sigue sin funcionar prepárate para leer un rato más.



11 nov 2011

Cherokee Market

Bien decíamos que las tiendas de aplicaciones llegaron para quedarse, ahora no pensé que el rango de escenarios fuera tan diverso, leyendo por ahí me traigo el Cherokee Market, no sé si es el único en su tipo pero tiene pinta. Aparentemente es como los hostings con aplicaciones prearmadas pero en tu propia infraestructura, viniendo de la mano de Cherokee no debe ser malo, tuve la oportunidad de jugar un poco con este servidor y es muy amigable, con una interfaz cuidada que simplifica bastante el trabajo.






Y lo fundamental, el rendimiento parece ser bastante bueno, no debe ser lo óptimo para configuraciones muy exigentes donde haya que afinar mucho las perillas pero es interesante.
A mí personalmente instalar un Nagios o un Redmine no me engancha demasiado así que si con un par de clicks tengo el tema solucionado no lo dudo, en precios ambos por ejemplo figuran como gratuitos y un Liferay CE está a U$S 29.95, tampoco tan escandaloso, habrá que probarla a ver que tal.


7 nov 2011

Web o Desktop?

Mientras leía el post Web o desktop? en Software Guisho, pensaba en lo lindo que es poder iniciar un proyecto pudiendo decidir uno mismo que tecnologías usar, enfoques y si cabe lo que dice el título: lo hacemos web o desktop?
Precisamente hay una corriente a llevar todo lo posible a la web, los programas de toda la vida, los que siempre corrieron sin problemas en nuestra PC a la web, lo distribuido, lo siempre online. Ahora, creo que si bien es cierto que hacer un aplicación web tiene sus ventajas (muchas por cierto) y sus desventajas, hay que diferenciar varias cosas, para empezar: lo hacemos web o lo hacemos con tecnologías web?, creo que aquí podemos hilar fino y diferenciar un par de cosas. Considero que una aplicación es web cuando hace uso de todo el stack web, es decir, reside en un servidor, se comunica con el cliente mediante peticiones HTTP (generalmente, no siempre), y finalmente interactuamos con ella a traves de un navegador, es más, me traigo la definición de Wikipedia: 
"En la ingeniería de software se denomina aplicación web a aquellas aplicaciones que los usuarios pueden utilizar accediendo a un servidor web a través de Internet o de una intranet mediante un navegador."
Muy bien, ahora si yo realizo una aplicación que trabaja offline exclusivamente, que resida en local por ejemplo sin siquiera necesitar el servidor o el acceso a la red, un simple archivo HTML que el usuario abre con el navegador, es una aplicación web? o solo utiliza tecnologías web tales como HTML, CSS y JavaScript? El ejemplo puede pecar de sencillo, nadie hace (me imagino yo) una aplicación medianamente útil en un simple archivo, pero... porqué debería ser simple? Los navegadores van camino de convertirse en plataformas de desarrollo completas, la "nueva maquina virtual" leí por ahí, por la capacidad de darnos un entorno más o menos controlado y poder abstraernos de la plataforma subyacente, léase SO's, arquitecturas y demás variables.
Esto siempre fue así, pero con todos las novedades que trajo HTML5 (y no digo traerá porque varias ya las tenemos disponibles, sí hoy, en mi navegador y seguramente también en el tuyo) sumados a nuevos enfoques (SPA, MVC client-side, bus de eventos, Thin Server Architecture...  la época de la librería JS solo para eye-candy quedo atrás) tenemos a nuestra disposición toda una serie de cosas que antes estaban reservadas a las aplicaciones desktop como bases de datos locales o el multiproceso en background, o que éstas ni siquiera tenían como el manejo de historial para diferenciar tareas y recordar sus estados, varias de estas características tienen la posibilidad de trabajar completamente offline, junto a otras menos conocidas forman un entorno muy interesante.
Pensándolo bien no suena tan descabellado una aplicación que usara todo esto de manera exclusivamente local sin necesidad de un servidor remoto, solo parte del stack web, perdería la mitad de la gracia pero que es posible seguro.

Y el Cloud?
Es verdad que hay como una "manía" de migrar toda aplicación que se pueda a la web, potenciado por todo el ruido del Cloud que reflota las bondades de toda la vida y algunas nuevas: no solo distribuido, accesible, multidispositivo, sino que los desarrolladores también optimizamos almacenamiento, recursos hardware ahorrando energía, es ¿mas seguro? que tener nuestros datos en local (supuestamente usamos sistemas redundantes y tolerantes a fallos), costos, mantenimiento, todo color de rosas. Aunque muchos de los tópicos solamente son aplicables a los que manejan datacenters y no todos son relevantes para nosotros los desarrolladores de apps, hay que reconocer que son cosas tentadoras de que formen parte de nuestra arquitectura, y de nuevo, suman y nos inclina la balanza. Estas ventajas no son de uso exclusivo de una aplicación full-web, pero hablan el mismo idioma.


Tenemos también los efectos colaterales: la progresiva migración de las aplicaciones a la web y su consiguiente maduración nos familiarizó otro concepto: usabilidad, si bien esta área hace tiempo que existe, en el diseño para la web es donde encuentra su punto álgido, su mayor representación, un tópico que es cada vez más tenido en cuenta y suma puntos para un mejor trabajo. Ahora, alguien recuerda la usabilidad de los programas de escritorio?, sacando el software de cabecera (las aplicaciones con años en el mercado o mucha industria detrás que financie mejoras continuas) el resto deja mucho que desear, nadie se extraña si en un local comercial u oficina hay alguna aplicación de letras verdes sobre fondo negro (no necesariamente de consola, cuidado), si ese programa es portado a la web alguien pensaría por un instante en hacerlo de la misma forma? creo que no. Incluso las empresas de desarrollo que trabajan a menudo con tecnologías web poco a poco incorporan este concepto a sus productos.
Sin duda la mentalidad es otra, incluso esas aplicaciones típicas SAAS, me refiero a los refritos de CRM's de toda clase que surgen como hongos, incluso hasta los más inmaduros tienen una interfaz cuando menos agradable, lo cual ya es mucho decir. No importa si como el alcance es global los players se multiplican y por eso hay que poner cuidado en lo visual, es un paso adelante y los usuarios agradecidos. Me a pasado de tener un par de mejoras estéticas simples, pero cuando vuelves a la interfaz anterior ya las hechas de menos, es hasta gracioso, como esa receta para  un "logo web 2.0", que si bien es una tontera ya nos indica algo, como que hay un diseño 2.0 y otro que no lo es, algo que esperamos que este ahí aunque no sepamos de que se trata.


Entonces?
El tema es que hay aplicaciones que naturalmente tiene sentido que sean web, básicamente todas las que involucren acceder a un recurso compartido que este medianamente centralizado, las redes sociales por ejemplo, los datos tiene que estar en algún lado al que podamos acceder todos, y dejando de lado algunas frikeadas lo más lógico es un prestador de servicio y una serie de  consumidores que accedan a los mismos, igual para los portales de noticias, blogs, buscadores o similares.
Pero por otro lado, y donde es difícil contradecir a los evangelizadores del "todo web", ¿hay aplicaciones que no tenga sentido llevar a la web?, aquí ya no es tán facil la respuesta, y en caso afirmativo, porque no?
Una de la cosas que más se criticaba era la vuelta al "cliente tonto", donde el PC volvía en el tiempo para convertirse en un equipo de escasos recursos que solo se utiliza para acceder a la red, delegando en un servicio remoto la persistencia/procesamiento de los datos, los documentos, archivos, configuraciones y demás, ok, pero veamos un poco más en detalle: esto solo lo podriamos aplicar en el caso de las aplicaciones thin-client, no en términos hardware, sino en términos web, típico portal de la intranet que lista recursos y nos habilita el CRUD, la página web de toda la vida, pero y las verdaderas aplicaciones web?, es decir, las aplicaciones pesadas en el cliente (cuidado, no sean asnos y le llamen fat-clients, es más elegante: rich-client apps), esas que sí hacen un uso extensivo de los recursos hardware que posea el equipo.




Miremos a corto/mediano plazo: en lo inmediato ya tenemos aceleración por hardware de gráficos en el navegador, algunos más avanzados que otros pero es un feature que llegó para quedarse, iniciativas como el WebGL necesitan sí o sí este tipo de recursos para una experiencia medianamente fluida, pero en el futuro inmediato tenemos WebCL, la posibilidad de acelerar el poder de calculo de JavaScript mediante GPU, los demos sobra decir son IMPRESIONANTES, así que tenemos aceleración por harware en gráficos y nitro puro en el lenguaje de programación (no utilizo JavaScript solamente porque tambien esta DART, por ahora  irrelevante pero con Google detrás nunca se sabe). Esto en el campo de potenciar las tecnologías más extendidas, pero no hay que olvidarse de NaCl, otra  propuesta de Google para ejecutar código nativo compilado (C/C++) en una sandbox dentro del navegador, aquí tendríamos uso extensivo de recursos del PC, también los procesos independientes por pestaña o plugin en Chrome van en la linea de aprovechar al máximo el hardware ganando de paso estabilidad en la ejecución, otra tendencia en ascenso.





Si miramos a más largo plazo tenemos WebRTC (no te gustan los acrónimos? dos platos!), básicamente un conjunto de tecnologías disponible para los fabricantes de navegadores que habilita tareas en tiempo real, la típica videoconferencia pero se supone que irán apareciendo cosa más interesantes. Sumo otra tendencia  no tan nueva que dejo para un post completo: la aparición de las arquitecturas SOFEA que calzan en este enfoque, trasladando gran parte del trabajo (no todo) al cliente.



Con todo esto tenemos que la vieja idea de que el tema pasa por el uso o no de la potencia de cálculo local ya pierde fuelle, pero repito: potencia de cálculo local, no digo recursos locales, y aquí es donde creo finalmente llegamos a la línea divisoria: el acceso a los recursos hardware, al sistema de archivos (cada vez menos relevante pero hoy día está ahí) y más importante, el acceso a los periféricos, al USB, al asqueroso puerto serial de toda la vida (nadie se asombre: scanners de algunos años o lectores de tarjetas). Sin ir más lejos te invito a que la próxima vez que vayas al super observes el tipo de conectores que disponen las balanzas.

Algunos apuntes
Me quiero detener en un algunos puntos, primero el hámbito: hay que diferenciar el uso casual del uso laboral, en el primer caso creo que la disyuntiva está ganada, yo mismo si enciendo el PC y no tengo acceso a Internet, no importa que fuese a hacer, ya me entra una apatía indisimulable, el navegador debe ser por lejos la aplicación más utilizada por cualquiera aquí y sobre cualquier plataforma.
Pero en el entorno laboral la cosa cambia, esas aburridas aplicaciones de facturación, gestión de documentos o planillas de calculo hay veces en que es hasta deseable que no tengan conección a Internet, por seguridad o porque sencillamente no la necesitan y así funcionan tan campantes desde hace años, ahora, no les aseguro les quede mucho por delante trabajando desconectados.

Segundo, otra cosa en que quiero profundizar es en lo del acceso al sistema de archivos local, si bien esto se espera se dé cada vez menos, como mencionaba en parte a la tendencia a lo cloud, donde nuestros archivos estarán cada ves en menor medida en nuetro equipo, no oculta el hecho de que los navegadores no están diseñados para manejar recursos locales, simplemente no están hechos para eso, en todo caso el manejo de archivos se limita a la tarea de enviarlos a un servidor externo mediante el botón de upload, no tienen capacidad de acceso decente, en todo caso te dan un explorador básico, permiten abrir un manojo de tipos de archivos, pero más allá de eso tenemos que recurrir a extenciones, addons o plugins (cuidado, esto no es exclusivo de los navegadores, el mismo explorador de archivos de cualquier SO no maneja todos los tipos de ficheros obviamente), pero la idea queda clara: el navegador es para acceder a recursos externos, no locales.

Esto puede cambiar en un futuro no muy lejano, particularmente con la popularización de los smartphones los browsers se ven tentados a incluir cada vez más capacidades de acceso al hardware del equipo solventando así más situaciones, volviéndose más capaces, aún así hay un fenómeno curioso con estos dispositivos: en un principio las aplicaciones funcionaban básicamente en local, no accedían a Internet. Luego con la masificación del WIFI, el 3G, ya con  el acceso a la red como algo trivial, todo parecía migrar otra vez al navegador, pero en cuanto las capacidades hardware comenzaron a aumentar la tendencia se revirtió, la mayor parte del tráfico de Internet hoy se da desde aplicaciones, no desde el navegador, desde software instalado en local, otra vez pantallas de inicio plagadas de íconos multicolores en lugar de marcadores y el arribo de las tiendas de aplicaciones, extraño no?
- no pasemos por alto sin embargo que esto de las appstores no solo crean un nuevo mercado de oportunidades sino que también es un ambiente más controlado por los fabricantes que la web, cuidado con esto -




Creo que el fenómeno se explica de la misma manera, amplificado porque lo móvil tiene el foco de la industria y los cambios de procesan y adoptan de manera mucho más rápida, en mi forma de ver es lo mismo, solo que en los smartphones no hay USB, no hay archivos locales, lo que hay es cámara de fotos, más acelerómetro, más velocímentro, más GPS, más Bluethot, más RDF, y por fin sí: más USB, más  archivos locales, y ahí el fenómeno se repite, el navegador se queda corto y necesita entrar en acción algo una capa más abajo, algo que corra sobre el bare metal, y ahí no hay chance, las aplicaciones nativas llevan delantera.

Por último quiero mencionar el uso del concepto de API's como medio estándar de interactuar los recursos, sean hardware como mencionaba o remotos, cualquier aplicación o sevicio hoy día tiene que tener un  medio estandarizado de comunicarse o exponer los recursos contenidos, incluso era la carencia que más se le reclamaba a Google+  en su salida, y salvando las distancias entre una red social masiva y un software para la oficina, todo esto trae aparejado un concepto: hoy el software totalmente standalone no tiene cabida, a menos que sea algo muy puntual o simple, en su lugar se potencia el ecosistema de aplicaciones, dejando de paso más margen para hacer negocio, de nuevo un concepto que  ya existía pero que en lo web encuentra su mayor expresión: que una extensión para esto, que un módulo extra, que freemium, que límite de consultas gratuitas y la lista sigue.
Las aplicaciones de escritorio claro tienen toda una serie de cosas para comunicarse, algunos implementamos un RMI, otros usaban un socket y escuchaban, alguno tiene embebido un nevagador, de todo, ahora en un ambiente web esperamos desde el vamos una URL y una serie de operaciones REST, SOAP o lo que sea, pero esperamos que estén ahí, sin complicaciones, hoy día el consumo de API's -públicas o no- es moneda corriente, encontrando su máxima expresión en los mashups, otros que cada vez tienen más huecos en el mercado.




Retomando si Web o Desktop no quiero dejar de mencionar un tercero en discordia, el llamado desarrollo híbrido, un enfoque para mi acertadísimo ya que nos da lo mejor de dos mundos. Este término no es tan nuevo, si bien puede aplicarse a cualquier cosa que mezcle un par de tecnologías con foco diferente, aquí lo referenciamos en el caso del desarrollo para desktop que hace uso de tecnologías web. Esto es interesante ya que tiene una serie de ventajas, la primera es utilizar todo el knowhow de desarrollo web volcado al escritorio, no solo es novedoso, hay veces que no tienes tiempo/ganas/recursos de aprender una tecnología según cada SO. La mayor parte de las veces consiste en utilizar un motor de renderizado de HTML + CSS, un intérprete de JavaScript (alguien dijo un navegador sin botones?) envuelto en alguna suerte de wrapper que permita instalarlo como una aplicación ejecutable más y nos de acceso a las funciones de bajo nivel del SO que generalmente no teníamos en el caso del browser puro (tray icon o integración al menú contextual por ejemplo).

Es cierto que te quedas en un "a medias", que no es ni full web ni full desktop, pero prefiero verle el lado positivo, ya que repito te da lo mejor de dos mundos y para nosotros los desarrolladores web tiene un plus no menor: programas para un solo navegador, nada de diferencias según lo que tenga el cliente.
En mi caso puntual (luego de haber ensayado otros enfoques como JWS) estoy probando la plataforma Titanium que peca de estar un poco verde, sobre todo la documentación, otra que promete es QT con el módulo QtWebKit, pero aquí trabajamos con C++ sumándole la idiosincrasia de QT, solo para valientes, quizás más adelante :)

Para ir rematando creo que la discusión es más profunda pero repito me quedo con la impresión de que cada ves tiene menos sentido tener aplicaciones solo desktop, al menos en la empresa donde generalmente son complejas y preferiblemente necesitan intercomunicarse con el mundo exterior (que no con Internet, cuidado aquí), creo que de a poco van a ir evolucionando pero en un enfoque más como los smartphones, aplicaciones locales con las ventaja de estar conectados por default, de tener los recursos más accesibles desde fuera o exponer los propios. Aunque una migración a tecnologías full web no siempre tiene sentido creo integrarán en menor o mayor medida cada vez más servicios externos, y si vamos a encarar un desarrollo, mejor ir previniendo y utilizar la tecnología que está desde el vamos creada para eso. Sobre esto un ejemplo clarísimo: Wunderlist, una aplicación que empieza a sonar con fuerza desarrollada con Titanium y obteniendo de paso la multiplataforma, al ser el resultado un navegador más un wrapper simplifica mucho la distribución en cada SO -móviles incluidos- más el despliegue web unificando más la experiencia/ecosistema.

A pesar de lo mucho que mejoren los navegadores siguen siendo un medio de acceso a contenidos remotos, no locales, por más que puedan editar videos o generar gráficos impresionantes, por esto diferencio que una cosa es para un usuario en su casa (95% neto consumidor y las redes sociales como ejemplos de apps full-web) y otra cosa es el hámbito laboral, donde se genera el contenido, los datos, aquí hay otras exigencias que los navegadores al menos hoy día no cubren, y el desarrollo híbrido puede abrirnos una veta muy interesante.
Volviendo al título del post: "Web o desktop?", creo que podemos complicarla aún un poco más: Web, Desktop o Híbrido?


7 oct 2011

El fin de la era de iGod

No puedo evitar dedicar unas líneas a la muerte de Steve Jobs, en principio pensé en actualizar el anterior post pero la repercusión a sido tal que me hubiese quedado corto. Ayer me desayuno con la noticia nada menos que en el informativo de la mañana, lo cual ya es mucho decir para los medios uruguayos tan alejados del mundo tecnológico, la noticia tuvo una difusión inusitada y hasta me comentaron que canal 5 (canal estatal en Uruguay) transmitió un reporte bastante completo sobre su vida, otros dedicaron el segmento económico a un análisis de Apple. Incluso los periódicos ya terminando el día (observar la hora de las capturas) mantienen la nota en portada y me llama la atención que incluso algunos tan de izquierda como La República lo destaquen, por ejemplo el título de este post está tomado de Observa y creo que lo resume brutalmente todo. Indudablemente la repercusión fue mucha, tanta como pocas veces recuerdo para alguien exclusivamente relacionado al mundo de la tecnología, otro síntoma de como la informática nos es cada vez más familiar, algo del día a día y por extensión, sus protagonistas.








Aunque la muerte no exime de culpa nos obliga a depurar el discurso, prueba de ellos son los comentarios en múltiples foros donde TODOS pasaron de un "muérete puto Jobs!" a un más diplomático "no coincidía con su visión pero reconozco que cambio nuestra forma de pensar y ver la tecnología", en fin, resumiendo mi opinión viene por esa línea, alguien imposible de pasar por alto y del que como todos, mejor quedarse con no diría lo bueno, sí con una forma de pensar basada en tus ideales, buenos o malos pero tuyos al fin.
Un forma de actuar discutible pero bisagra en la electrónica de consumo, no me atrevía a escribir que clave en su evolución, más bien solo a nivel de mercado, pero si razono que la tecnología avanza indisolublemente empujada por las ventas...., y sí, me la juego: hizo historia, aunque claro, la función debe continuar.












Seguramente desde ahora sin el malo la película va a ser un poco más aburrida, para entretenernos mientras tanto tenemos algún comentario inmediato y viral.





5 oct 2011

Abróchese el cinturón por favor

Que el mundo de la tecnología se mueve rápido nadie lo duda, pero el caso de Aardvark (un sitio de preguntas y respuestas) es  llamativo, tenía pendiente hace tiempo comentar que en su blog anunciaron muy alegres un Aardvark joins Google! para luego, tan solo 6 mese después, colocar un Goodbye Aardvark motivado por  el cierre de Google Labs.


Aardvark joins Google!



Goodbye Aardvark


Si lo junto con la ocasión que en mi trabajo ya contaba con luz verde para adquirir GWT Designer para enterarme al día siguiente que Google adquiría la empresa  que lo desarrollaba y pasaba a ser gratuito junto a todo el set de herramientas, la rapidez en que me contestaron una pregunta en StackOverflow (la realizé a las  20:27, me resolvieron la duda a las 20:46) y que no he comenzado a experimentar con PhoneGap cuando me despacho que Adobe adquirió la empresa cediendo el producto a la fundación Apache que sin demoras ya le está buscando nuevo nombre...no hay vuelta, esto se mueve muuuuy rápido.



15 sept 2011

GWT: arrays como argumentos desde Java hacia JavaScript mediante JSNI


Todo un tema el intercambios de datos entre los métodos en JavaScript nativo escritos con JSNI y nuestro código Java, básicamente tenemos solo unos pocos tipos ya que aparentemente esta pensado para intercambiar argumentos simples. Repasemos la documentación a ver que tenemos:


Los más prácticos son los básicos: String, boolean y numéricos, los demás requieren de sintaxis especial o son valores opacos que no se prestan demasiado a la manipulación, pero atentos, tenemos a la vista la solución a nuestro problema: los valores de tipo JavaScriptObject.
La documentación da lugar a confusión, ya que aparentemente solo los podríamos usar como valores de retorno de otro método JSNI, pero si revisamos el Javadoc de los tipos de datos disponibles para manejar JSON, vemos que tanto JSONArray como JSONObject poseen el método getJavaScriptObject que tiene como tipo de retorno JavaScriptObject, precisamente lo que podemos pasar como argumento a nuestro código JSNI. Bien, con esto en mente y como muy probablemente utilicemos JSON para el paso de valores es que llegamos al siguiente ejemplo:

package test.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONParser;

public class TestJSNI implements EntryPoint {

 public void onModuleLoad() {

  // creamos un JSONArray de prueba
  JSONArray jsonArray = JSONParser.parseLenient("['rojo','negro','verde']").isArray();
  
  // pasamos como ragumento su JavaScriptObject
  parseArray(jsonArray.getJavaScriptObject());

 }
 
  
  
 private native void parseArray(JavaScriptObject myArray) /*-{

  // mostramos el valor de la primer posición 
  alert(myArray[0]);

 }-*/; 
 
}


Cortito y simple, creamos un JSONArray (incluir en el XML de módulo la línea <inherits name="com.google.gwt.json.JSON" />) para probar y luego lo utilizamos para llamar al método JSNI, el truco como mencionaba es pasar como argumento su objeto JavaScriptObject subyacente y especificar también de este tipo el argumento de nuestro método nativo. Muy útil, seguro una excelente manera para el pasaje de datos con mucha más flexibilidad.



13 sept 2011

GWT: incluir librerías JavaScript externas


Si bien GWT nos proporciona una cantidad muy interesante de métodos para manipular el DOM directamente desde Java, hay ocasiones que es mucho más práctico incluir JavaScript directamente a través de JSNI, si bien no es aconsejable ya que el código incluido no es verificado ni optimizado por el compilador.
Por otra parte, hay ahí fuera miles de librerías y utilidades súper prácticas que es imposible pasar por alto, algunas insustituibles más teniendo en cuenta que GWT tiene serias carencias en algunas áreas, los efectos son un ejemplo, salvo un manojo de buenas herramientas portadas a Java el abanico es escaso, además no siempre tenemos un equivalente a la altura, varias veces los ports terminan siendo más voluminosos que la solución original y a veces con menos posibilidades.
Todo esto nos lleva a más que escribir unas pocas líneas a través de JSNI vernos tentados a incluir librerías externas completas para tener funcionalidades extra en nuestra aplicación, el tema es como lo hacemos.

Lo más básico es escribir un tag link en nuestro archivo home de HTML referenciando el código externo, opcion esta desaconsejada, no solo perdemos el control ya que confiamos en un recurso externo que no sabemos si invariablemente va a estar cuando hagamos el despliegue (con GWT también se hacen pequeños módulos que podemos distribuir independientemente, no solo apps completas), si no que delegamos en el browser las tareas de control del cache y manejo de errores, estamos jugando con fuego se podría decir.
Lo otro es otra incluirlo en nuestro archivo XML de proyecto utilizando la Automatic Resource Inclusion para incluir código externo de una manera más elaborada, pero en este caso siempre lo incluirá más allá de que finalmente lo necesitemos o no.

Precisamente viendo como podemos hacer todo esto de una manera un poco más elegante es que llegamos a la dimensión desconocida de la interfaz Client Bundle para el manejo de recursos externos. Una de las ventajas que ya nos mencionan es que los recursos incluidos a través de ésta pasan a la categoría de recursos cacheados para siempre (repito la importancia  de tener el control de que se cachea y como), lo cual es muy conveniente para recursos que no cambian con el tiempo, los más obvios y por tanto conocidos son imágenes y archivos CSS. Estos cuentan con soporte exaustivo, desde los prácticos sprites de imágenes a cosas más rebuscadas como soporte RTL, pero... y los archivos JS?
En el caso de archivos JavaScript la cosa es un poco acotada, de los tipos disponibles utilizamos el TextResource, que engloba los recursos de "static text content", una linda manera de referirse al JS de toda la vida. 
Otra cosa muy bienvenida que tenemos desde la release 2.4 es la clase ScriptInjector que nos permite crear un tag SCRIPT sin tener que manejar directamente el DOM lo cual es propenso a errores (por ejemplo si nos salteáramos un paso como incluir el tag sin definir el tipo o similares puede fallar), incluso tenemos algunos métodos extra como definir un setCallback en caso de archivos cargados desde una URL, básico pero nada mal.

Comencemos con un ejemplo así vemos como usar esta técnica que seguro nos ayuda a perder el miedo a incluir recursos externos o hacerlo de una manera más consistente, en este caso estaba tratando de utilizar los features de HTML5 Storage, pero en caso de que esta funcionalidad no estuvieran disponible en el cliente quería ofrecer un método alternativo de almacenar datos en el browser, si bien hay excelentes librerías que chequean exhaustivamente el navegador para ver que tenemos disponible (desde almacenamiento Flash hasta características exclusivas de IE entre otras) me decidí por lo simple y utilicé una vieja amiga como es TaffyDB, una muy buena opción para almacenar info en el cliente con algunos métodos muy útiles: contar, ordenar, filtros y algunas cosillas más.


estructura del ejemplo


Allá vamos entonces, proyecto nuevo en Eclipse y creamos un directorio para almacenar Taffy, en este caso bajo el package client/lib, utilizamos la versión minificada de producción taffy-min.js, menos de 20kb... un lujo.
Ahora lo interesante, para incluirla debemos definir una interface que extienda de ClientBundle y tenga la ruta a la librería como argumento de la anotación @Source y un método para referenciarla por el tipo, en mi caso la llame TaffyDBBundle quedando de la siguiente manera:

package testTaffy.client;

import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.TextResource;

public interface TaffyDBBundle extends ClientBundle {
 @Source("lib/taffy-min.js")
 TextResource taffy();
}

Es bastante descriptiva, como mencioné especificamos la ruta al archivo en @Source y definimos un método para accederla del tipo TextResource, en mi caso taffy();
Ahora en el onModuleLoad vamos integrar todo usando el ScriptInjector, aquí tenemos dos opciones: ScriptInjector.fromString y ScriptInjector.fromUrl (no confundir el tipo de retorno con el nombre del método) en este caso como ya tenemos incluida la librería utilizaremos fromString, que recibe como argumento el contenido de nuestro archivo JS, a este lo accedemos mediante el método getText() de la interfaz TextResource que ya implementamos, quedando así:

package test.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.ScriptInjector;

public class TestDB implements EntryPoint {

 public void onModuleLoad() {

  TaffyDBBundle taffy = GWT.create(TaffyDBBundle.class);
  JavaScriptObject result = ScriptInjector.fromString(taffy.taffy().getText()).inject();
  
 }
 
}

Primero creamos nuestro recurso a través de GWT.create quedando del tipo de nuestra interfaz (TaffyDBBundle), luego utilizamos el ScriptInjector.fromString y le pasamos como argumento el llamado a nuestra instancia mediante el método taffy() (podemos llamarlo como queramos) y luego su contenido mediante .getText(), finalmente incluimos el script al DOM mediante .inject();
Para verificar vamos a crear un par de métodos mediante JSNI para verificar que está funcionando, en este caso definimos una base de datos e ingresamos algunos registros, luego verificamos consultando cuantos cumplen con determinada condición:

    private native void createDB() /*-{

  $wnd.sobrinos = TAFFY([ {"id":1,"user":"Hugo","edad":"12"},
        {"id":2,"user":"Paco","edad":"12"},
        {"id":3,"user":"Luis","edad":"12"}  
                        ]);

 }-*/;

 private native void testDB() /*-{

  alert($wnd.sobrinos({"edad":"12"}).count());

 }-*/;


vale recordar que en GWT siempre es conveniente referirse a las variable a través de el objeto $wnd (window) para evitar problemas, ahora juntamos todo:
package testTaffy.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.ScriptInjector;

/**
 * Entry point classes define onModuleLoad().
 */
public class TestTaffyDB implements EntryPoint {

 public void onModuleLoad() {

  TaffyDBBundle taffy = GWT.create(TaffyDBBundle.class);
  JavaScriptObject result = ScriptInjector.fromString(taffy.taffy().getText()).inject();
  
  if (null != result) {
   createDB();
   testDB();
  }
 }

 private native void createDB() /*-{

  $wnd.sobrinos = TAFFY([ {"id":1,"user":"Hugo","edad":"12"},
        {"id":2,"user":"Paco","edad":"12"},
        {"id":3,"user":"Luis","edad":"12"}  
                        ]);

 }-*/;

 private native void testDB() /*-{

  alert($wnd.sobrinos({"edad":"12"}).count());

 }-*/;
}


Utilizo un JavaScriptObject result para verificar que el tag se creo correctamente, al correrlo obtenemos un mensaje de alerta con 3, efectivamente está funcionando ya que hay 3 usuarios cargados en Taffy con el campo edad igual a 12, bastante accesible, como mencionaba hay más métodos útiles disponibles como setCallback al cargar recursos por URL o setWindow para especificar en que ventana queremos colocar el tag SCRIPT, simple y consistente.

Por último juro que busqué que edad tienen los sobrinos del Pato Donald para el ejemplo pero no encontré nada :)



2 sept 2011

Jornadas JIAP 2011

Un poco tarde escribo para comentar sobre las jornadas JIAP 2011 organizadas por AsIAP que fueron del 17 al 19 de agosto en el Centro de Conferencias de la Intendencia de Montevideo.
Según AsIAP su visión es "Por un Uruguay líder en el mundo en Tecnologías de la Información y las Comunicaciones", con semejante lema no podía quedarme fuera de este evento, la consigna esta vez fué "SEGURIDAD: Desafíos de hoy", no es mi tema favorito pero había varias charlas interesantes, asi que haya fuí cámara en mano a ver que que tal.

Este evento y varios que he concurrido tienen un sabor local impresionante, tanto que se da por sentado que todos sabemos donde esta el Centro de Conferencias de la Intendencia de Montevideo, de ahí la ausencia de cartelería tanto en la entrada como dentro del recinto así que pasamos por Informes y allá vamos. El lugar lo encontré un poco corto de espacio, bien para acceder a las salas de conferencia pero chico para montar una serie de stands, de ahí que había que serpentear entre ellos para acceder a las salas, el salon Rojo por ejemplo estaba en un corredor lateral medio escondido, nada grave, solo esquivar el público y no detenerse demasiado frente a los expositores.


Sobre estos solo decir que no había mucho más que cartelería y algun asesor, nada demasiado llamativo, solo uno se la jugó a traer una pizarra táctil gigante cargando Windows 7, estuve toqueteando un poco y respondía bien, lamentablemente no pude sacar fotos pero resultó interesante, me imagino que debe dar buenas posibilidades en enseñanza o algo similar.
Los demás stands solo lo dicho, empresas ya consolidadas (Samsung, Eset,Tilsor,Urudata) y algunas pocas nuevas caras, de nuevo que el recorrido no ayudaba demasiado, incluso el stand de Antel estaba en un lateral medio escondido, quizás el hall de la Intendencia hubiese sido mas cómodo, está claro que se armó el recorrido como se pudo, por ejemplo si a los chicos de la UTU si se les acercaba demasiada gente trancaban un poco el paso.

Sobre esto quiero destacar que tenían los proyectos mas interesantes: un pc refrigerado con vaselina líquida, algo como una cámara que detectaba la posición de un puntero, codigos QR, bastante interesante. Por curiosidad toqué la pecera que contenía el motherboard del pc refrigerado con vaselina y lo noté bastante caliente, al consultar me dijeron que la temperatura aumentaba solo hasta cierto punto, espero que sea como máximo el que tenía en ese momento, sino al fin de la jornada se podrían hacer tortas fritas en la pecera, también tenía el ventilador, supongo que para  ayudar a que circule la vaselina sobre el micro pero creí se podría hacer por convección eliminando piezas mecánicas, igual me gustó ya que estaba novedoso.



Sobre las charlas preferí asistir a las de "Televisión digital interactiva: Situación en la región",
y por último "Implantación de DW Open Source" a la cual pertenecen las fotos que acompañan esta entrada, dejo el temario completo aquí con los slides y filmaciones de las charlas.

Al respecto de estas solo puedo decir que fueron muy flechadas hacia productos, por ejemplo las de "Sistemas de telefonía IP..." básicamente era como Conatel resolvió SU arquitectura básica para SU sistema VoIP, pero sin entrar en demasiados detalles, mucho menos técnicos.
Es como si te dijera que para aumentar la potencia de un auto le pongas un motor más grande, pero no te aclare que tipo de motor, o como ponerlo, cosas así, otras casi eran demos de productos ("Tecnología CISCO en videovigilancia", "Printing Solutions Samsung") y esta es hasta graciosa: "Construyendo la interoperabilidad por medio de estándares", nada raro solo que venía de parte de MICROSOFT, me imagino que serían estándares de facto, similar a la cartelería de Oracle que abogaba por la innovación, un poco desentonado con los últimas demandas impuestas contra todos los que usen Java y demás, solo marketing.



La de televisión digital aunque interesante me recordó que nuevamente vamos a ser tomadores natos de tecnología, esta vez de los brasileños (el middleware Ginga es desarrollado por ellos), cuestión de mercados. Al escuchar de donde procedía solo espere que no usara LUA como lenguaje de scripting, pero sí, Ginga-NCL lo utiliza ampliamente, aclaro que no es que el lenguaje me parezca malo, solo que al ser otro desarrollo brasileño me la ví venir.

La de Conatel mediana (no mala tampoco) como mencioné y la de DataWarehouse Open Source para ASSE bastante más interesante, contando un poco sobre arquitectura, productos seleccionados, problemas encontrados (mencionaron más de 19 departamentos, gente registrada que todavía no nació, otros de más de 120 años), adjunto algunas fotos pero en los PDF's de las charlas lo puden ver mucho mejor. Como conclusión un evento bastante ameno, mejorable como todo pero interesante, y al ser de carácter genérico mas allá de la consigna sobre seguridad es bien heterogéneo, soluciones privativas, otras Open Source, poco ruido por lo "Cloud" afortunadamente y lo fundamental y más importante, promotoras lindas que amenizen la jornada, como para no tirar un par de fotitos.








29 ago 2011

Java vs Ruby


Este post es absolutamente viral así que no esperen demasiados fundamentos técnicos, el tema es que lo leo y aún no lo creo, están realizando el llamado a presentar charlas para la RubyConf Uruguay 2011 y en el proceso te disparan "charlas inspiradoras que demuestren por qué ruby y el ecosistema circundante son una mejor alternativa que otras tecnologías (*ejem* Java *ejem*)." WTF??, y estos que se traen, vamos, no se porque me gasto en enojarme con estos trolls, pero es que no entiendo a que viene esto, yo mismo dije que me gustaban las comparaciones de esta herramienta vs otra, pero un palo así gratuito es que no lo veo.


Esta tendencia de atacar a Java desde la comunidad Ruby es que ese torna molesta a más no poder, es como un capricho impertinente, como viene con ideas nuevas todo lo otro esta desfasado, pasado de moda, algo que no vale la pena invertir tiempo ni esfurzo en usar o aprender.
Es verdad que Rails (que no es lo mismo) puso sobre la mesa una nueva manera de ver las cosa en esto del desarrollo web, no por nada tenemos frameworks tanto en Java (Groovy con Grails principalmente pero hay otros ) como en mi querido PHP (CakePHP creo el más representativo) toman esas ideas y la hacercan a estos lenguajes u otros, pero el universo es acotadísimo, es que si te sales del desarrollo web difícilmente alguien te mencione Ruby, todo lo contrario a por ejemplo Python, doy fé de que tengo varios compañeros  que hace años trabajan haciendo scripts de servidores y jamás hicieron una web, es más, esa es una de las cosas que me enamoraron de Python, la capacidad de ser multiuso, lo usamos para todo y el abanico de áreas donde se aplica es diverso a más no poder, unos para web con Django y otros en aplicaciones que ni siquiera tienen interfaz gráfica, y no me recuerden que PHP no es solo para web porque existe PHP-GTK, no estoy hablando de bindings aquí, me refiero a sus hambientes naturales.

Esta actitud la veo desenfocada, la gente que recién entra en esto puede llegar a tener la mala idea de que solo hay una forma cool de hacer las cosas, no se, es como que tienen que aderezar la herramienta con un toque de ideología fundamentalista, y si parece que exagero al menos no me pueden discutir que esto de enfrentarse al resto de soluciones en Ruby ya parece hábito, de puro necio me traigo un par de videos con esa onda Apple vs Microsoft y demás.







En fin, no voy a mostrar músculo pero es que no puedo evitarlo, solo hablar del mundo SOA, sobre las más de 300 JSRs, ya sé que cantidad nunca equivale a calidad pero demuestra que hay mucha gente detras de esto, mucha industria empujando este muerto a pesar de los palos en la rueda de Oracle, solo menciono que con seguridad el banco a traves del cual cobras el sueldo, la agencia de pagos donde lo gastas o el ISP que te permite leer estas líneas tienen en toda o parte de su infraestructra algunas líneas de Java, y te aseguro que no son pocas, dudo que se pueda decir lo mismo de Ruby.
Y sigo, existe algo como esa gran desconocido que es JWS en Ruby?, si aterrizamos a desktop el desarrollo multiplataforma real, no olvidemos tampoco que las apps de Android se desarrollan básicamente en Java, o las demás aplicaciones de peso pesado, solo aceptaría que viniese alguien de .NET o los dinosaurios de SAP a generar controversia, pero seguro que no un fanboy de Ruby, en fin, para el que solo tiene un martillo todo son clavos, me quedo con una frase que leí y por lo cual Ruby on Rails y esa magia, perdón: "convención por sobre configuración" aunque útil bien usada, me genera un poco de rechazo:

- No sabes lo que estás haciendo, pero funciona.
- No sabes lo que estás haciendo, y además no funciona.

No es que en Java no me haya perdido más de una vez, pero por lo menos aplica aquello de "en Java es difícil hacer las cosas mal, en Python es fácil hacerlas bien", creo que es como dice mi compañero, es fácil pegarle a Java, no tanto a Python, más si hablamos de web donde las carencias son muchas y el desarrollo generalmente pesado, lo reconozco ya que no por nada existe GWT, que si bien es fabuloso nace para facilitar la transición de desarrolladores Java a esto de la web 2.0 (cliché feo si los hay, pero nos entendemos) o por lo menos la gran mayoría de sus usuarios así lo usan.
Es que ni siquiera se comparan, el que desarrolla web difícilmente opte por Java, y el que desarrolla con Java seguramente no se meta a crear sitios, hay alternativas más baratas, simples, rápidas y creativas de hacer las cosas, y acepto que Ruby es una de las mejores, pero marearse con los aplausos creo es demasiado.

Bueno, hasta aquí llegue, si buscan fundamentos más técnicos adjunto un par de enlaces interesantes, para lo viral ya tenemos este post, ahora me es más fácil tomármelo con humor (mentira, sigo ofuscado, pero soy tolerante).





Steve Jobs y mis sensaciones encontradas

Los que me conocen saben que me caen bastante mal los productos de Apple, su política y sobre todo la personalidad de Steve Jobs, un personaje de esos que es preferible no tener como jefe, es más, me parece patético como los desarrolladores aceptan esas condiciones lamentables a cambio de poder estar en la App Store, si si, ya lo sé, si tienes demasiados principios no se llega muy lejos en esto de la venta del software, si no me crees pregúntale a mi jefe que vendió un CRM que solo existía en el papel, por eso prefiero estar podríamos decirle en el lado ¿bueno, romántico?... no, mejor llamarle el lado oscuro de la fuerza, picando código, investigando, atento a ese cambio de versión que deja obsoleto todo lo anterior y te obliga a releer de nuevo la documentación, más difícil sí, pero mas prometedor también, imposible no dejarse atrapar, lejos de los departamentos de venta y soporte al cliente (ufffff!!, perdón, me dejé llevar).

Volviendo al tema del post, es increíble con internet lo fácil que es formar una opinión de alguien sin siquiera conocerle personalmente, mejor dicho siempre fué fácil (si no no existiría la política) y hasta natural, pero hoy tenemos info hasta de sobra, así que las posibilidades se multiplican, por eso en el caso de Jobs valoro posts como este en que opinan de primera mano, valioso para reafirmar mis convicciones de que el tipo apesta.

Ahora con la noticia de que renuncia a su puesto de CEO en Apple, y sin creerme aún los comentarios ridículos (ej:  "en la palabra genio deberia ir su foto al lado en el diccionario", otro: "estoy al borde de las lagrimas, espero que se mantenga la compañía #PapaJobs"  y este ya me superó: "Tim no decepciones a tu amigo Steve, que el dinero y el poder no te cieguen que tu mirada sea al futuro, aun tenemos la dicha de tenerlo a nuestro lado y eso ya es bastante. Que Dios te bendiga Steve Jobs"), como hay gente tan hueca que habla del tipo como si perdieran un familiar o peor?, en fin, me puse a buscar un poco de información más detallada, escuchar una charla o un discurso a ver que tanto puede decir, y aquí es donde me cambia un poco la idea que me había hecho del fulano, solo un poco quizás pero lo suficiente para volver a recordar que realmente no sabemos nada de nadie, ya sé, demasiada filosofía o la madrugada me está afectando, por eso les dejo este video y solo comento que hacía tiempo no prestaba tanta atención a un discurso.









26 ago 2011

Doodle Día de la Independencia de Uruguay



Imposible no mencionar el Doodle del 25  de Agosto celebrando el día de la Declaratoria de la Independencia uruguaya, está compuesto por un par de flores de Ceibo y un cintillo con el nombre del país, todo con un aire medio vintage.
En el noticiario mencionaron que millones se habían enterado de nuestra celebración gracias a Google, cosa que dudo ya que solo aparecía en la versión uruguaya del buscador, tanto en .ar como .br no estaba, me faltó comprobar si en la .com sucedía lo mismo.





Otra cosa es que al clickearla el primer resultado que arroja es del sitio www.redargentina.com, una pena si lo que queremos es que no nos confundan con los argentinos pero bueno, todo no se puede pedir.




Por último un comentario, este tipo de tonterías son las que marcan diferencia en la forma de pensar de las empresas, no en vano están donde están.


23 ago 2011

Slide Secrets of the GWT

Comparto un slide diferente sobre GWT de los muchos que hay ya que toca temas que otros más básicos pasan por alto, aunque un poco largo (son 80+) solo es una muestra de algunos tópicos interesantes así que imagínense el mundo que hay detrás de esta herramienta, ya voy más de un año y todos los días aprendo algo nuevo, para no aburrirse.


18 ago 2011

GWT Command para ejecución secuencial

Con GWT hay que estar atentos al hecho de que la programación esta dirigida por eventos y de manera totalmente asíncrona, por lo que no solo debemos basarnos en ellos para hacer fluir la aplicación sino que tampoco podemos fiarnos de que la lógica que necesitemos haya sido correctamente implementada por las sentencias anteriores.

Precisamente esto mismo me paso al realizar una serie de métodos secuenciales: la lógica necesaria para pasar al siguiente método aún no estaba disponible, por lo que al avanzar la cadena de ejecución fallaba miserablemente ya que no verificaba que un paso estuviera totalmente finalizado para avanzar al siguiente.
Una posible solución es que al ejecutar un método si todo esta correcto invoquemos el próximo, pero no queda muy prolijo que digamos, fácilmente podemos tener una ensalada de llamadas por doquier, ni hablar si queremos cambiar el flujo de la aplicación, suerte en pila.

Una solución que da buenos resultados es utilizar los Comandos, con ellos es posible encapsular determinada lógica y luego ejecutarla a demanda, si a esto lo aderezamos con iteradores y ArrayLists, la cosa empieza a tomar otro color, veamos un ejemplo completo y luego lo diseccionamos:

package com.myPackage.client;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Window;

public class DemoComandos {

	private List<Command> commandsStack = new ArrayList<Command>();
	private Command command_01, command_02;
	private Iterator<Command> cmdIterator;


	public Comandos(){
		loadCommandsStack();
		run();
	}
	

	private void loadCommandsStack(){

		command_01 = new Command() {
			@Override
			public void execute() {
				
				boolean ok_01 = true;
				if(ok_01){
					run();
				}
				else{
					Window.alert("error comando 1");
				}
				
			}
		};

		
		command_02 = new Command() {
			@Override
			public void execute() {

				boolean ok_02 = false;

				if(ok_02){
					run();
				}
				else{
					Window.alert("error comando 2");
				}
				
			}
		};
		
		
		commandsStack.add(command_01);
		commandsStack.add(command_02);
		cmdIterator = commandsStack.iterator();
	}
	
	
	private void run(){
		
		if(!cmdIterator.hasNext()){
			Window.alert("no hay mas comandos");
		}
		else{
			cmdIterator.next().execute();
		}
	}
	
}


Veamos por partes, la idea es encapsular nuestra lógica en comandos y agrupar estos en una lista, para mantenerlo simple dentro de la ejecución de estos no llamaremos métodos externos pero es lo más recomendable para separar la lógica de las sentencias y tenerlas definidas aparte.
Al crear una lista de comandos no solo unificamos ya que ahora todos son del mismo tipo, sino que podemos verificar que un paso esta completo antes de llamar al siguiente, pera hacerlo dinámicamente creamos un iterador que sea invocado por los propios métodos si estos finalizan correctamente, en caso contrario la aplicación se detiene ya que cortamos la cadena de llamadas. Ahora en detalle:

	private List<Command> commandsStack = new ArrayList<Command>();
	private Command command_01, command_02;
	private Iterator<Command> cmdIterator;

aquí creamos la lista que contendrá nuestros comandos, la definimos del tipo ArrayList para manejarlos mejor, luego creamos los comandos y por último definimos un iterador, no lo inicializaremos hasta tener cargados los comandos en la lista.

public Comandos(){
        loadCommandsStack();
        run();
    }


Por sencillez ejecuto en el constructor el método para la carga de los comandos, solo agrupa esta operación para mantenerlo conciso pero podemos colocarlo en cualquier lado, lo hacemos así:


command_01 = new Command() {

	@Override
	public void execute() {
		// aquí ejecutamos la rutina o llamamos a un método aparte
		// si todo es correcto invocamos el método run() y continuamos

			boolean ok_01 = true; // simulamos que todo fué Ok
			if(ok_01){
			    run();
			}
			else{
			    // en caso contrario la aplicación se detiene
			    Window.alert("error comando 1");
			}
				
		}
	};


Como mencionaba para agregarle flexibilidad a la ejecución de la pila de llamadas agregamos los comandos a un ArrayList e inicializamos el iterador:

commandsStack.add(command_01);
commandsStack.add(command_02);
cmdIterator = commandsStack.iterator();


Ahora lo interesante, el iterador posee un método hasNext() que nos indica si hay un comando próximo cargado a ejecutar, si no es el caso quiere decir que completamos la pila de llamadas, este lo encapsulamos en un método run(), al llamarlo por primera vez dispara la secuencia de ejecución, luego esta es mantenida por los resultados de los siguientes métodos, es decir, si estos se efectuan correctamente invocan sucesivamente run() continuando la secuencia, si ocurre un error la cedena de llamadas se detiene y si no todo concluye correctamente.


private void run(){
	
    if(!cmdIterator.hasNext()){
        Window.alert("no hay mas comandos");
    }
    else{
        cmdIterator.next().execute();
    }
}

Inclusive podemos tener una clase maestra que contenga un metodo run()  general y clases inferiores más específicas con la misma estructura, éstas al concluir sus comandos locales si tienen una referencia a la clase maestra pueden invocar al run() general en vez del local y continuar la pila de llamadas a otras clases inferiores.

En mi caso utilizé este planteo con una clase maestra llamada Init que invoca varias clases menores que realizan tareas específicas como chequear la conexión, crear la GUI, obtener JavaScript onDemand u otros, cada una tiene una referencia a Init que luego de realizar todos sus comandos ejecutan Init.run() y pasan la posta a la pila de llamadas contenidas en otra clase.Otra ventaja que vuelvo a mencionar es la facilidad para cambiar el flujo de la aplicación, basta con comentar el commandsStack.add(myCommand) que queramos y todo seguirá fluyendo normalmente salteándose ese paso, creo que solo aporta ventajas así que vale la pena probarlo.