miércoles, 12 de diciembre de 2012

Objective-C se moderniza: subscripting

Objective-C es un lenguaje bastante distinto en su sintaxis a otros lenguajes de programación como ser C#, Java o Ruby. Como tal, es un lenguaje que a primer golpe de vista parece dificil de entender.

Además, es un lenguaje que por sus características, es más "verbose" que los demás, y esto a su vez puede hacer que parezca que hay que escribir mucho código.

Esta última característica no es siempre mala. Por ejemplo, en Java (o cualquier otro lenguaje que no incluya los nombres de los parámetros en el nombre del método), si uno no conoce la API en detalle, y ve este código:
String result = "some sample string".replace( 'a', 's' );
puede no quedarle claro si se va a remplazar la 'a' por la 's' o la 's' por la 'a'. En Objective-C, esto se escribe así:
NSString *result = [@"some sample string" stringByReplacingOccurrencesOfString:@"a" withString:@"s"];
Es verdad que es mucho más código, pero el mismo se entiende sin necesidad de conocer la API ni de ir a la documentación.

Nota: es un ejemplo "tonto", pero se complica si se tienen funciones con varios parámetros.

Sin embargo, hay casos en que tanto código puede resultar innecesario. Por ejemplo, cuando se quiere acceder a un elemento de un array:
id item = [someArray objectAtIndex:index];
o peor, cuando se quiere almacenar un elemento en un array (mutable):
[someMutableArray insertObject:item atIndex:index];
Por suerte, Objective-C es un lenguaje en evolución, y hay varias cosas que están cambiando. Ya hablamos de Automatic Reference Counting y de Blocks, funcionalidades que se agregaron recientemente al lenguaje/compilador, pero también por ejemplo literales para arrays, diccionarios o números (de lo que hablaré en algún otro momento).

A partir de Xcode 4.4, el acceso a los elementos de un array, tanto para leer como para modificar, se puede hacer de forma más concisa:
id item = someArray[index];
someMutableArray[index] = item;
Esto también aplica para los diccionarios, que se puede acceder por clave por ejemplo con:
id item = someDictionary[key];
someMutableDictionary[key] = item;
Pueden ver más información en la documentación del LLVM al respecto.

lunes, 3 de diciembre de 2012

Los robots nos van a dejar sin trabajo?

Estuve viendo esta charla de TED que me pareció interesante, y la iba a "tuitear" pero no estoy del todo de acuerdo con las conclusiones, así que me pareció mejor comentarla acá...


En la charla, Andrew McAfee se hace esta pregunta, y llega a la conclusión de que sí, en gran medida vamos a ser reemplazados por robots.

Uno de los ejemplos que pone también me parece interesante. Dice que en Estados Unidos, hay más de 3 millones de camioneros, que potencialmente van a perder el trabajo cuando se perfeccionen los vehículos autónomos. No se cuanto dará el número si se le suman los taxistas, repartidores, conductores a ambulancias, etc.

Es verdad que ahora puede parecer ciencia ficción, pero la tecnología va a llegar en 5, 10 o 15 años, y a las empresas les va a servir más que contratar seres humanos, porque va a ser mucho más barato.

McAfee dice ser optimista, que a pesar de que los robots nos van a dejar sin trabajo, la tecnología va a resolver los problemas, y que nosotros vamos a estar más libres para hacer otras cosas.

Yo también soy optimista con respecto a la tecnología, pero en el largo plazo. Creo que si la perdida de trabajo se da de golpe van a haber crisis muy importantes, que no van a ser despreciables como parece dar a entender el autor de la charla.

Lo que una cosa sí estamos de acuerdo: we ain't seen nothing yet...

jueves, 1 de noviembre de 2012

Script Bash para sincronizar cambios entre repositorios SVN

Creo que es algo bastente común, cuando se está trabajando con distintas versiones del mismo producto, tener que sincronizar cambios de una versión a otra.

En particular en Artech tenemos el código en un repositorio SVN, y en este momento tengo cuatro versiones del cliente de iOS en las que estoy trabajando:
  • la versión prácticamente cerrada del Upgrade 2 de la Evolution 2
  • la rama de upgrades (Upgrade 3 y posteriores) de la Evolution 2
  • la versión oficial de Tilo (nombre código de la próxima versión de GeneXus)
  •  una versión inestable de Tilo donde estoy haciendo cambios que no quiero hacer commit porque están "atados con alambre"
Llevar los cambios de una versión a otra puede ser bastante complicado, si se trata de un fuente que tiene cambios en más de una versión. Es un proceso bastante manual.

Para facilitar este proceso hice un script Bash que se fija los cambios en la versión de origen y muestra el comparador (File Merge, viene con Xcode) para los archivos modificados, o copia directamente los archivos que son nuevos.

Estoy en fase de beta-test... para las primeras comparaciones que hice me funcionó.

Si a alguien le sirve, quedó disponible en GitHub. Lo único que hay que cambiar es la función pathForName, el mapeo entre los nombres de las versiones y los directorios.

Aclaro que no soy experto en Bash ni mucho menos, así que seguramente haya muchas mejoras para hacerle. Cualquier aporte es bienvenido.

Por último, repetir que no está muy probado, así que quien lo quiera usar, hágalo bajo su propio riesgo. El soporte que le de dependerá del tiempo que pueda dedicarle. En principio, los cambios que le haga van a ser para poder usarlo yo de forma razonable en el día a día.

jueves, 4 de octubre de 2012

Encuentro #GX22

Los pasados días, del 1 al 3 de octubre, se llevó a cabo como todos los años el Encuentro GeneXus, esta vez en su edición número 22.

Este año no me tocó dar charla, así que fue más tranquilo :)

Como siempre un lujo la organización. Viéndolo desde adentro se ve que hay mucha gente que trabaja mucho para que todo funcione y salga como tiene que salir, así que mis felicitaciones a todos los involucrados.

Pero vamos a las charlas...

Lunes

GeneXus y el contexto tecnológico

En su charla sobre GeneXus, Nicolás Jodal contó algunas de las cosas que tenemos en la Evolution 2, contó sobre las aplicaciones que (conocemos que) se hicieron con el generador de Smart Devices, y que sumadas tienen más de 250.000 descargas de las respectivas tiendas de aplicaciones.

Luego contó alguna cosa de lo que vamos a tener en GeneXus Tilo, entre ellas el generador Windows 8. Para esta parte de la charla invitó a Eduardo Mangarelli de Microsoft que mostró una tableta con Windows 8 y algunas aplicaciones, y luego a Alejandro Silva del equipo de desarrollo que mostró las cosas que se pueden hacer con el generador para esta plataforma.

GeneXus X Evolution 2

Armin Bachman y Franklin Buitron presentaron la versión Evolution 2 de GeneXus, que se liberó el pasado mes de marzo, y contaron varias de las funcionalidades y ventajas que tiene.

Fue un repaso completo de las mejoras de la versión, y por lo tanto no dio para profundizar en cada tema. La ventaja que al ser una de las primeras charlas del evento, daba la posibilidad al que le interesara de ir a la charla correspondiente a enterarse en más detalle de cada tema.

Quedé contento que en la parte que presentó Franklin usó de ejemplo la aplicación de Equipos :)

Bienvenido a la Comunidad

En la charla sobre comunidad, Gabriel Icasuriaga contó sobre los recursos que tenemos disponibles los desarrolladores GeneXus: training, wiki, foros, etc., y contó sobre dos casos de personas que usaron estos recursos para lograr aprender GeneXus y mejorar en el uso de la herramienta.

Además presentaron su experiencia personal Sebastián del Río y Matías Preciozzi.

Migrando KB Grandes: Protegiendo los activos más valiosos para empresas de software

Enrique Almeida contó su experiencia en migraciones de KBs grandes, en este caso de GeneXus 9.0 a la Evolution 2, pero dando tips y presentando una metodología que creo sirven como base para cualquier migración.

Hubo mucha gente en la sala, se ve que es un tema que interesa a la comunidad.

Panel de tecnología: Amazon, Google y Microsoft

Fui a esta charla pensando que se podía armar un debate interesante, pero me encontré con que estaban todos de acuerdo en todo...

Lo que esperaba era que representantes de tres empresas que están en competencia directa y en varios frentes, plantearan una discusión con más discrepancias.

Generación automática de test: probando su aplicación con un solo clic

Me pareció espectacular la funcionalidad de GXTest que presentó Sebastián Grattarola en esta charla, que permite generar de forma automática todos los tests básicos (altas, bajas, modificaciones, búsquedas) de los objetos generados por el pattern WorkWith.

Por lo que dijo, hasta el 80% de los casos de prueba se pueden generar de esta forma, pero además para el 20% restante, se pueden utilizar los casos generados como bloques básicos de construcción para hacer cosas más complejas.

Además tienen planes de soportar todos los patterns: WorkWithPlus, K2B y PXTools.

Aplicaciones offline para Smart Devices +
Offline Smart Device Apps, estado del arte con GeneXus y casos + 
Café con Offline Smart Device Apps

El lunes de tarde hubo tres charlas relacionadas con el tema de aplicaciones offline para Smart Devices (aplicaciones que fucionan ocasionalmente o completamente desconectadas).

Gustavo Proto hizo una presentación teórica del tema con los escenarios que va a resolver esta tecnología.

En la siguiente charla, Pablo Mazzilli comentó sobre los proyectos y clientes que están en proceso de alpha-test de la funcionalidad, y mostró un ejemplo funcionando en Android con sincronización de datos mediantes procedimientos REST.

Le faltó mostrar el ejemplo en iOS, pero la media hora que tenía para la charla quedaba corta.

El "café con" estuvo interesante, hubo varios planteos y discusiones. Me resulta interesante el formato de estas charlas...

Martes

Diseño y Desarrollo: en busca de la integración

Estuvo muy interesante la charla de Lucía Guedes y Alejandro Cimas donde contaron como se hace el diseño de la "user experience" de la aplicación, antes de empezar con el desarrollo.

Creo que es el camino correcto para desarrollar aplicaciones para Smart Devices: hacer el diseño primero en papel, incluyendo a la gente de desarrollo y de diseño, e iterar en esta etapa hasta lograr algo que convenza a todos.

¡Listo! Tengo el diseño... ¿cómo sigo?

Esta charla fue la continuación de la anterior, donde Fabián Bonilla contó como integrar el diseño de la charla anterior a la aplicación GeneXus.

Si alguien está pensando en hacer una aplicación SD y no tiene experiencia en el tema, le recomiendo estas dos charlas.

Sabemos cómo hacerlo y ¿para qué?

Ana Berta contó sobre la experiencia del equipo de desarrollo de GeneXus, en lo que se dio en llamar el "Challenge Developer Edition".

Para los que no conocen, esta fue una competencia de dos semanas donde los integrantes del equipo de desarrollo desarrollamos varias aplicaciones para Smart Devices con GeneXus.

Desarrollo móvil – Mi experiencia personal

Ignacio Roqueta contó su experiencia en el desarrollo de aplicaciones para Smart Devices con GeneXus, y dio algunos consejos y datos acerca de la publicación de las mismas, principalmente en el AppStore de iOS.

Una década de videojuegos uruguayos

La charla de Gonzalo Frasca de este año se centró en la historia (bastante rica, por cierto) del desarrollo de juegos en Uruguay.

Estuvo divertida, fue casi un "stand up", sin PPTs y con varios chistes...

Nuestra experiencia en la AppStore

Pablo Realini de Iron Game Studio contó cual fue su experiencia en la AppStore con el exitoso juego Kingdom Rush.

Es muy interesante conocer como fue el proceso y ver cuales fueron las distintas etapas que pasaron en cuanto a monetización de la aplicación.

En resumen, la mejor forma de ganar plata con una aplicación parece ser mediante "In-App Purchase"... que tendremos disponible en GeneXus a partir del Upgrade 2 de la versión Evolution 2.

Todo lo que se puede hacer utilizando el generador para Smart Devices

Armando Cardozo contó sobre las aplicaciones que están haciendo en Simplifica con el generador de Smart Devices y también las extensiones que están desarrollando para este generador.

En particular, hubo dos cosas que hicieron que pueden ser muy útiles: el objeto externo para imprimir usando bluetooth en Android, y el user control que permite firmar en el dispositivo y captura la imagen.

Cara a Cara SD Generators

Obviamente fui a esta charla... pero estuve del otro lado.

No me gusta demasiado el formato de los "cara a cara". Hubo varias preguntas que respondimos (eso espero...), pero es un formato de "charla" donde es difícil que la gente se anime a preguntar. Me gusta más el formato de los "café con"

Miércoles

Charla abierta con el equipo de desarrollo

El miércoles arrancamos temprano con la charla con el equipo de desarrollo. Hubo varias preguntas y alguna sugerencia interesante.

Tilo Overview

Gastón Milano contó sobre las cosas que estamos trabajando para la versión Tilo, en un repaso rápido por varios de los temas.

Media hora es poco para este tipo de charlas, pero igual que en la de Evolution 2, había oportunidad de ir a las que le seguían para ver en más detalle alguna de estas funcionalidades.

Café con Proyectos SD

Vino mucha gente al café con proyectos de Smart Devices, tanta que no alcanzaron las sillas...

La gente que ya tiene aplicaciones liberadas contó un poco las cosas que estuvieron trabajando, y después hubo tiempo para varias preguntas.

Aprovechamos que después de la charla había un "break" de 30 minutos y extendimos la charla, porque media hora nos hubiera quedado corta.

ZetaCuentas para todos y todas … las plataformas

Quería ver en que había estado trabajando la gente de ZetaCuentas, porque había visto alguna versión de la aplicación para iOS.

Realmente la aplicación está disponible para todas las plataformas: web, web mobile (ambas con WorkWithPlus), y ahora están por liberar versiones para Android e iOS.

GeneXus Server Evolution 2: desarrollo profesional, eficiente y bajo control

José Lamas habló principalmente sobre buenas prácticas y metodología, enfocándose en como GXServer ayuda en ese sentido a quienes trabajan con GeneXus.

Creo que vale la pena verla aunque no usen el producto. Las buenas prácticas de las que habla aplican prácticamente a cualquier escenario de desarrollo de software.

GeneXus Tilo: Una nueva experiencia de usuario en aplicaciones web

Nicolás Cardelino mostró las cosas en las que está trabajando el equipo de los generadores web para la versión Tilo.

En esta versión se van a hacer varias mejoras en la forma en que se generan las aplicaciones web, que facilitan el desarrollo, mejoran la experiencia de usuario y también el rendimiento de las aplicaciones.

Entre los cambios que se vienen, hay modificaciones en como se disparan los eventos en web, pero no se preocupen, porque hay una propiedad para mantener la compatibilidad en las KBs migradas.

Potenciando nuestras aplicaciones con la nube

Daniel Monza contó su experiencia con la nube de Amazon, y varios de los recursos que utilizó para desarrollar su aplicación.

Estuvo interesante, hay mucha cosa para probar de Amazon que puede servir, creo que para poner una aplicación en producción vale la pena dedicarle un rato a enterarse que cosas se pueden usar.

Entrevista a los creadores de Kingdom Rush

Muy buena la entrevista, de nuevo, es interesante conocer cual fue el proceso que los llevó a tener su juego en el número 2 del AppStore de iPad.

Lo único malo fue que faltó la pregunta más interesante: ¿cuánta plata hicieron con el juego? :)

Industrias creativas: creando lo imposible

No lo conocía a Carlos Argüello, un nicaragüense criado en Guatemala que ha trabajado en la parte de efectos especiales en varias películas de Hollywood.

Ahora se dedica a hacer producciones desde varios países de latinoamérica, donde capacita jóvenes para que puedan competir en una industria que en principio es difícil de entrar.

Cierre del evento

Como siempre la charla deportiva de Nicolás Jodal fue muy interesante. Es difícil de resumir, así que si no la vieron, háganlo...

Por último Breogán Gonda habló sobre la guerra de patentes, sobre educación, y en un final muy emotivo nombró a Jodal como nuevo presidente de Artech, y anunció que va a dedicarse a lo que a él le gusta: la investigación.

Conclusión

Como siempre un muy buen evento, con un excelente nivel de charlas y oradores, donde se pudieron ver las cosas nuevas de la industria, de GeneXus, y en particular algo que me interesaba mucho, ver las cosas que se están haciendo con el generador de Smart Devices.

Me quedaron varias charlas por ver, que iré viendo en estos días en el sitio del encuentro. Si tienen alguna para recomendar, es bienvenido el dato :)

martes, 25 de septiembre de 2012

¿Qué pasa cuando los celulares alcancen a los notebooks?

En el 2008, uno de los mejores celulares en cuanto a características era sin duda el iPhone 3G[1], que tenía:
  • CPU: single core, 412MHz
  • RAM: 128MB
El iPhone 5 que salió hace unos días, tiene:
  • CPU: dual core, 1.2GHz
  • RAM: 1GB
Eso da un factor de mejora de 3x en el procesador y de 8x en la memoria.

Sin embargo, el iPhone 5 a pesar de que (dicen que) es el teléfono más rápido en el mercado, no es el que tiene mejor especificación técnica.

El LG Optimus G, que se espera que salga en los próximos días, tiene las siguientes características:
  • CPU: quad core, 1.5GHz
  • RAM: 2GB
Eso representa una mejora de 4x en el procesador con respecto al iPhone 3G de hace 4 años, y una mejora de 16x en la memoria.

Esto es en cuanto a celulares. Pero, ¿qué ha pasado mientras tanto con los notebooks?

Buscando en Google por "best notebooks 2008" o "best notebooks 2012" aparecen varios sitios con reseñas de los mejores en cada año, y entre los primeros siempre aparecen las MacBooks correspondientes a cada uno de los años[2]

Por ejemplo, la MacBook Pro de 2008, tenía:
  • CPU: dual core, 2.1 o 2.4GHz
  • RAM: 1 o 2GB
  • CPU: quad core, 2.3 o 2.6GHz
  • RAM: 8GB
Comparando las versiones más potentes de ambos años, nos da que la velocidad del procesador no cambia significativamente, y la memoria se multiplica por 4x.

Todo parece indicar que los celulares van a seguir mejorando rápidamente, mientras que los notebooks están prácticamente estancados. Hace unos días Coding Horror comentaba algo relacionado, y se plantea si el notebook que tiene ahora es el último que va a comprar...

Entonces lo que decía en el título... ¿Qué pasa cuando los celulares alcancen a los notebooks?


[1] Seguramente hubiera alguno con mejor especificación técnica, lo pueden poner en los comentarios :)
[2] Detractores de Apple: es un ejemplo, pero elijan la marca que quieran y les va a dar más o menos lo mismo...

viernes, 14 de septiembre de 2012

Educación on-line

En la última nota que hablaba sobre el documental La Educación Prohibida, decía que pienso que en el siglo XXI tiene que haber mejores formas de acceder a la educación que la escuela tradicional.

Básicamente me refiero al mundo de posibilidades (literalmente) que se abren con Internet, y en particular quiero mencionar tres servicios gratuitos de excelente calidad que están disponibles en la red para el que los quiera usar.

Lo bueno de acceder a distintos servicios de educación on-line, es que uno puede hacer uso de ellos en cualquier momento, puede aprender lo que tenga ganas en el momento que quiera, y no solo durante la etapa escolar.

Khan Academy

Este sitio nace por el 2006, fundado por Salman Khan, a partir de unos videos en YouTube que había filmado para explicarle temas de álgebra a sus primos...

Actualmente tiene más de 3.300 videos, pero no solo eso, tiene además ejercicios interactivos, y la posibilidad de tener tutores o docentes que guíen a sus estudiantes por los distintos temas.

Pueden ver la charla de TED Let's use video to reinvent education, altamente recomendable.

Hace no mucho, el plan Ceibal incorporó los videos de Khan Academy en español, una muy buena iniciativa.

Si tienen niños en edad escolar, creo que es un recurso indispensable.

Duolingo

Duolingo es un sitio para aprender idiomas, también de forma gratuita, y que también vi por primera vez en una charla de TED, muy divertida además.

Tienen un objetivo bastante modesto, además de enseñar idiomas: traducir todo el contenido de Internet.

No he tenido demasiado tiempo para dedicarle, pero por lo que llegué a ver está bueno.

Si alguien tiene ganas de aprender alguno de los idiomas que ya tienen (no son muchos por ahora, pero han ido ampliando de a poco), lo puede probar y después me cuenta como le fue :)

Coursera

Coursera es un sitio que brinda cursos de nivel universitario también de forma gratuita. A diferencia de los dos anteriores, los cursos tienen una fecha de comienzo y de fin, y tienen entregables además de las clases, es decir, uno debe hacer ejercicios y mandarlos antes de una determinada fecha.

Las universidades que brindan los cursos son de primer nivel, como por ejemplo Princeton o Stanford.

Adivinarán que llegué a este sitio también a partir de una charla en TED...

Para ver como era, me anoté a un curso de algoritmos que resultó bastante interesante. Nada demasiado nuevo, pero viene bien para repasar algunas cosas que vi hace años en la facultad. Además, al ser un tema más o menos conocido, me da la posibilidad de evaluar el nivel del curso, que resultó ser muy bueno.

Ahora que está por terminar, me anoté también a un curso sobre programación funcional en Scala, que empieza la semana próxima... A propósito, quien dicta el curso es Martin Odersky, inventor del lenguaje.

Conclusión

Las opciones para aprender en Internet son sin dudas ilimitadas, y estos tres ejemplos muestran que se puede lograr educación de calidad accesible para todo el mundo.

El modelo de salón de clase tradicional pierde entonces un poco de sentido, y debería reinventarse para sacar el mayor provecho a estos nuevos recursos.

Por último, quería destacar la iniciativa de OpenFING, que pretende publicar los videos de las clases de la Facultad de Ingeniería para que estén disponibles en la red. No hay mucho por ahora, solo Fundamentos de Bases de Datos, pero esperemos que se amplíe. Por otro lado, creo que no sería mala idea intentar contactarse con la gente de Coursera para brindar cursos a través de ese sitio...

martes, 4 de septiembre de 2012

La Educación Prohibida

La Educación Prohibida es un documental que habla sobre los defectos que tiene el sistema educativo actual, y hace propuestas de como debería mejorarse. Creo que vale la pena verlo, la película se puede bajar grátis del sitio, de hecho invitan a hacerlo y a compartirla.

Las ideas que plantea no son nuevas, y creo que tampoco pretenden serlo. Por ejemplo Ken Robinson en su charla de TED de 2006 (la más vista de las charlas TED), habla del tema.

Básicamente lo que plantea es que el modelo de la escuela que se tiene hoy, donde un maestro dicta clase para 25, 30 o más alumnos, que están todos sentados mirando para el mismo lado prestando atención, no es adecuado para los tiempos que corren.

Este modelo viene de la revolución industrial, y es sin duda mucho mejor a lo que había antes (donde la educación era para unos pocos). Probablemente incluso fuera lo mejor a lo que se podía aspirar en los siglos XIX y XX. Pero en el siglo XXI, tiene que haber una forma mejor de pensar la educación.

La escuela como la conocemos, si bien intenta transmitir valores, no los practica. Pretende enseñar a cooperar, pero no permite que los alumnos trabajen en equipo, y promueve la individualidad haciendo que los niños compitan por una nota.

El otro problema que tiene, y esto es algo que me ha molestado bastante, es que muchas veces se enseñan fórmulas (por ejemplo en física o matemática), que tienen una historia atrás, una motivación, pero se enseñan como que son verdades absolutas que se conocen desde siempre, con lo cual se pierde la "diversión" de descubrirlas por uno mismo, de entender de donde salen.

De todas formas hay algunas cosas que no me terminan de cerrar del documental, pero capaz que es porque tengo ya una idea pre-concebida de lo que es la educación. Por ejemplo, plantea que cada niño debe seguir su propio camino de aprendizaje, pero en realidad, hay cosas que tienen que aprender obligatoriamente (no son muchas) como ser leer, escribir y las operaciones aritméticas básicas...

Creo que el documental está bien encaminado, y creo que el sistema educativo tiene que cambiar. Sería muy bueno que se planteara un debate de hacia donde queremos que vaya, y empezar a recorrer el camino. De hecho, sería bueno (aunque la veo difícil) que eso pasara en Uruguay, que tiene todas las condiciones por ser un país chico y tener una educación bastante deteriorada para experimentar en este sentido.


domingo, 12 de agosto de 2012

Navegación guiada en Montevideo con Waze

Desde hace unos días estoy probando una aplicación para el iPhone, que tiene navegación guiada en Montevideo (o "turn-by-turn navigation" en inglés), y por ahora estoy muy conforme.

La aplicación se llama Waze, es gratuita, y está disponible tanto para iOS como para Android.

Por las pruebas que he hecho, la ruta que encuentra es en general una buena opción, aunque no siempre elige la que yo seguiría :). Acá va una foto de la aplicación en ejecución:


En el sitio web, definen a la aplicación como:
a fun, community-based GPS traffic and navigation app.
y justamente es la parte de community-based que le da su mayor potencia.

Es que la aplicación se alimenta de los datos de quienes la están usando para saber los lugares donde hay algún accidente, donde el tránsito está muy pesado, o donde hay algún desvío.

Además de esta información, uno puede reportar errores en la ruta. Por ejemplo, hubo un caso en que me recomendaba doblar a la izquierda en un semáforo donde no podía, lo reporté, y al otro día me llegó un mail confirmando que habían aceptado el arreglo (aunque no pude comprobar si quedó bien...).

Otra cosa interesante que tiene, supuestamente, es que aprende de la ruta que uno sigue. Digo supuestamente, porque la estoy usando para ir de casa al trabajo y por ahora no ha aprendido: me quiere hacer doblar en un punto donde no doblo nunca...

Así que los invito a probarla y generar datos para que todos tengamos información más confiable :)

jueves, 9 de agosto de 2012

Nuevo blog: GeneXus Tips

El mes pasado algunos compañeros de soporte de Artech empezaron a escribir un blog con tips de GeneXus. Ese blog que hasta el martes pasado estaba privado, quedó ahora público.

Muy amablemente me invitaron a participar, así que de vez en cuando van a ver alguna nota mía en dicho blog :)

Así que sin más, les dejo el link: GeneXus Tips.

Espero que les resulte útil.

martes, 7 de agosto de 2012

El futuro de la televisión es Internet, segunda parte

Creo que lo que dice el título de la nota no sorprende a nadie (o no debería), a esta altura es bastante obvio.

Hace unos días por ejemplo, veíamos esta noticia (vía @ealmeida) donde dice que 400.000 hogares en EE.UU. dieron de baja el cable en lo que va del año, y cito:
Reuters points to high unemployment rates, a weak housing market and regular programming factors as key contributing factors for the drop, but other factors may include the increasing amount of available Web-based content and high costs of cable and satellite-based TV service.
La televisión por cable, o más en general, la televisión para abonados, según yo lo veo tiene dos grandes problemas:
  1. Estoy pagando por muchos canales que no veo. En general, de las varias decenas de canales que tengo, solo miro 3 o 4 de forma habitual, más alguna película en los canales que pasan cine.
  2. Para ver algo, tengo que adecuarme a la grilla dictada por los canales, en vez de los canales adaptarse a mis horarios.
Esos dos problemas no existen (o se diluyen) si miro contenido en Internet...

Pero, ¿Internet es una opción viable, hoy, en Uruguay?

Yo creo que se están dando varias cosas más o menos al mismo tiempo, que hacen que la respuesta a esta pregunta sea cada vez más afirmativa.

Primero que nada, la disponibilidad de películas y series, ya sea con servicios pagos como Netflix por U$S 8 por mes, u otros medios como Cuevana o "torrents". Pero de esto, ya hablé hace un tiempo.

Segundo, los aumentos de velocidad y baja de precios en las conexiones de banda ancha de Antel, como se anunció hace unos días.

Lo último que está faltando es poder disponer de eventos en vivo trasmitidos por Internet. En ese sentido, si la transmisión que está haciendo Antel de los juegos olímpicos (retransmitiendo los canales de Terra) es un indicador de algo, estamos muy cerca de tenerlo.

Para los que hayan visto esta transmisión, debería quedar más que claro que supera en mucho la transmisión televisiva: tengo muchos más canales y puedo elegir ver el deporte que quiero sin depender de lo que elija el director de cámara en cada canal.

Para los que no hayan visto la transmisión on-line, véanla: http://www.terra.com.ar

Ahora, la duda que me queda es si esto es parte de una estrategia de Antel, o si es un hecho aislado.

Más allá de lo poco ético que pueda resultar que Antel se meta en este rubro[1], tiene mucho sentido como estrategia comercial. Si Antel garantiza acceso a cierto número de eventos deportivos, entonces va a ser más interesante la oferta de conexiones de alta velocidad por fibra óptica, que es lo que quieren vender.

Hasta creo que sería razonable para Antel pensar en tener una cajita con Android que se puede conectar a los televisores por HDMI, para facilitar el acceso a este tipo de contenidos...

[1] Digo poco ético, porque cuando los cables quisieron distribuir Internet por el cable coaxial, la URSEC no los dejó porque entraba en conflicto con el monopolio de Antel. Que ahora Antel se meta en el terreno de los cables sin rever la otra decisión, parece por lo menos desleal... De todas formas, desde el punto de vista del consumidor final, sería una buena noticia.

lunes, 23 de julio de 2012

Automatic Reference Counting en Objective-C

Cuando uno empieza a programar en Objective-C, una de las mayores dificultades que se encuentra es con el manejo de memoria.

Objective-C utiliza una técnica que se llama "reference counting", que resuelve el manejo de memoria en tiempo de compilación (a diferencia de "garbage collection"), pero que hasta la aparición de iOS 5 y OS X 10.7, lo dejaba en manos del programador.

Cómo funciona el "reference counting"

Básicamente, la técnica de "reference counting" funciona así:
  • cuando quiero quedarme con una referencia a un objeto tengo que mandarle un retain, esto incrementa el retainCount en uno
  • cuando ya no lo necesito más le mando un release, esto  decremente el retainCount también en uno
  • si no quiero quedarme con una referencia pero tampoco quiero que el objeto se libere inmediatamente, puedo mandarle un autorelease que hace un release pero en el futuro(1)
  • cuando el objeto queda con retainCount en cero, el mismo objeto se encarga de llamar a su propio método dealloc que libera la memoria.
(1)La explicación de como funciona el autorelease puede ser un poco compleja si no se conoce el mecanismo. El autorelease se ejecuta en el contexto de un "autorelease pool" que mantiene una referencia a cada uno de los objetos que se les envió el mensaje, y cuando se libera manda un release por cada autorelease que hice.

Además en Objective-C se usan convenciones de nombres para saber si un método devuelve un objeto con o sin retain. Por ejemplo, si el nombre del método empieza con "new", ya viene con el retain.

Esto si se usa bien funciona, pero puede generar dos tipos de errores:
  • memory leaks: a un objeto se le mandan más retain que release, por lo que la memoria nunca se libera
  • zombies: el objeto se usa luego de quedar con retainCount en cero, y por lo tanto se accede a memoria que contiene basura, ya que el objeto fue liberado al llegar a cero.
Automatic Reference Counting

La solución de Apple a partir de iOS 5 y OS X 10.7 es el Automatic Reference Counting (ARC).

Con ARC, se mantiene el mismo esquema de manejo de memoria con "reference counting", solo que no lo hace el programador, sino que lo hace el compilador de forma automática.

Esta técnica tiene ventajas sobre el "garbage collector" usado por otros lenguajes, ya que no es necesario contar con un proceso que recorra la memoria buscando objetos en desuso, que puede (y de hecho lo hace) causar problemas de performance en tiempo de ejecución.

Por lo tanto, con ARC, se tiene lo mejor de dos mundos: el manejo de memoria se hace en tiempo de compilación, y no depende del programador el que se haga bien.

Sobre la "migración"

Para los que venimos programando en Objective-C, al principio ver código escrito para ARC puede resultar un poco chocante. Algunos ejemplos:

Cuando se hace un alloc, siempre corresponde hacer un release en algún momento, y el no verlo cuando se tiene ARC hace pensar que el programa está dejando memory leaks.

El método dealloc con ARC no es muy usado, porque el objeto no tiene que liberar memoria, pero a veces se necesita por ejemplo para dejar de recibir notificaciones. En ese caso, se implementa el método dealloc, pero que no llama al [super dealloc], por lo que a primera vista da toda la impresión de estar mal.

Referencia a objetos ya liberados

Otro problema bastante común, es mantener una referencia a un objeto que ya se liberó.

Por ejemplo, cuando se tiene una referencia de tipo weak (o assign en nomenclatura pre-ARC), si el objeto referenciado quedaba con retainCount en cero, se liberaba y quedaba la referencia apuntando a memoria basura.

Con ARC en iOS 5, estas referencias se borran automáticamente al liberarse el objeto, y quedan con valor nil.

Lamentablemente si la aplicación debe funcionar con iOS 4, si bien se puede usar ARC, las referencias no pueden ser de tipo weak y no quedan con nil luego de liberarse el objeto. Se deben declarar como assign o unsafe_unretained, y se deben seguir manejando igual que antes.

Conclusión

ARC es bastante mejor a lo que teníamos: el manejo de memoria de forma manual, aunque puede costar un poco acostumbrarse.

Además se hicieron mejoras de performance, que junto con las optimizaciones que realiza el compilador, deberían mejorar el rendimiento y el uso de memoria de las aplicaciones.

En GeneXus ya estamos pasando los proyectos a ARC, y el Upgrade 2 de la Evolution 2 será compilado bajo este esquema.

jueves, 21 de junio de 2012

La importancia de respetar los estándares

Una discusión que tenemos de forma bastante recurrente en el equipo de iOS en Artech, es hasta donde es conveniente salirse de los estándares de la plataforma.

En ese sentido iOS es bastante particular, porque las guías de desarrollo llevan a que las aplicaciones sean bastante uniformes, lo que hace que los usuarios se acostumbren a que las cosas se hagan de determinada forma.

Por ejemplo, ¿es razonable en una aplicación sacar la barra de navegación? ¿Conviene usar un ícono no estándar para una acción estándar? ¿Vale la pena hacer una implementación "custom" de algún control que está disponible de forma nativa?

En general, la respuesta a todas estas preguntas es que NO, que lo mejor es ajustarse a lo nativo. Por supuesto existen excepciones y casos en los que sí me quiero salir de lo estándar, pero hay que hacerlo a conciencia y con mucho cuidado.

¿A qué viene todo esto? Que hace unos días actualicé una aplicación que uso todos los días, e hicieron un cambio que me complicó...

La aplicación se llama Reeder, y es un excelente lector de RSS que entre otras cosas se integra con Google Reader y permite compartir noticias muy fácilemente via Twitter.

El cambio que hicieron fue al leer una noticia, sacaron la Navigation Bar. En esta barra se encuentra el botón para volver a la pantalla anterior, es decir a la lista de noticias.

El botón de "back" que perdieron al sacar la barra de navegación, lo pusieron mediante un botón en el mismo control donde se muestra la noticia, con lo cual no queda más remedio que hacer todo el "scroll" hasta arriba para encontrarlo.


Este cambio, que en principio parece razonable para ganar espacio, complica al usuario acostumbrado a hacer las cosas de cierta manera.

Claro, hicieron esto y agregaron otra opción: hacer un "swipe" con un dedo de izquierda a derecha para volver a la pantalla anterior. El problema con esto es que hay que descubrirlo, ya que no es algo natural en la plataforma.

En conclusión: si existe un estándar de la plataforma, no conviene hacer lo mismo de otra forma, porque los usuarios no van a saber como reaccionar.

jueves, 14 de junio de 2012

TEDxMontevideo 2012

En el día de ayer, se llevó a cabo la tercera edición del TEDxMontevideo, la primera a la que puedo ir.

A la primera edición me había anotado, pero no quedé en el sorteo. En esta tampoco salí sorteado, pero a último momento quedó una entrada disponible en Artech de alguien que no podía ir.

La organización

La organización fue muy buena. La hora de comienzo era a las 17:00, y al final empezó a eso de 17:45, pero supongo que estaba previsto porque terminó en hora. Lo bueno es que no me perdí ninguna charla a pesar de llegar tarde...

El nivel de las charlas y los oradores también fue muy bueno.

La gente

De los asistentes, lo que me llamó la atención (no digo me sorprendió, porque no sería cierto), es la cantidad de gente joven que había. O capaz que me estoy volviendo viejo...

Lo otro es que había muchos "smart devices". Mucho iPhone, mucho iPad, mucho Android, etc. Creo que era esperable dado el tipo de público que va a este evento.

Las charlas

Hubo charlas de temas variados, pero sin duda el tema central del evento fue la educación. Yo diría que al menos en la mitad de las charlas se habló del tema. De como están cambiando los paradigmas; de que la educación está diseñada para acumular inforamción, cosa que con internet ya no es necesaria; de como los niños se aburren en las escuelas por el formato; de como se pueden buscar formas alternativas de enseñar que sean más atractivas.

Los videos de las charlas van a estar disponibles en el sitio de TEDxMontevideo. Si tengo que recomendar alguna charla, me quedo con las de Roberto Balaguer (sobre la relación que tenemos con el celular), Tiburcio de la Carcova (sobre como están haciendo inventos en Santiago de Chile) y Diego Golombek (sobre lo que es la ciencia).

También recomiendo la de Jorge Bafico (para los que son padres), que habló sobre los niños y sobre una moda que hay de diagnosticar hiperactividad y déficit de atención. Según dijo, en Uruguay el 30% de los niños recibe medicación (metilfenidato, o más conocido por su versión comercial: Ritalina). Aparentemente esta droga tiene muchos efectos secundarios, entre los que se encuentra generar adicción a las drogas durante la adolecencia.

Conclusión

El evento estuvo muy bueno, valió la pena ir. Ahora solo espero conseguir entrada para la edición 2013 :)

viernes, 1 de junio de 2012

Equipos: applicación iPhone y Android

En el equipo de desarrollo estuvimos haciendo un poco de dogfooding, para probar el nuevo generador para Smart Devices de la Evolution 2.

Surgieron varias aplicaciones interesantes que podrán encontrar ahí, pero que no voy a poner los links porque hay una competencia a ver quien consigue más descargas :)

En particular, la que hice yo se llama Equipos, y es un juego. Sí, un juego con GeneXus. Puede parecer raro, pero no soy el primero; ni siquiera soy el único que hizo un juego para Smart Devices en esta competencia de desarrollo.

En realidad la aplicación tiene dos juegos:
  • en el primero se debe adivinar cual es el escudo que corresponde, entre varios, a un equipo de fútbol dado su nombre
  • en el segundo se debe ingresar el nombre de un equipo viendo su escudo (para esto usé lo de la comparación de strings que comentaba en otra nota).
La aplicación está disponible para iPhone y para teléfonos Android. Los invito a que la bajen.

Con respecto a la dificultad para hacerla, fue bastante fácil. Es verdad que es una aplicación muy simple, pero de todas formas no la hubiera podido hacer en el tiempo que la hice programando "a mano".

Primero la hice para iOS con backend Ruby (que tiene seguridad con GAM), y después la pasé a Android haciendo solo algunos ajuntes de UI. Cada uno de los componentes en sí no es complicado: el front-end son 5 pantallas básicamente, y el backend son 4 tablas, pero la combinación de hacer todo junto, con GeneXus es trasparente.

Hubo tres cosas que me resultaron complicadas:
  1. obtener los datos
  2. el diseño de la aplicación
  3. la publicación en los markets.
Para los datos, tuve la suerte que ya alguien más había hecho una aplicación que usaba escudos de cuadros de fútbol, que los había sacado de Wikipedia o quien sabe donde... De todas formas no es un tema para despreciar.

Con respecto al tema del diseño, no es algo que me salga naturalmente. Les dejo dos fotos de pantalla, la primera hecha por mi y la segunda después de pasar por un disañador.


No es nada del otro mundo, con un fondo adecuado y una buena combinación de colores queda mucho mejor. El tema es saber hacerlo...

Por último, la publicación en Google Play y en el App Store lleva tiempo. Nunca lo había hecho en ninguno de los dos, y si bien involucran varios pasos (sobre todo el de Apple), la documentación que hay en el wiki está completa y se puede seguir bien.

La aprobación de Apple es el otro punto a tener en cuenta, que en mi caso llevó más de una semana...

Nuevamente los invito a que la bajen para iPhone y/o para teléfonos Android.

miércoles, 2 de mayo de 2012

Comparación de strings por aproximación

Para una aplicación que estoy haciendo con GeneXus (después cuento de que se trata...), necesitaba poder comparar dos strings, pero no necesito que sean exáctamente iguales, me alcanza con que sean aproximados.

El primer intento fue hacer que uno de los dos strings fuera por lo menos la mitad del largo del otro y que estuviera contenido. Como aproximación está bien, pero si por ejemplo uno de los dos tiene un tilde y el otro no, da que son diferentes.

Gracias a Matías me enteré que existe un algoritmo, llamado Distancia de Levenshtein, que se usa justamente para esto. Según Wikipedia:
En Teoría de la información y Ciencias de la Computación se llama Distancia de Levenshtein, distancia de edición, o distancia entre palabras, al número mínimo de operaciones requeridas para transformar una cadena de caracteres en otra. Se entiende por operación, bien una inserción, eliminación o la sustitución de un carácter. Esta distancia recibe ese nombre en honor al científico ruso Vladimir Levenshtein, quien se ocupara de esta distancia en 1965. Es útil en programas que determinan cuán similares son dos cadenas de caracteres, como es el caso de los correctores de ortografía.
Dejo acá el algoritmo en GeneXus, por si a alguien más le resulta útil:
/*
* Distancia de Levenshtein
*
* Fuente: http://es.wikipedia.org/wiki/Distancia_de_Levenshtein
*
* parm(in:&str1, in:&str2, out:&distance);
*
* Todas las variables son N(4) salvo &str1 y &str2 que son C(100)
*/

&lenStr1 = &str1.Length()
if &lenStr1 > 99
    &lenStr1 = 99
endif

&lenStr2 = &str2.Length()
if &lenStr2 > 99
    &lenStr2 = 99
endif

for &i = 1 to &lenStr1+1
    &distMatrix(&i, 1) = &i-1
endfor
for &j = 1 to &lenStr2+1
    &distMatrix(1, &j) = &j-1
endfor

for &i = 2 to &lenStr1+1
    for &j = 2 to &lenStr2+1
        if &str1.Substring(&i, 1) = &str2.Substring(&j, 1)
            &costo = 0
        else
            &costo = 1
        endif

        &val1 = &distMatrix(&i-1, &j)+1 // deletion
        &val2 = &distMatrix(&i, &j-1)+1 // insertion
        &val3 = &distMatrix(&i-1, &j-1) + &costo // substitution

        &min = &val1
        if &val2 < &min
            &min = &val2
        endif
        if &val3 < &min
            &min = &val3
        endif

        &distMatrix(&i, &j) = &min
    endfor
endfor

&distance = &distMatrix(&lenStr1+1, &lenStr2+1)

sábado, 14 de abril de 2012

iPhone 4s vs. iPhone 3Gs

Hace unos días, ya que pude desbloquear el 3Gs para venderlo, me compré el iPhone 4s...

Acá va una comparación de ambos

La pantalla

La pantalla "retina display" del 4s es espectacular. Mirando uno al lado del otro se nota claramente la diferencia. Estas son fotos de pantalla, una de cada uno de los teléfonos (click para agrandar)



La cámara

La diferencia en las fotos que se pueden sacar, también salta a la vista. La cámara del 4s es mucho mejor que la del 3Gs, y no solo por el tamaño de las fotos, sino también por la nitidez y la calidad de los colores que se obtienen.

Ni hablar de que el 4s además de la cámara tiene flash.

También tiene más funciones, como por ejemplo HDR (high dynamic range), que mejora por software (y mediante la captura de varias fotos en una sola exposición) las fotos que tienen una variación muy grande de luz.

Acá pueden ver tres fotos comparativas: la primera con el 3Gs, la segunda con el 4s y la tercera usando HDR.



Todavía no he tenido oportunidad de jugar mucho con la cámara, pero la primer impresión es que es muy superior.

Rendimiento

Con el 3Gs, ya había cosas que se notaba que tenía problemas de performance. Con el 4s cualquier cosa que haga es instantanea.

Batería

Aunque parezca mentira, en estos días la batería del 4s me ha durado más que lo que duraba la del 3Gs. El uso que le doy es el mismo, así que parece ser que dura más.

También es verdad que el 3Gs ya tenía 2 años y medio, y las baterías van perdiendo capacidad a medida que pasa el tiempo. Para hacer una comparación seria, habría que probar con los dos nuevos...

Forma, dimensiones y peso

El 3Gs me resultaba más cómodo de sostener en la mano, gracias a que la parte de atrás es redondeada. Igual el 4s no resulta tan incómodo como pensé que iba a ser. Después de un par de días uno se acostumbra.

La ventaja que tiene la forma del 4s (y del 4 ya que estamos) es que al no tener curvas, permite acomodar mejor los componentes internos, y eso hace que sea más chico.

Con respecto al peso no noté demasiada diferencia entre uno y otro. Aparentemente el 4s es 5 gramos más pesado.

Conclusión

Si tienen un 3Gs y están pensando en cambiarlo, no lo piensen más :) Vale la pena.

Si tienen un iPhone 4, no me queda tan claro que convenga cambiarlo, a lo mejor conviene esperar a la siguiente generación...

Si quieren una comparación más seria, funcionalidad por funcionalidad, la pueden ver en GSMArena.

viernes, 13 de abril de 2012

Desbloqueo oficial de iPhone

Hasta hace poco, pensaba que el desbloquear un iPhone era un proceso no aprobado por Apple, casi que ilegal digamos.

Pero resulta que no, que hay una forma de desbloquear un iPhone de forma totalmente legal, aunque no hay mucha información al respecto.

Para eso, el operador tiene que ofrecer el desbloqueo (ver lista de operadores), que en el caso de Uruguay está disponible tanto en Movistar como en Claro.

Les cuento como fue el proceso, por si alguien más necesita hacerlo...

Mi experiencia con Movistar

En mi caso, tengo un iPhone 3Gs de Movistar, que se venció el contrato original a fines de 2011.

Cuando me enteré que se podía desbloquear, pregunté en Movistar como tenía que hacer, y me dijeron que tenía que ir simplemente al local que está en Soca y Rivera, que ahí lo hacen. Después alguien que comentó que en el Palacio Salvo también se puede, pero no tuve la oportunidad de confirmarlo.

Fui un día al local de Movistar indicado, y me dijeron que sí lo podían desbloquear, pero que lo tenía que autorizar la gerencia y podía demorar hasta dos meses. Así que dejé el pedido hecho...

No demoraron tanto, más o menos a los 10 días me llamaron para pedirme el IMEI del celular, se los pasé, y al otro día me llamaron para avisar que ya estaba pronto, y lo único que debía hacer era conectarlo a una computadora que tuviera conexión a internet, y abrir iTunes.

El proceso de desbloqueo, aparentemente, consiste en que la operadora le pasa a Apple los datos del teléfono, y Apple de alguna forma lo marca como desbloqueado.

Estuve una semana más o menos conectando el aparato a iTunes, pero nada, nunca se desbloqueó.

Volví a ir a Movistar a reclamar, y me dijeron que ese era el procedimiento correcto, y que tenía que esperar.

Esperé... unos diez días más aproximadamente.

Así que volví a ir a Movistar a reclamar, y después de que la vendedora se lo llevó un rato, para que lo viera el técnico, volvió a decirme que ellos ya habían hecho su parte y que no tenían nada más para hacer. Pedí para hablar con el técnico, pero me dijeron que no atienden público, y que me pusiera en contacto con soporte de Apple.

Al final lo logré desbloquear, pero no gracias Movistar, ya que quienes atienden al público que no tienen ni idea...

El proceso de desbloqueo

Para hacer un resumen, los pasos para desbloquear el teléfono son:

  1. Asegurarse que la operadora ofrezca ese servicio, y esperar al fin del contrato
  2. Pedir a la operadora que haga el desbloqueo, pagar lo que corresponda (pueden llegar a cobrar algo, no fue mi caso)
  3. Esperar a que la operadora nos confirme que ya hizo el pedido a Apple
  4. Conectar el teléfono a iTunes, con conexión a internet, y restaurar los ajustes originales.
Lo que nunca me dijeron en Movistar, es que para que se aplique el desbloqueo hay que restaurar el teléfono.

En el paso 4, puede ser que sea necesario ponerle un chip de otra compañía. Yo lo hice, pero no se si es obligatorio...

El paso de restaurarlo, es bien simple y funciona sin ningún problema. Eso sí, no se olviden de hacer un respaldo antes (iTunes pregunta antes de empezar la restauración) si pretenden mantener los datos.

jueves, 12 de abril de 2012

La venta de entradas para Paul McCartney por internet

A menos que haya algún despistado... todos sabrán que el próximo 15 de abril viene Paul McCartney a tocar al Estadio Centenario.

Como buen fanático de los Beatles, tenía ganas de ir, así que me dispuse a comprar las entradas.

Las que se vendieron en Abitab volaron, algo así como 28.000 entradas en menos de una hora. Y eso que los precios no eran precisamente baratos.

Mi idea era comprar de esas, pero no pensé que se vendieran tan rápido y no conseguí. En internet cuando me fui a fijar quedaban entradas solo con tarjeta del Citi.

Para la segunda tanda de 5.000 tampoco pude ir a la hora que se ponían a la venta, pero tenía la esperanza de poder comprar por internet. El problema fue que también eran solo con tarjeta del Citi.

Así que lo que hice fue preguntar en Twitter si alguien tenía y me podía prestar, y por suerte un amigo (Gabriel) me ofreció la de él.

Acá empieza la parte divertida.

El proceso de compra por internet fue razonable. No se para que me pidieron registrarme en el sitio donde se vendían, pero es algo aceptable.

Durante el proceso de compra me pidieron la dirección de entrega, como que me las iban a mandar, pero en el mail de confirmación decía que había que retirarlas en algún lugar que no indicaba.

Unos días después me llegó otro mail con el lugar donde había que retirarlas, los horarios, y que se podía ir a partir del lunes 9 de abril. Además decía que tenía que ir el titular de la tarjeta con documento válido.

Así que quedamos de encontrarnos con Gabriel el lunes para retirarlas. Él llego antes que yo, y cuando las fue a retirar, le pidieron el mail impreso con la confirmación de la compra, que obviamente no tenía porque no decía en ningún lado que se precisaba. Me avisó, volví a imprimirlo (porque ya estaba en camino) y allá fui con el mail impreso.

Otra vez a la ventanilla, ahora con el titlar de la tarjeta y el mail impreso. ¿Qué nos dijeron? Que las entradas compradas en abril iban a estar a partir del miércoles... Eso a pesar de que el mail decía que se podían retirar a partir del lunes.

Además nos enteramos, de casualidad porque a alguien adelante nuestro lo rebotaron, que además de ir el titular de la tarjeta con la cédula, tenía que llevar la tarjeta.

Como que así pierde la gracia de comprar por internet, ¿no? Yo me pregunto si en Londres por ejemplo, donde tocó hace unos días será igual...

El miércoles sí, finalmente, pudimos retirar las entradas. Igual escuchamos decir que no estaban todas, que habían algunas que no estaban impresas todavía y había que retirarlas el jueves...

Todo esto me hizo acordar al estereotipo de trámite en organismo público, donde siempre te rebotan porque falta un papel, nunca nadie te dice todo lo que se precisa y si le preguntas a dos personas distintas te dicen cosas contradictorias.

Es lamentable que estas cosas funcionen así...

En fin, final de la historia, el domingo es el recital que seguramente va a estar muy bueno.

viernes, 30 de marzo de 2012

Game of Thrones: el libro y la serie de TV

Acabo de terminar de ver la primera temporada de Game of Thrones, después de haber leído el libro.

Cuando empezaron a dar la serie Game of Thrones en HBO parecía interesante, y me dieron ganas de verla, pero la verdad cada vez me parece más complicado tener un horario fijo para poder ver algo en la tele[1]. Así que, después de ver el primer capítulo, no vi más...

Poco tiempo después me enteré que estaba basada en un libro, así que me puse a leer el libro antes de ver la serie.

El libro está bueno. La historia en sí es atrapante, pero después de leer las 700 páginas, la sensación que me quedó es que fue una especie de introducción, que quedaron muchos cabos sueltos. Claro, es el primero de 5 libros (hasta ahora...), y como tal, no es la historia completa.

Después de leer el libro, me puse a ver la serie gracias a Cuevana. Es una excelente adaptación, bastante fiel a la historia original, y creo que vale la pena verla aunque no se haya leído el libro. La gran ventaja que tiene el libro es que permite profundizar mucho más en los personajes, y por las cosas que pasan por la cabeza de cada uno de ellos.

Creo que haber leído el libro primero fue una buena decisión, y pienso repetirla para la segunda temporada que está por comenzar.

[1]Nota aparte: hay una gran oportunidad de negocio para el que resuelva bien el tema de distribuir contenido a demanda. No me refiero a la solución técnica, que ya existe (por ejemplo Netflix o Cuevana), sino a entregar contenido de calidad de forma simple para el usuario y con un costo razonable. Me llama la atención que las operadoras de cable no lo hayan visto todavía...

jueves, 22 de marzo de 2012

Detectar problemas de memoria con Instruments

En Objective-C, cuando se maneja la memoria "a mano" con retain/release/autorelease, es bastante común que aparezcan problemas de memoria.

Estos problemas no deberían aparecer si se usa ARC (Automatic Reference Counting) en el proyecto, ya que todo el manejo lo hace automáticamente el compilador.

Los problemas que pueden aparecer son de dos clases:
  • Leaks: un objeto se retiene más veces que las que se libera, por lo que queda memoria en uso, a la que no se puede acceder.
  • Zombies: un objeto que se libera más veces de las que se retiene, por lo que la aplicación da un error cuando se le intenta mandar un mensaje.
Los Zombies en general son más fáciles de detectar ejecutando la aplicación, porque la aplicación termina con un error. De todas formas, a partir del error, no siempre es fácil detectar donde se produce o por que.

Para ambos casos, Xcode viene con una aplicación llamada Instruments, que permite detectarlos.

Para poder ejecutar Instruments, se debe ejecutar la aplicación con "Profile" (en lugar de "Run"), lo que va a mostrar una pantalla como sigue:

En esta pantalla se elige que es lo que queremos buscar (Leaks o Zombies), y luego se abre la ventana de Instruments correspondiente y la aplicación en el Simulator.

Al ejecutar la aplicación, si aparece algún problema de memoria, se va a ver en esta ventana.

Por ejemplo, cuando tenemos "leaks":

En la parte superior de la pantalla, nos muestra en azul la memoria que va usando, y en rojo cuando aparece un "leak".

En la parte de abajo, muestra los objetos que no se liberaron. Ahí se puede ver la clase del objeto, quien fue la biblioteca responsable, y donde fue que se produjo el "leak". Si hacemos click en la flechita al lado de Address, entonces muestra toda la historia de ese objeto: cuando fue que se creo, cuando se retuvo y cuando se liberó. Eso permite tener una idea bastante clara de donde fue que se produjo el problema.

Si bien no nos da la ubicación exacta de donde está el problema (es decir, donde se debió haber liberado la memoria y no se hizo), da mucha información que permite encontrarlo de forma relativamente fácil.

Lo mismo ocurre con los "zombies", cuando la aplicación da un error de tipo "EX_BAD_ACCESS", es seguramente porque tenemos un objeto que se liberó de más.

Cuando corremos la aplicación con Instruments, si aparece un "zombie" muestra una cartel indicándolo, y si hacemos click en la flechita, muestra toda la historia del objeto, cuando se le hizo "retain" y "release", lo que permite encontrar de forma bastante rápida donde está el problema.


Con Instruments se pueden hacer muchas más cosas. Estas dos tal vez sean las más comunes, pero es una aplicación que tiene mucha potencia. Vale la pena dedicarle un rato, para ver las cosas que tiene. La parte de "Leaks" sobre todo es fundamental para encontrar problemas de memoria, que si no, son muy difíciles de detectar.

miércoles, 7 de marzo de 2012

Administrando el correo con GMail

Si hay algo que me gusta tener ordenado es el correo. No sigo la filosofía de inbox zero (ni soy experto en el tema), pero me gusta tener la bandeja de entrada limpia en todo momento.

La idea de esta nota es contar como me organizo, ya que creo haber encontrado una metodología que me convence, y capaz que le puede servir a alguien más. Obviamente si alguien piensa que se puede mejorar, escucho los comentarios.

Para el correo, tanto personal como laboral, uso Gmail. En algún momento probé algún otro cliente (Thunderbird y Sparrow), pero no lograron convencerme del todo. Gmail tiene el Priority Inbox, que facilita bastante la organización.

El Priority Inbox de Gmail permite definir hasta cuatro secciones, que en mi caso son:

  • Important and unread
  • Starred
  • etiqueta Follow up
  • Everything else
En Important and unread va eso, mensajes que Gmail etiqueta como importantes y que todavía no leí. Hay que entrenar un poco a Gmail para que sepa que cosas tienen que estar marcadas como importantes y cuales no, pero después de un tiempo el algoritmo es bastante bueno (aunque igual a veces se equivoca).

En esa sección no puede haber nada... Cuando chequeo la bandeja de entrada, si hay un mail ahí, entonces hay que prestarle atención. Las opciones son varias:

  • Si el mail no era importante, entonces lo primero es marcarlo como tal, para que Gmail vaya mejorando la heurística.
  • Si es un mail informativo, pero no requiere ninguna acción de mi parte, se lee y se archiva. En caso que tenga información que voy a necesitar más adelante, puede quedar en la sección de Everything else como leído.
  • Si el mail requiere una acción, pero no urgente, se le pone la etiqueta Follow up para verlo más adelante.
  • Si requiere atención urgente, y no estoy con nada urgente en el momento, se lo marca como Starred. Si ya estoy con otra cosa, entonces va también a Follow up.
Para los mails sin leer que aparecen en Everything else (los que Gmail no marca como importantes) se sigue el mismo procedimiento, pero pueden quedar sin leer si estoy con algo urgente en el momento.

La sección Starred es para las cosas que estoy viendo en el momento. Por ejemplo, cuando empiezo a trabajar en un issue, el mail correspondiente lo marco con una estrella, y cuando termino lo desmarco.

Obviamente en esta sección no puede haber mucha cosa. Es difícil que esté activamente en más de un tema a la vez, por lo tanto solo pueden estar los mails que corresponden a ese tema. También puede haber algún tema que tenga en espera de una respuesta si pienso que va a llegar rápido, pero si demora mucho, va para Follow up o se archiva (ya va a llegar otro mail con la respuesta...).

Cuando no hay nada en Important and unread ni en Starred, entonces le toca el turno a Follow up. De los mails que están ahí, se toma el que parezca más importante, se le saca la etiqueta de Follow up y se lo marca como Starred.

En este momento tengo:
  • 0 mails en Important and unread :)
  • 2 mails en Starred (uno de un tema que empecé a ver y todavía no terminé y otro esperando una respuesta)
  • 10 mails en Follow up
  • 11 mails en Everything else, todos leídos.

domingo, 26 de febrero de 2012

HTTPS y sitios uruguayos

Hace unos días leí un artículo en el blog de Jeff Atwood, que hablaba sobre si se debería encriptar todo el tráfico de internet usando HTTPS.

La conclusión que llega, con la que estoy totalmente de acuerdo, es que sí se debe usar HTTPS siempre que el usuario esté logueado y se puede usar HTTP para el contenido público. De todas formas, el costo de usar HTTPS hoy en día es muy bajo (en términos de recursos).

El protocolo HTTPS lo que hace (muy básicamenete), es encriptar la comunicación entre el servidor y el cliente, utilizando un certificado de clave pública/privada del lado del servidor. Para eso, el sitio que va a utilizar HTTPS, necesita tener un certificado válido.

Cuando un cliente se quiere conectar le pide el certificado al servidor, verifica que sea válido, y si lo es se lleva a cabo la comunicación.

La parte de "verifica que sea válido" es la más compleja, porque ambas partes tienen que confiar en alguien común, que valide el certificado, es decir, que asegure que el servidor es quien dice ser.

Para eso existen las entidades certificadoras, que tienen certificados que son de conocimiento público (porque vienen instalados con el sistema operativo o con el navegador web), y que usan para firmar los certificados de los demás sitios web. Así, por ejemplo, si veo el certificado de GMail, veo que la raíz del certificado es de confianza.


En Uruguay, quien emite certificados, es el Correo. ¿Y adivinen qué?: el certificado no está firmado por una entidad de confianza:


Por lo tanto, cuando quiero ir a la página del Banco de Previsión Social, Chrome me muestra lo siguiente:


Por suerte el país está discutiendo el tema de la firma digital...

Ah, y por si fuera poco, después que uno se registra (ignorando este tema de que el certificado no es de confianza), le mandan la contraseña generada automáticamente a la dirección de e-mail.

viernes, 20 de enero de 2012

Nuevo blog: GeneXus for Smart Devices

Esta nota es solo para contarles que estamos empezando un nuevo blog: GeneXus for Smart Devices.

La idea es tener un lugar donde contar las cosas que estamos haciendo, nuevas funcionalidades, tips, como extender los generadores, etc.

Los invito a que lo visiten y se suscriban (por RSS). Ya tiene un par de notas, la bienvenida y una nota contando una funcionalidad nueva :)

El blog está en inglés, porque parece lo más razonable para una comunidad de desarrolladores.

jueves, 12 de enero de 2012

Implementar un User Control para el generador iOS

En los generadores para Smart Devices en GeneXus X Evolution 2, tenemos la posibilidad de crear user controls, para extender el comportamiento del generador.

La idea de esta nota es contar como desarrollar un nuevo user control para el generador iOS.

Nota: crear un nuevo user control involucra varios pasos: implementación en la plataforma, definición del control, implementar resolvers para las propiedades, distribución, etc. Ahora me voy a concentrar solo en la parte de implementación.

Como ejemplo, voy a mostrar como implementar el SD ImageMap. Básicamente lo que hace es mostrar una imagen de fondo con un conjunto de imágenes en posiciones determinadas, que cuando se seleccionan tiene la posibilidad de disparar una acción.

El código completo del control (al día de hoy) lo pueden ver en https://gist.github.com/1600064

Clase base

Como decía, el control muestra una lista de imágenes con una imagen grande de fondo. Esa lista puede venir de una tabla en la base de datos, o de un SDT collection. En cualquier caso, los controles que reciben una lista de registros, se implementan a partir de un control Grid en GeneXus, cambiando la propiedad Control Type según corresponda.

Lo primero que tenemos que hacer entonces es crear la clase GXControlImageMap, como subclase de GXControlGridBase.

Advertencia: los nombres que empiezan con "GX" están reservados. En este caso el control es parte del Framework, por lo tanto puede llamarse así. Cuando implementen sus controles usen algún otro nombre...

Creación de la vista

Lo primero que debemos implementar es el método que crea la vista que va a utilizar el control. La forma de hacerlo es implementar el método newGridViewWithFrame:, que será llamado por la clase base cuando se haga el loadView.

Es importante notar que no es aconsejable implementar el loadView directamente, ya que la clase base hace varias cosas además de crear la vista del control (por ejemplo crea otra vista donde coloca la vista que estamos creando, le aplica la propiedad "Visible", etc.).

- (UIView *)newGridViewWithFrame:(CGRect)frame {
    UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];
    [imageView setAutoresizingMask:UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth];

    NSString *imageName = [self imageName];
    if (imageName) {
        UIImage *embededImage = [GXResources imageForName:imageName];
        if (embededImage) {
            [imageView setImage:embededImage];
        }
        else {
            NSURL *imageUrl = [GXResources urlForImageName:imageName];
            [imageView setImageWithURL:imageUrl placeholderImage:nil];
        }
    }
    
    [imageView setUserInteractionEnabled:YES];
    
    UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleImageTap:)];
    
    [imageView addGestureRecognizer:tapGestureRecognizer];
    
    [tapGestureRecognizer release];
    
    return imageView;
}

El método newGridViewWIthFrame: hace lo siguiente:
  • crea un UIImageView donde va a dibujar la imagen de fondo
  • carga la imagen, el valor lo obtiene usando el método imageName (ver más adelante)
  • agrega un "tap gesture recognizer" para poder detectar cuando se hace un tap sobre alguna de las imágenes
Acceso a la vista del control

El UIImageView que estamos creando en este método queda accesible usando el método gridView de la clase base. Es recomendable implementar un método que permita acceder a esta vista con el tipo de datos correcto, ya el gridView es un UIView genérico. Por lo tanto, el control implementa el método imageView

- (UIImageView *)imageView {
    return (UIImageView *)[self gridView];
}

Propiedades definidas en GeneXus

El control también va a necesitar acceso a las propiedades definidas en GeneXus. Para eso define nueve métodos, uno por cada una de las propiedades:

- (NSString *)imageName;
- (NSString *)imageAtt;
- (NSString *)imageField;
- (NSString *)horizontalCoordinateAtt;
- (NSString *)horizontalCoordinateField;
- (NSString *)verticalCoordinateAtt;
- (NSString *)verticalCoordinateField;
- (NSString *)sizeAtt;
- (NSString *)sizeField;

La propiedad imageName tiene el nombre de la imagen de fondo a usar.

Las demás propiedades vienen en pares, una con sufijo "Att" y la otra con sufijo "Field". La propiedad con sufijo "Att" indica el nombre del atributo o variable que contiene el valor. La propiedad con sufijo "Field" contiene el "field specifier", que se usa en el caso que el "Att" sea un SDT, e indica el nombre del miembro del SDT.

Ejemplos:
  • Si usamos el atributo MyAttribute, en la propiedad "Att" viene "MyAttribute" y la propiedad "Field" viene vacía
  • Si usamos la variable &MyVar, en la propiedad "Att" viene "&MyVar" y la propiedad "Field" viene vacía.
  • Si usamos un miembro de un SDT, &MySDT.Item, entonces en la propiedad "Att" viene "&MySDT" y en la propiedad "Field" viene "Item"
Los cuatro grupos de propiedades que tienen esta característica son:
  • image: contiene la imagen del ítem a mostrar
  • horizontalCoordinate: la posición horizontal donde se debe mostrar, relativo al tamaño de la imagen de fondo (el origen de coordenadas {0,0} está en la parte superior izquierda de la imagen de fondo)
  • verticalCoordinate: la posición vertical
  • size: el tamaño con el que se debe mostrar la imagen, relativo al tamaño de la imagen de fondo.
Las propiedades se leen de forma muy simple, por ejemplo:

- (NSString *)horizontalCoordinateAtt {
    return [[self properties] getPropertyValueString:@"@SDImageMapHCoordAtt"];    
}

La única que tiene algo más de complejidad es imageName, que por ser una imagen viene con un prefijo que es el GUID de las imágenes, y debemos separarlo para poder usarla:

- (NSString *)imageName {
    NSString *imageName = [[self properties] getPropertyValueString:@"@SDImageMapImage"];
    imageName = [GXObjectHelper parseObjectNameOfType:kGXObjectIdImage from:imageName];
    return imageName;
}

Carga de datos

La carga de datos la maneja la clase base, y cuando termina de obtener los datos del servidor le manda el mensaje reloadData al control.

En este caso la implementación invoca un método privado loadData: pasándole la cantidad de registros que tiene el proveedor de datos:

- (void)reloadData {
    [self loadData:[[self entityDataListProvider] numberOfLoadedEntitiesInSection:0]];
}

El método loadData: es más interesante.

Lo primero que hace es borrar cualquier imagen que tuviera ya cargada, porque las va a volver a agregar:

[[[self imageView] subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];

Luego obtiene los valores de las propiedades configuradas en GeneXus:

NSString *imageNameAtt = [self imageAtt];
NSString *imageNameField = [self imageField];
NSString *hCoordAtt = [self horizontalCoordinateAtt];
NSString *hCoordField = [self horizontalCoordinateField];
NSString *vCoordAtt = [self verticalCoordinateAtt];
NSString *vCoordField = [self verticalCoordinateField];
NSString *sizeAtt = [self sizeAtt];
NSString *sizeField = [self sizeField];

Lo siguiente es iterar sobre los registros disponibles (la cantidad se le pasa como parámetro al loadData: en la variable count)

for(NSUInteger index = 0; index < count; index++)

y para cada uno, obtener los valores. Para eso usamos el método valueForEntityDataFieldName:fieldSpecifier:indexPath: de la clase base:

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0];
NSString *imageName = [self valueForEntityDataFieldName:imageNameAtt fieldSpecifier:imageNameField indexPath:indexPath];
NSNumber *hCoord = [self valueForEntityDataFieldName:hCoordAtt fieldSpecifier:hCoordField indexPath:indexPath];
NSNumber *vCoord = [self valueForEntityDataFieldName:vCoordAtt fieldSpecifier:vCoordField indexPath:indexPath];
NSNumber *size = [self valueForEntityDataFieldName:sizeAtt fieldSpecifier:sizeField indexPath:indexPath];

Nótese que el indexPath le indica al proveedor de datos cual es el registro que estamos procesando.

El resto del código del evento es específico al control y no viene mucho al caso, lo pueden ver en el link con el código completo. Lo único para destacar es que con los valores de las propiedades leídas crea un UIImageView para cada ítem y lo agrega a la vista principal del control con

[[self imageView] addSubview:itemView];

Disparo de acciones

Por último, lo que hace el control es disparar la "default action" cuando se selecciona una de las imágenes.

Eso se configuró en el método newGridViewWithFrame: cuando agregamos el "tap gesture recognizer", que va a invocar el método handleImageTap:

- (void)handleImageTap:(UITapGestureRecognizer *)sender {
    UIView *mainView = [self imageView];
    
    CGPoint tapPoint = [sender locationInView:mainView];
    UIView *tappedView = [mainView hitTest:tapPoint withEvent:nil];
    
    if (tappedView && tappedView != mainView) {
        NSUInteger index = [tappedView tag];
        [self executeDefaultActionForEntityAtSection:0 row:index];
    }
}

Este método determina sobre cual ítem se hizo el tap, y luego simplemente llama al método executeDefaultActionForEntityAtSection:row: de la clase base para que se encargue.

Resumen

La nota quedó bastante larga, pero en realidad no es mucho lo que hay que hacer para implementar un user control. La parte más compleja se encarga la clase base: obtener los datos (ya sea de un data provider o de un SDT), lectura de propiedades, manejo de la vista del control, manejo de eventos, etc.

En resumen, lo que tiene que hacer el control es:

  • crear la vista, en el método newGridViewWithFrame:
  • implementar el método reloadData para cargar los datos que vienen en el provider (en este caso se implementó en un método privado loadData:, pero es lo mismo)
  • determinar cuándo se debe disparar una acción y cuál es el ítem que corresponde.