lunes, 12 de diciembre de 2011

Serie numérica

Hace un tiempo en un pizarrón en la oficina apareció la siguiente serie:

1
11
21
1211
111221
312211
13112221

1113213211

Algunas preguntas:
  1. ¿Cuál es el próximo elemento de la serie y como se construye?
  2. ¿Cuál es el dígito más grande que puede aparecer? Tip: es menor que 9 :)
  3. Tengo una conjetura: el largo de un elemento de la serie no puede ser menor que el largo del elemento anterior. ¿Alguien se anima a demostrarlo?

sábado, 10 de diciembre de 2011

Sobre la comparación entre lenguaje de programación

El otro día en un almuerzo salió el tema de si tiene sentido comparar distintos lenguajes de programación.

Una de las posturas era que en realidad, con cualquier lenguaje de programación moderno (léase Java, C#, Objective-C, Ruby, etc.) puedo solucionar cualquier problema que pueda solucionar con otro de estos lenguajes.

De todas formas yo creo que sí se pueden comparar, y que si bien con cualquiera se pueden resolver los problemas, no se obtiene la misma productividad.

Voy a poner un ejemplo, usando una muy pequeña característica de los lenguajes de programación: los loops de tipo "for".

El caso más simple, es querer recorrer una colección partiendo del primer item hasta el último, avanzando de a uno. Para eso me alcanza una construcción del tipo:

for index = 0 to count-1 {
  // hacer algo con index
}


¿Qué pasa ahora si quiero contar de dos en dos? ¿Me sirve la construcción anterior? Bueno, sí... puedo escribir lo siguiente:

for fakeIndex = 0 to (count-1)/2 {
  index = fakeIndex * 2
  // hacer algo con index
}


No es complicado, pero no parece muy práctico. Un lenguaje que le pueda decir el "step" al comando "for" no es más potente, pero sí más práctico. La forma de escribirlo quedaría entonces:

for index = 0 to count-1 step 2 {
  // hacer algo con index
}


El problema que tiene esto, es que si quiero que el step sea variable, por ejemplo quiero iterar sobre las potencias de 2, con el step solo no me alcanza. Lo puedo resolver, pero queda más complicado. Una solución es usar la sintaxis que usa C, donde se le indica el valor inicial, la condición de parada, y el incremento. Así:

for (int index = 1; index <= someValue; index *= 2) {
  // hacer algo con index
}


Esta iteración sí la puedo construir con el primer tipo de "for", pero es más difícil: hay que pensar como mapear el índice de la iteración con el índice que realmente quiero manejar.

De todas formas, cuando uno tiene este "for" como es el caso de C y todos sus lenguajes derivados, lo más común es usarlo para acceder a los elementos de una colección:

for (int index = 0; index < array.count; index++) {
  value = array[index];
  // hacer algo con value
}


En general, el índice se termina usando solo para acceder al elemento correspondiente de la colección. El valor inicial, el final y el incremento son una construcción artificial. Lo que realmente quiero es poder iterar sobre los elementos de mi colección.

Supongamos ahora que tengo una construcción que me permite hacer esto:

for (value in array) {
  // hacer algo con value
}


¿Es esta construcción más potente que la anterior? No, las dos permiten expresar lo mismo. Pero sin duda es mucho más conveniente, aumenta la productividad y minimiza el riesgo de cometer errores (por ejemplo si uso "index <= array.count" en vez de "index < array.count", error bastante común).

¿Se puede hacer mejor? Sí, se puede, y lo curioso del caso es que para la forma de mejorarlo es eliminar la construcción "for", que es lo que se tiene en Ruby (donde sí existe el "for" pero no se usa...).

Si no tengo el comando "for", entonces tengo que buscar otra forma de iterar sobre una colección o conjunto de valores. Esto en Ruby se resuelve con el método "each" (o "each_index") de la siguiente forma:

array.each do |value|
  # hacer algo con value
end


o

(0..5).each do |index|
  # hacer algo con index
end


¿Por qué esto es mejor? Porque si el "each" es un método y no una construcción del lenguaje, quiere decir que el lenguaje me permite iterar de la forma que quiera. Ahora puedo separar el uso del "for" según para que lo quiera.

Las cosas más comunes para las que recorro una colección son para transformar los elementos en otra colección, filtrar los valores según alguna condición, o acumular en una variable. Entonces puedo tener métodos que hagan estas cosas, y en mi programa no voy a necesitar la iteración, porque en realidad lo que quería no era iterar sino hacer algo de más alto nivel a la colección.

En conclusión, es verdad que no hay nada que no pueda resolver con las construcciones más simples, y por lo tanto no hay un lenguaje más potente que otro, lo que sí hay son lenguajes más productivos.


Actualización, 12/12/11 8:56: Willy me encontró un bug, así que lo corregí... Había un loop que empezaba en cero e incrementaba multiplicando por dos, por lo que nunca iba a salir...

lunes, 14 de noviembre de 2011

RubyConf Uruguay 2011

Los días 11 y 12 de noviembre se llevó a cabo el evento RubyConf Uruguay 2011. Este año (es la segunda vez que se hace) tuve la suerte de poder ir.

El evento fue en el Auditorio de Antel que está muy bueno, nunca había ido.

El formato del evento fue de charlas de 30 minutos, de a una por vez (había una sola sala).

Oradores

Una cosa que me sorprendió fue el buen nivel de los oradores. Trajeron gente de varias partes del mundo (Argentina, Brasil, Chile, Estados Unidos, Alemania, Australia, Japón y seguramente alguno más...). Pero no solo eso, trajeron algunas personalidades importantes del mundo de Ruby, como por ejemplo Scott Chacon, uno de los creadores de Git, o Blake Mizerany, creador de Sinatra.

Una curiosidad con respecto a los oradores internacionales: varios de habla inglesa dieron su charla en español, pero todos los brasileros que vi (3 por lo menos) la dieron en inglés...

Audiencia

Siendo un evento técnico, para desarrolladores, la audiencia éramos todos (o la gran mayoría) desarrolladores.

Otra característica es que la inmensa mayoría eran hombres. Diría que un 95%, pero tengo miedo de quedarme corto...

Con respecto a la vestimenta de la gente, era sumamente informal. Y lo digo yo que durante años fui vestido de forma informal (pero no tanto) a los encuentros GeneXus... Había por ejemplo gente de la organización de short y chinelas, o expositores que dieron la charla de bermudas.

Otra cosa que me llamó la atención es que un buen número de las personas que asistieron estaban con su notebook, y lo tenían abierto y prendido durante las charlas. Los notebooks, habían muchas Macs, y las que no eran Macs por lo que se veía tenían Linux. Creo que no vi a nadie usar un Windows.

Organización

La organización estuvo bastante bien:
  • el wi-fi funcionó muy bien todo el tiempo,
  • las charlas empezaron y terminaron con una puntualidad bastante aceptable (claro, uno se mal acostumbra y lo compara con los encuentros GeneXus...),
  • el lugar en sí está bueno para un evento de este tamaño.

Charlas

Con respecto a las charlas, hubo momentos donde me perdí un poco, porque al no estar metido de lleno en la tecnología hay cosas que me resultaron demasiado específicas.

De todas formas, hubo varias que me gustaron. Creo que se pueden ver acá (aunque no probé...)
  • A Tale of Three Trees, por Scott Chacon sobre git, y más específicamente sobre el comando git-reset y como maneja internamente la última versión confirmada, los cambios para confirmar y el directorio de trabajo.
  • JRuby: Introduciendo Ruby en el mundo enterprise, por Jano Gonzalez.
  • Lean Startups for the Ruby Hacker, por Evan Henshaw-Plath.
  • Winning strategies in the battle against code smells, por Nigel Fernandes.
Hubo varios temas recurrentes, como metodologías ágiles de desarrollo, TDD o pair programming. De este último me llama la atención, porque hay varios que dijeron que usan pair programming todo el tiempo. Yo le veo la utilidad, pero más para cosas específicas. No se si me convencen de hacer pair programming todo el tiempo...

Conclusión

Me gustó el evento, creo que valió la pena ir. Sirve para salir un poco de lo que uno está acostumbrado y ver en que anda la gente de otras comunidades.

miércoles, 9 de noviembre de 2011

Por qué creo que Objective-C es mejor que Java

Hace unos días @GMilano hacía una comparación en Twitter donde decía que
Android vs iOS
IDEs:Eclipse > XCode
Language: Java > Objective-C
Framework: Cocoa > Android
Emulator: iOS > Android
Analysis: iOS > Android
y mi respuesta fue que
Casi de acuerdo, solo que Objective-C > Java... Pero, no es algo evidente al principio.
Esa respuesta tiene tiene una justificación, pero como verán lleva un poco más de 140 caracteres.

Aclaraciones:
  1. Trabajo con Objective-C desde hace unos dos años, pero hace mucho que no programo en Java en serio. Si cometo algún error en la comparación agradezco que me lo hagan notar.
  2. Hasta hace no mucho, tenía la idea de que todos los lenguajes de programación "modernos" eran más o menos equivalentes. Si tienen esa misma idea, primero lean este artículo de Joel Spolsky: Can your programming language do this?
  3. Muchas veeces uno no puede elegir (iOS = Objective-C, Android = Java), pero no por eso la comparación deja de ser válida :)
Extensibilidad de clases estándar

En Objective-C, uno puede agregar métodos a las clases estándar. Digamos por ejemplo que uno quiere agregar el método year a la clase NSDate para invocarlo con
int year = [myDate year];
en vez de hacer
NSDateComponents *comp = [[NSCalendar currentCalendar] components:NSYearCalendarUnit fromDate:myDate];
int year = [comp year];
Eso se puede hacer de forma muy simple, creando una "category" con la implementación
@interface NSDate (Helpers)
- (int)year;
@end
@implementation NSDate
- (int)year {
    NSDateComponents *comp = [[NSCalendar currentCalendar] components:NSYearCalendarUnit fromDate:self];
    return [comp year];
}
@end
Esto en Java no es posible. Se puede crear una subclase, o hacer un método estático en alguna otra clase, pero no modificar las clases ya existentes.

Blocks y selectors

En Objective-C, se pueden definir métodos que reciban un bloque de código o un "selector" (básicamente es el nombre de un método). En Java el pasaje de funciones por parámetro es bastante más complicado e involucra crear una clase específica que contenga el método.

Pasar funciones o bloques de código por parámetro permite por ejemplo implementar el método map: en la clase NSArray (combinando con lo que decía más arriba de las categories) de esta forma
- (NSArray *)map:(id (^)(id element))block {
  if (!self) {
    return nil;
  }
  NSMutableArray *tempArray = [[NSMutableArray alloc] initWithCapacity:[self count]];
  for (id element in self) {
    [tempArray addObject:block(element)];
  }
  return [tempArray autorelease];
}
¿Cuál es la gracia? Que si quiero construir un array a partir de otro, solo tengo que pasarle al método map: el bloque de código de la transformación, sin tener que escribir todo el código accesorio: crear el nuevo array, iterar, manejo de memoria, casos de borde (if !self), etc.

Además si en algún momento se hace alguna optimización o algún arreglo, queda para todos los que lo usan.

Manejo de memoria

En lo que tiene que ver con el manejo de memoria, tanto Objective-C como Java tienen Garbage Collector.

Claro, eso no es cierto para el caso de iOS... donde Objective-C usa una técnica llamada "reference counting". Si bien esto es más complejo para el programador, es mejor en tiempo de ejecución (si se hace bien) porque la memoria se libera en el momento que se deja de usar, no hay que esperar por un proceso que lo haga (GC)

Antes de iOS 5, era el programador que tenía que encargarse de retener/liberar los objetos, cosa que es bastante tediosa al principio y genera buena parte de los errores que cometen los novatos.

Con la liberación de iOS 5 y las herramientas asociadas, se incluye una nueva opción: dejar que el compilador se encargue. Esto se llama Automatic Reference Counting (ARC) y tiene lo mejor de los dos mundos: es mejor en tiempo de ejecución y no es una carga para el programador.

Sintaxis

Con respecto a la sintaxis, tengo que reconocer que ahí sí, Java le gana  a Objective-C. Tener que acceder a un elemento de un array con
[myArray objectAtIndex:0];
es bastante tedioso...

Por eso decía en Twitter que no es evidente que Objective-C es mejor que Java, porque la primer impresión que uno se lleva con el lenguaje es que es bastante complicado, sintácticamente hablando.

Conclusión

Estas son algunas de las diferencias que tienen ambos lenguajes. Seguramente hay muchas más, y alguno tendrá votos a favor para cualquiera de los dos lenguajes. Lo que quería con este post era justificar mi respuesta en Twitter, dando mi punto de vista al respecto.

En una próxima entrega agregaré también la comparación con C# y Ruby...

viernes, 4 de noviembre de 2011

Pésimo servicio de Movistar

Soy cliente de Movistar desde hace poco más de dos años, cuando les compre el iPhone.

En octubre de este año se me vencía el contrato que tenía, y como era más de lo que necesitaba, antes que se renovara automáticamente hice otro más barato y con menos prestaciones. El contrato nuevo entró en vigencia a partir del 1º de noviembre.

Con esto del nuevo contrato, ya había algo que me parecía abusivo por parte de Movistar, que paso a explicar. Cuando uno compra un iPhone tiene la opción de hacer un contrato a uno o dos años. Con el contrato a un año, el teléfono cuesta algo mas de $11.000. Con el que es a dos años, cuesta algo más de $7.000.

La diferencia de precio es obviamente porque con el contrato se paga parte del teléfono. Si no es así, que alguien me explique los $4.000 de diferencia.

Cuando llamé para decir que quería hacer otro contrato y que obviamente tenía que ser más barato, me dijeron que el único contrato que había con el iPhone era el que ya tenía. Pero bueno, después de explicar que no precisaba ese contrato, me dijeron que sí podía hacer otro...

Allá fuí entonces, a hacer mi nuevo contrato, y elegí uno que tiene cierta cantidad de tráfico para navegar por internet. Este es el que entró en vigencia el 1º de noviembre.

Lo primero que pasó con este contrato, fue que me decía que no tenía saldo, con lo que no podía hacer llamadas ni mandar SMSs, ni navegar por internet.

Después de la llamada para reclamar y esperar casi 24 horas, puedo hacer llamadas. Algo "curioso", es que dos minutos después de llamar para reclamar, me llegó un SMS que decía:
Te estas por quedar sin saldo! Envia CARGA al 550 para recargar $200 y lo pagas en tu proxima factura. Podes pedirlo una vez al mes. Vto. carga 60 dias
¿Habrá sido casualidad? Les voy a dar el beneficio de la duda, porque no quiero pensar que me mandaron publicidad engañosa, ya que tenía vigente un contrato con saldo...

Lo que no puedo hacer todavía es usar el plan de datos.

Hoy volví a llamar. Primero me dijeron que apagara el teléfono y probara en 10 minutos. Nada. Después que le sacara el chip. Nada. La tercera vez fue la que me hizo calentar, cosa que no es para nada sencilla.

La respuesta fue que el contrato que tengo no me sirve para usar con el iPhone, porque el iPhone precisa una conexión 3G especial.

Esto es absolutamente falso, y fue lo que le expliqué varias veces a la persona que me atendió, pero nada. Le terminé pidiendo que me pasara con alguien que me pudiera dar una explicación técnica, y después de esperar otros dos minutos, volvió para repetirme lo mismo que ya me había dicho.

Estoy con muchas ganas de ir a cancelar el servicio y volver a Ancel, pero lo que me hace dudar es que de esa forma pierdo el número.

¿Alguien tiene algún conocido en Movistar que me pueda dar una respuesta? En todo caso acepto sugerencias.

jueves, 3 de noviembre de 2011

Gmail.app

En el día de ayer, Google anunció la aplicación nativa de Gmail para iOS, y al rato la tuvieron que bajar... Yo fui uno de los afortunados que la llegó a instalar en el rato que estuvo en el aire :)

El motivo por el cual la bajaron, es porque da un error al entrar:


Lo que me llama la atención, es que haya pasado el filtro de Apple, esta gente se durmió en los laureles y están bajando el estándar...

Más allá de eso la aplicación está buena, y es más rápida que la aplicación de Mail de Apple, sobre todo para acceder a las etiquetas. Además tiene acceso al "priority inbox", que con la aplicación del iPhone no se puede acceder.

Una desventaja que tiene, sin embargo, es que no soporta múltiples cuentas, aunque supongo que eso lo van a resolver. Lo otro que no tiene son las notificaciones, que es por el error que muestra al entrar, que también lo van a resolver.

Con respecto a la aplicación, y sin saber demasiado como la hicieron, es bastante parecida a la interfaz web, por lo que parece que está hecha en HTML5, y lo que es nativo es el cascarón de afuera.

El mismo enfoque es el que tuvo Facebook con su última versión de la aplicación, con el objetivo de unificar los desarrollos en todas las plataformas.

¿Será que se está convirtiendo en tendencia?

miércoles, 5 de octubre de 2011

iPhone 4 vs. iPhone 4S

En el día de ayer, Apple en un evento especial, anunció el lanzamiento del nuevo iPhone, llamado iPhone 4S.

La información relativa al iPhone 4S ya está disponible en el sitio de Apple, donde cuentan las características y hay algún video explicativo.

No tenía intención de escribir sobre esto, pero Mauricio me preguntó por Twitter que me parecía, y no me dio para contestarle en 140 caracteres...


Las diferencias entre el iPhone 4 y el iPhone 4S

Como era de esperarse, hay varias cosas que cambiaron en esta nueva versión del teléfono de Apple.

Usa un procesador A5, en lugar del A4, que según dicen duplica la velocidad del dispositivo. También aumenta varias veces la velocidad de la tarjeta gráfica, fundamental para los que lo usan como una consola de juegos.

La cámara de fotos salta de 5MP a 8Mp, pero además tiene otras mejoras como la cantidad de luz que captura, la velocidad, etc. (no se mucho de fotografía, pero sí que la cantidad de pixeles no es lo único que importa).

La duración de la batería creo que es de los puntos más fuertes. En estos dispositivos, la batería es un problema. Si uno pretende usar el teléfono todo el día sin cargarlo, tiene que estar cuidando no quedarse sin batería. Según dijeron, el iPhone 4S mejora mucho en este aspecto.

Actualización, 12:03: Me hace notar @palsina que la duración de la batería aumenta para hablar, pero baja de 300 horas a 200 en "stand by". Habrá que ver como afecta esto la duración global de la batería... Más información en http://www.apple.com/iphone/compare-iphones/

Por último anunciaron Siri, un asistente personal al que se le puede hablar en lenguaje natural para pedirle que haga cosas como consultar el estado del tiempo, agendar una cita en el calendario, contestar un mensaje de texto, buscar en Wikipedia, y muchas otras cosas más. Lo que no me quedó claro es si es solo para el 4S o si es una funcionalidad de iOS 5. Seguramente precise del procesador más rápido para algunas cosas...

Lo que no se anunció

El nombre, llamarlo 4S en vez de 5, fue una decepción para varios.

Como siempre en estos eventos, había mucha expectativa y mucha especulación, con lo que siempre hay gente que pronostica de más...

Se pensaba que podía haber un iPhone 5 y un iPhone 4S más barato, lo que no sucedió.

También se suponía que iba a contar con un chip NFC (Near Field Communication, para pagos móviles como tiene Google Wallet), que no apareció.

La tecnología 4G, aunque no muy difundida aún, también era algo con lo que se especulaba.

A mi personalmente me hubiera gustado un cambio de forma. No he usado mucho el iPhone 4, pero me parece más cómodo de usar el 3GS con la parte de atrás redondeada, como que se ajusta mejor a la mano.

Entonces, ¿qué me pareció y qué pienso hacer?

Actualmente tengo un iPhone 3GS que ya tiene 2 años, y estoy con ganas de cambiarlo.

Del iPhone 4S, lo que más me motiva es la duración de la batería. La velocidad del procesador también me parece que está bueno tenerlo, pero con el 3GS tengo buen rendimiento, no creo que con el 4 tuviera problema.

La cámara no me motiva demasiado. Sí, está bueno tener una cámara mejor, pero solo eso no me motiva a cambiar.

Siri parece interesante, pero por ahora solo va a estar disponible en inglés, francés y alemán, por lo que no me parece que lo vaya a usar mucho al principio. Además no me veo dandole órdenes al teléfono con la voz... Sí está bueno para probarlo y ver que han hecho de inteligencia artificial :)

De las cosas que no tiene, el 4G y el chip NFC no me cambian nada, porque de todas formas en Uruguay no los iba a poder usar.

Que hubiera un iPhone 5 con estas cosas agregadas y un 4S con lo que anunciaron ayer sí hubiera estado bueno, para poder comprar el 4S más barato :)

El tema de la forma del teléfono sí es un punto en contra para el 4S, porque me hubiera motivado más tener algo más parecido al 3GS...

En conclusión: cuando llegue el 4S a Uruguay voy a cambiar mi 3GS. Lo que todavía no me decidí es por cual, si por el 4 o por el 4S. Dependerá de la diferencia de precio que haya entre uno y otro, y si la duración de la batería justifica pagar esa diferencia.

jueves, 15 de septiembre de 2011

Encuentro #GX21

Pasó otro encuentro GeneXus más, y este año me tocó vivirlo desde el otro lado, desde el lado de la organización.

Se vive distinto, pero no tanto el evento en sí, sino más bien la previa, donde vi lo que trabajaron todos para llegar con todo pronto en fecha.

Del evento en sí, el estar adentro le quita el componente de la sorpresa, de ver en que estuvieron trabajando en el último año. Así y todo, hubo momentos en los que tuve que elegir, porque había más de una charla que me interesaba.

Este año no me dio el tiempo de hacer una reseña por día como venía haciendo en años anteriores, así que hago una sola con los tres días.

Lunes

Sobre las charlas, vi las primeras, de @breogan_gonda, @guscarr y @gmilano en la sala 4CR donde se trasmitían en vivo, porque la 2B quedo chica... Como introducción estuvieron muy bien, para que todos estemos más al tanto de lo que se iba a hablar en el resto del evento. Lástima que a @guscarr no le anduvo apagar la lámpara desde el teléfono...

La de @arminbachmann y @rorro sí la vi en vivo (pero parado al fondo porque tampoco había lugar) y estuvo muy bien. Los diálogos salieron muy naturales :). En resumen, hicieron una aplicación móvil (para las tres plataformas) en 50 minutos... Como toda charla con demo en vivo, les falló cuando quisieron hacer el "deploy to cloud" por un tema de red, pero pruébenlo que funciona :)

La charla "A que le llamamos distancia" por @cimasan y Fabian Bonilla estuvo buena, contando la experiencia de vivir en Japón. No es fácil... Saliendo de lo técnico, estuvo muy interesante.

La última que vi en la mañana fue la de @pablobrenner donde presentó una nueva red social para cuidar el medio ambiente: Greentizen. La idea es interesante, pero no se si va a funcionar... se supone que uno va a comentar y proponer acciones en las redes sociales, y ganar puntos por eso.

En la tarde llegué al final de la otra charla de @cimasan, así que no vi mucho.

Después fui al 15/15 de GeneXus Cotidiano. Fueron varias presentaciones cortas con tips, que me resultaron algunos demasiado específicos (por ejemplo relacionados con DBFs...), y con mucho cambio de tema muy rápido. La otra queja es que no se usaron PPTs, se presentó desde una página del wiki que no se veía nada desde el fondo. Cosas para mejorar de una charla que vale la pena tener en los encuentros.

La charla de @frascafrasca como siempre muy entretenida. Habló sobre "gamification", es decir, como usar técnicas usadas en los videojuegos, pero en la vida real. Véanla...

Después vi la segunda parte de la charla donde se presentaron los proyectos del Smart Challenge. Está bueno ver en las cosas que estuvieron trabajando.

El keynote de Mike Culver, estuvo interesante, fue una mezcla entre una charla comercial y una charla técnica.

La charla deportiva de @njodal estuvo buena, como siempre bien dada y amena. Habló sobre "exaptación" (sí, yo tampoco lo había oído nunca...). Básicamente presento un modelo para estudiar que hace que se produzca determinado comportamiento. Es un modelo que involucra la motivación, la habilidad y disparadores. Véanla...

Martes

El martes arranqué viendo las charlas de Silvia Keymetlian primero y luego de @PabloMazzilli, donde mostraron como hacer una aplicación y después la arquitectura de las aplicaciones para Smart Devices. Estuvieron las dos muy bien, con conceptos claros y bien explicadas. Si se van a meter en el tema, son recomendables.

Después estuve en la charla de DVelop, que presentaban el pattern WorkWithPlus. La verdad que parece estar muy bueno el pattern. Por lo que mostraron parece muy completo.

A las 11 estuve en el Café con Comunidad, en el piso 25. Espectacular la vista, les dejo un par de fotos que puse en twitter.



El café en sí estuvo bueno, se habló principalmente de user controls y Marketplace, a pesar que el tema era "comunidad". Pero bueno, esa es la dinámica de estas charlas...

Luego fui un rato a la charla que dió Marcelo Vignolo de Concepto sobre precintos electrónicos en la aduana. No es de las charlas que suelo ir, pero parece interesante el sistema que están haciendo. El problema es que media hora se pasa volando, y entre que el café se extendió unos minutos más y bajar del piso 25 lleva tiempo, llegué cuando ya iban por la mitad...

La charla de @martinoliveri sobre el GeneXus Marketplace estuvo interesante, contó algunas cosas que se han hecho para mejorar el sitio y las que se tienen pensadas a futuro.

Después fui a la charla de Alejandro Blengio sobre como publicar aplicaciones en las distintas "stores" de Apple, BlackBerry y Google. Yo sabía que publicar una aplicación en la tienda de Apple era complicado, porque involucra varios pasos, pero me quedo tranquilo que en las otras dos tampoco es trivial...

A las 15:00 estuvo mi charla. Pueden ver el video en el sitio del eventobajar las PPTs, o verla en SlideShare.

A continuación tuve el cara a cara de Smart Devices, por suerte con un break de 15 minutos para poder cambiar de sala.

El keynote de Juan Grompone fue interesante, pero me resultó un poco pesado. La presentación tenía demasiado texto, y por momentos se hacía difícil de seguir...

A la charla de @eliax fui un rato, pero no me pude quedar hasta el final, así que la veré después...

Miércoles

El miércoles arrancamos temprano con el cara a cara con desarrollo. Como siempre en estas charlas, a las 8 había poca gente, pero fueron llegando y a las 9 terminamos a sala llena. Hubieron varias preguntas, por suerte no me tocó responder ninguna :)

La charla de Gastón sobre el generador de Smart Devices empezó unos 10 minutos tarde, porque hubo que sacar las sillas que estaban en el escenario y lleva tiempo. Contó básicamente las cosas en las que se estuvo trabajando, cual es el roadmap de la Evolution 2 de aquí en más (liberar una RC antes de fin de año y la versión Release poco después), y las cosas que están faltando.

Luego vino la charla de @finthamoussu, donde contó cual es el estado actual de la plataforma iOS y lo que se viene en la versión 5. Una lástima que no pudo hacerla por AirPlay, porque el proyector no tenía entrada HDMI que es la salida del Apple TV...

A continuación fui a ver la charla que daba la gente de Concepto sobre su experiencia con GXtest. Por lo que contaron, los comienzos fueron duros, con una herramienta que no estaba del todo estable, pero hoy a un año de haber empezado con la experiencia, tienen buenos resultados y van a seguir por ese camino. Una buena noticia, porque se precisaba en la comunidad una buena herramienta de testing.

Después vi la charla de @minipanizza sobre Android. Contó sobre la plataforma, sobre lo que si hizo en GeneXus y sobre lo que queda por hacer antes de liberar la Evolution 2.

Lo irónico es que Fabian hizo la charla sobre iOS con fondo negro, y Fernando la de Android con fondo blanco, al revés de lo que se usa en cada una de las plataformas :)

La charla sobre pagos móviles estuvo interante también. Contaron algunas de las cosas que hay a nivel mundial y lo que hay disponible en Uruguay, que por ahora no es mucho. Algo de VISA y algo de OCA Cel, pero muy limitados a cosas específicas. Pronostican que va a haber una explosión de este tema en la región en los próximos años. Veremos.

En la charla "Las crónicas de Smart Devices: El termómetro, la lámpara.. y GeneXus!" se mostró algo bien distinto a lo que estamos acostumbrados a ver con GeneXus: una aplicación que controla dispositivos físicos como por ejemplo un portón o el encendido y apagado de una lámpara. Lo que hicieron fue un external object que encapsula la interacción con un controlador que permite interactuar con estos dispositivos físicos, y lo invocan tanto desde un web panel como desde una aplicación móvil.

En la tarde del miércoles tuvimos una charla motivacional por parte de Alfredo Barragán, capitan de la expedición Atlantis que en 1984 atravesaron el océano Atlántico desde las Islas Canarias hasta Venezuela en una balsa sin timón. Me resultó más interesante el video con el que abrieron la charla contando sobre la expedición, que la charla en sí, pero bueno, tampoco soy muy fanático de este tipo de charlas...

Luego vino el keynote de @njodal donde habló sobre el estado actual de la industria, sobre GeneXus y sobre la comunidad.

Por último estuvo el cierre por parte @breogan_gonda, invitando a que hagamos aplicaciones, ya que tanto la tecnología, como la comunidad y la actitud están.

Las que me faltaron ver

Hubieron varias charlas que me faltaron ver, porque tenía alguna otra charla o actividad al mismo tiempo.

Dejo una lista de las que no vi, e iré viendo de a poco en el sitio del evento:
  • Que aprendí haciendo PesoBook, por Juan Mateo
  • Mesa redonda de Cloud Computing
  • Avances, novedades y futuro de GeneXus Server, por José Lamas
  • Las más lindas son mejores, por Ursula Bartram y Ma. Ines Carriquiry
  • Native applications Rock!, por Franklin Buitron
  • La vuelta al mundo en 80 pixels, por Javier Larrosa
  • Mesa redonda, el PC ha muerto?
  • Desarrollando aplicaciones seguras con GeneXus, por Alejandro Silva
  • Probar GeneXus code con GeneXus code
  • ¿Qué hace y cómo se utiliza la Seguridad Integrada a GeneXus?, por Alejandro Zeballos
  • Plataforma BB: overview y estado del arte, por Felipe Herrera
Cosas para mejorar

La organización del evento fue espectacular como siempre, pero igual hay algunos puntos que me parece se puede mejorar:

  • Programa impreso: este año no se entregó programa impreso, porque estaban las aplicaciones en las tres plataformas. Sin embargo, hay mucha gente que no tiene un "smarte device", y se vio gente con el programa impreso desde el web o mirando el que se había pegado en una pared en el segundo piso. Creo que se debería tener la opción de tenerlo impreso...
  • Las conferencias son cortas, de media hora, y no se tiene en cuenta el tiempo que lleva el cambio de orador. Entre las charlas que no hay un break, el programa debería contemplar tener 5 minutos entre charla y charla, para poder hacer el cambio más tranquilo. Además le permite a la gente cambiar de sala, que a veces implica subir o bajar de piso.


martes, 6 de septiembre de 2011

El futuro de la televisión es internet

Ya hace un tiempo que estaba con ganas de escribir sobre este tema, y no encontraba tiempo para hacerlo. Pero visto los anuncios de los últimos días, es ahora o nunca...

Hace unos meses, cuando acá en Uruguay se discutía sobre que norma de televisión digital usar, si la japonesa o la europea, yo pensaba que la discusión iba mal encaminada. Para el 2015, cuando empiece a funcionar este sistema, ya va a ser obsoleto, porque la batalla la habrá ganado internet.

Me terminé de convencer hace un par de meses, cuando "descubrí" el sitio cuevana.tv. Es un sitio que se dedica a catalogar series y películas (hosteadas en otros sitios) y que permite verlas on-line. La calidad del contenido no es espectacular, pero es más que aceptable

Ahora a partir de mañana, además de cuevana.tv que es un servicio "ilegal" (más sobre esto en seguida), en la región va a estar disponible Netflix, que es completamente legal. El costo además es muy barato comparado con los servicios de televisión por cable (U$S8 contra unos U$S40 por mes).

Hay que ver que contenidos trae Netflix para la región, pero que se cuiden los cables o se van a quedar sin negocio...

Las ventajas de poder ver una película por internet son muchas, pero yo creo que la principal es que la puedo ver en cualquier momento, y no a la hora que el proveedor de cable quiere que la vea.

Sobre la ilegalidad de servicios como cuevana.tv

No se mucho de leyes, pero me parece difícil que ver contenido on-line sea ilegal. Es decir, si veo un video en YouTube (por poner un ejemplo), no creo que esté haciendo nada ilegal, aunque no sepa si el que subió el video tenía los derechos de autor o no. Lo mismo si escucho música en Grooveshark...

Tampoco lo que hace cuevana.tv parece ilegal, porque ellos ni siquiera tienen los archivos en sus servidores. Simplemente tienen un catálogo de links y un reproductor de videos que se ejecuta en el navegador del cliente. Probablemente sí sea ilegal subir las películas si no tengo derecho de autor...

Pero volviendo a la parte de consumir contenido. Puede que no sea ilegal, pero ¿es inmoral?

Supongamos que tengo contratado un servicio de televisión por cable, que tiene un determinado canal que transmite una serie que quiero ver, pero en un horario que no me sirve. ¿Es inmoral verlo en internet? ¿Por qué habría de serlo, si ya pagué por ese contenido?

En todo caso, lo inmoral es que los proveedores de cable no nos permitan ver el contenido en el momento que nos queda mejor... O que cobren 5 veces más caro que un servicio similar...

Claro, ver algo por lo que nunca pagué, seguramente sea más discutible, y no me voy a meter en ese tema.

De todas formas, creo que un servicio pago, al precio que propone Netflix, puede tener ventajas como por ejemplo mejor calidad de los contenidos o más variedad. Habrá que esperar a ver que ofrecen.


jueves, 18 de agosto de 2011

La simplicidad de Ruby

Una de las cosas que me gustan de Ruby, es la simplicidad.

Hoy necesitaba generar números hexadecimales de largo 24, de forma aleatoria, así que me hice un programita...

Hay seguramente muchas formas de hacerlo, yo elegí esta:

Seudocódigo:
24 veces:
  elegir un dígito aleatorio entre 0 y F (hexadecimal)
  imprimirlo
Código Ruby:
hexaDigit = ('0'..'9').to_a + ('A'..'F').to_a
24.times do
  print hexaDigit[rand(16)]
end
Simple, ¿no? Se puede escribir más corto, pero no mucho más claro que esto...

sábado, 13 de agosto de 2011

Primeras impresiones de OS X Lion

Hace unos días me instalé Lion, la última versión de Mac OS X.

Hay varias cosas que han cambiado, algunas más notorias que otras. Si quieren leer algo mucho más completo (y mucho más largo también), les recomiendo el review de ars technica

No estaba dentro de mis planes instalarlo tan pronto, pero al final lo tuve que instalar para probar algunas cosas que geolocalización de GeneXus que precisaba el SDK de iOS 5...

Instalación

La instalación fue realmente muy sencilla. Lo único que tuve que hacer fue desinstalar XCode, que igual quería instalar la última beta (4.2), así que lo iba a desinstalar de todas formas...

Después de eso, lo único que hice fue meter el disco (sí, me lo pasaron en DVD, si no hay que bajar como 5GB) y darle "next" a unas cuantas pantallas.

Demoró media hora aproximadamente, y cuando levantó ya estaba con la versión nueva. No tuve ningún problema de compatibilidad de aplicaciones ni perdí ningún dato de lo que tenía en Snow Leopard.

Gestos

Ya en Snow Leopard se podían usar gestos en el trackpad, pero en Lion parece que son bastante más importantes.

Hay gestos para varias cosas: dos dedos para hacer scroll, tres dedos para mostrar Mission Control o las ventanas de la aplicación actual, pinch para mostrar el Launchpad o el escritorio, etc.

Scroll

Dentro de los distintos gestos, hay uno que se destaca por haber tenido un cambio significativo: el scroll.

En todos los sistemas operativos de escritorio, cuando uno quiere moverse hacia abajo por ejemplo en una página en un navegador, mueve los dedos o la ruedita del ratón hacia abajo. Es decir, se indica hacia donde quiere que se haga el movimiento.

En iOS esto es al revés. Si quiero ir hacia abajo, lo que tengo que hacer es mover el contenido hacia arriba, por lo que selecciono y muevo el contenido de la página.

En Lion, el comportamiento por defecto es como en iOS (aunque se puede cambiar) y al principio marea un poco.

Lo curioso es que en dos o tres días me acostumbré y ahora hago el scroll bien (casi siempre...)

Mission Control

Es la aplicación que permite ver todas las ventanas y aplicaciones a pantalla completa que tengo corriendo en el momento.

Es práctico, está bien diseñada, y funciona. No tengo mucho más para decir...

Launchpad

Esta aplicación se agregó para poder tener una forma fácil y centralizada de ver todas las aplicaciones instaladas. La interfaz de usuario es una copia casi exacta de la pantalla principal del iPad.

De todas formas la carpeta de aplicaciones sigue estando en el Dock, se ve que no se animaron a sacarla.

Conclusión

Creo que es una versión que se puede instalar porque funciona muy bien.

Hay varias cosas que cambiaron, y las que tienen que ver con la experiencia del usuario, la mayoría fueron cambios para que se parezca más a iOS. Parece que ese va a ser el rumbo a partir de ahora.

miércoles, 27 de julio de 2011

Métodos privados y "protected" en Objective-C

El lenguaje Objective-C tiene algunas cosas a las que todavía no me termino de acostumbrar, después de más de un año de estar trabajando con él.

Una de estas cosas es la visibilidad de los métodos.

Me explico: en los lenguajes orientados a objetos, se suele tener por lo menos tres tipos de métodos: públicos, que son accesibles por todos; privados, que son solo accesibles dentro de la clase que los define; y "protected" que son visibles para la clase que los define y para sus clases derivadas.

Métodos públicos

En Objective-C todos los métodos son públicos, en el sentido que siempre se pueden ejecutar aunque no estén declarados como tal.

Para declarar un método como público y que quede visible para el resto del mundo, simplemente se declara en la definición de la clase en el .h

Métodos privados

Si bien cualquier método se puede invocar, los que no están declarados en el .h son considerados privados.

Al no declararlos en el .h, no es fácil conocer la firma de estos métodos, por lo que tampoco es fácil invocarlos. Además, si se usa un método privado, el compilador muestra un aviso que puede ser que el objeto no responda a ese método.

Métodos protected

En el lenguaje no hay forma de definir un método como protected. Lo que mejor que se puede hacer, es definirlo como privado, y documentarlo de alguna forma.

El problema es que al definirlo como privado, el compilador va a dar un warning de que no existe el método.

El "work arround" que encontré, es volver a declararlo en una categoría, para que el compilador sepa que existe.

Supongamos que tenemos una clase MySuperClass, que define un método privado
-(void)myProtectedMethod
y que tengo una clase MyDerivedClass que hereda de MySuperClass.

Si quiero usar el método en MyDerivedClass sin que me de un warning, puedo en el archivo MyDerivedClass.m, declarar una categoría para MySuperClass donde defino este método. Suena complicado, el código no lo es tanto.
// MyDerivedClass.m

#import "MyDerivedClass.h"

@interface MySuperClass (Protected)
-(void)myProtectedMethod;
@end


@implementation MyDerivedClass
...
@end

No se si es la mejor opción, pero es efectiva. Por supuesto, si alguien lo resolvió de otra forma, son bienvenidos los comentarios.

sábado, 23 de julio de 2011

Layout Enabled y nuevos controles

En el Night Build del 20 de junio de GeneXus X Evolution 2, aparece una nueva propiedad en el IDE, para los objetos de tipo Work With Smart Devices: Layout Enabled.

Esta propiedad está a nivel del Detail del pattern, e indica como dice su nombre, si se toma en cuenta el layout definido en el objeto (poniéndola en true), o si se dibuja un campo debajo de otro como se hacía hasta el momento (dejándola en false que por ahora es el valor por defecto).

Además de respetar el layout definido en el objeto, permite usar controles que antes no estaban disponibles.

Estos son algunas de las cosas en las que estuve trabajando y ahora quedan visibles.

Tab control

El Tab control permite agregar componentes en distintos tabs.


En la imagen se ven solo los tabs sin datos, porque fue como me quedó el ejemplo, también se pueden poner datos...

No se si en el último Night Build ya está en el IDE el control tab, pero si no está sale en el próximo...

Wheel control

Permite elegir valores usando una ruedita.

Funciona para enumerados y para campos numéricos, en estos últimos se le dice el rango de valores y el step, es decir, cuanto varía entre cada valor. Si el step es un decimal (por ejemplo 0.1 como en la imagen), se muestra una ruedita para los enteros y otra para los decimales.



Mapas a pantalla completa

En el iPad, se puede hacer que la aplicación se ejecute a pantalla completa (por defecto usa un split view: las listas a la izquierda y los detalles a la derecha). Para que ejecute a pantalla completa, hay que cambiar una propiedad: Navigation Style = Flip.

En este caso, cuando se usa el control SD Maps, se oculta la barra de navegación y la toolbar, quedando el mapa a pantalla completa (esto va a ser opcional mediante una propiedad, hoy es siempre que se pone Flip).


También se ve en la imagen, que cada uno de los marcadores usa una imagen distinta. Esto también es nuevo. Se agregaron dos propiedades para el control SD Maps: Pin Image y Pin Image Attribute. La Pin Image es una imagen estática, y usa para todos los marcadores la misma. El Pin Image Attribute permite poner una imagen distinta para cada marcador.

Sobre el uso de estas funcionalidades

Todas estas cosas van a estar disponibles en todos los generadores, aunque en este momento es posible que solo estén en iOS... así como también hay cosas que solo están en Android o en BlackBerry.

Además en general no van a funcionar con el Knowledge Base Navigator que está en el App Store, porque esa versión está sincronizada con la beta 3 y estos cambios son (pueden ser...) posteriores. Si los quieren usar, van a tener que compilar la aplicación usando una Mac o esperar a la próxima versión del KBN.

También aclaro que esto son solo algunas de las cosas que hay, y en particular son algunas en las que trabajé yo. En los Night Builds hay muchas más cosas, que se anuncian en el wiki.

sábado, 25 de junio de 2011

Música para correr

Hace un tiempo encontré el sitio jog.fm, que permite buscar música para correr, con la particularidad que busca la música más adecuada para el ritmo que uno elige.

Por ejemplo, se puede buscar música para correr a 6 minutos por km, y encuentra canciones que sirven para correr a ese ritmo.

También sirve para buscar música para otras actividades, como caminar o andar en bicicleta.

En el sitio se pueden escuchar las canciones, comprarlas en Amazon o iTunes, armar listas de reproducción (que no se como la escucho mientras voy corriendo...), escuchar listas de otros usuarios, etc.

Además tienen una aplicación para el iPhone, pero no me convenció demasiado. La aplicación procesa toda la biblioteca, y cuando uno va a hacer ejercicio puede decirle a que ritmo quiere correr o que detecte el ritmo automáticamente. Supuestamente se van a reproducir las canciones adecuadas.

Digo supuestamente porque hice una prueba y me parece que no me funcionó muy bien. Algunas mejoras que le haría:

  1. poder elegir música de una lista, yo ya tengo una que se llama "música para correr"...
  2. tener alguna forma más fácil de decirle que canciones no quiero que use, por ejemplo un botón en el reproductor.
Con esos dos cambios sí sería más usable.

Sobre la corrida

En mi punto más alto (diciembre 2010 - enero 2011), llegué a correr 7km hasta tres o cuatro veces por semana, y corrí una carrera de 10km, de esas que hay un montón en primavera.

Desde ahí, vengo bajando. Primero en frecuencia y después en distancia. Es impresionante como se va perdiendo el estado físico por la falta de ejercicio. Ahora estoy corriendo una vez por semana (sábado o domingo, porque entre semana es imposible), y corro 5.7km. Pero cada vez cuesta más...

Lo bueno es que aumentar la distancia y mejorar el tiempo es algo relativamente fácil, si uno tiene la constancia necesaria. Cuando empecé, en agosto de 2010, hacía un recorrido de 2.5km, y a veces no me daba para hacerlo todo corriendo. De a poco fui subiendo, primero 3.5km, 4.5km, 6km, hasta llegar a los 7km y la carrera.

Así que cuando vuelvan los días más largos, trataré de salir a correr más seguido para estar mejor que en mi mejor época :)

Una mención especial

Hay dos canciones que se ajustan particularmente bien a mi ritmo de corrida. No las encontré en jog.fm, ya las tenía en mi biblioteca. Se las dejo para que las escuchen (en un dispositivo que soporte Flash...):

 The Ramones - I Wanna Be Sedated

 Astroboy - Did I Tell You?

jueves, 16 de junio de 2011

Subversion vs. Git

Cuando se habla de control de versiones, hay dos grandes formas de encarar el tema: centralizado o distribuido.

Durante un año estuve usando Git (un sistema de control de versiones distribuido), y ahora hace un mes y medio que estoy usando Subversion (que es centralizado).

Lo que sigue es un intento de comparar ambas herramientas, desde mi punto de vista personal, sin intención de hacer una comparación exhaustiva ni del todo objetiva.

Lo primero que hay que aclarar es que ni Git es del todo "distribuido" (ya que se suele mantener un repositorio centralizado), ni Subversion es totalmente centralizado (porque se trabaja sobre una copia local). La diferencia en realidad es donde ocurren las operaciones (branch, commit, etc.). En el caso de Git (y los demás que son distribuidos como Mercurial), las operaciones son locales, mientras que en Subversion ocurren en el servidor.

Esto quiere decir que en Git puedo hacer N commits antes de mandar los cambios al servidor, mientras que en Subversion cada commit se hace en el servidor.

Algunas consecuencias de esto son que:
  1. En Subversion los números de cada revisión son consecutivos, mientras que en Git cada commit se identifica con un UUID
  2. En Git puedo hacer commits intermedios, sin necesidad de tener una versión "estable", porque puedo hacer el push al final. En Subversion, cuando hago un commit tengo que tener una versión consistente antes de hacer el commit para no romper nada que pueda necesitar alguien más. Ese commit puede ser eventualmente bastante grande.
Otra diferencia es que en el caso de Git, no es posible hacer un "checkout" parcial, lo que es bastante natural en Subversion. Por lo tanto, si el repositorio es grande, obtener la versión inicial puede ser bastante más costoso con Git.

Una de las cosas que no me convencen del todo de Subversion, es que no puedo dejar un cambio por la mitad, para hacer por ejemplo un arreglo en la última versión estable. En Git, aunque tenga cambios pendientes, puedo moverlos a un nuevo branch, arreglar lo que sea que estuviera roto, y volver a poner arriba de eso los cambios que moví temporalmente. En Subversion, la mejor alternativa que encontré a esto, sería hacer un checkout en otro directorio para hacer el arreglo ahí.

Eso nos lleva a otra diferencia: en Git hacer un branch es totalmente natural. De hecho, cada copia local puede verse como un branch. Llevado al extremo, hay quienes hacen un branch para cada nueva feature que van a estar trabajando. En Subversion, un branch se usa solamente para congelar una versión, y no es posible hacerlo de forma local.

Por último, hace unos días apareció esta noticia, que dice que GitHub es el repositorio más popular (para proyectos open source al menos). Puede ser un punto a considerar al momento de elegir.

En conclusión, si me dan a elegir, me quedo con Git. Pero lo verdaderamente importante, sea cual sea la herramienta que se use, es tener algún tipo de manejo de versiones.

Si alguien se quedó con ganas de saber más, acá les dejo una comparación más seria de los dos.

miércoles, 8 de junio de 2011

User Controls para iOS, parte 2

Hace unos días les contaba que estuve trabajando en un User Control para el generador iOS (una galería de imágenes), y que se estaba trabajando en un mecanismo para poder definir controles desarrollados por terceros.

Hoy ese mecanismo ya está funcionando (build superior a 44260), y de hecho en este momento tenemos 4 user controls externos, tres para listas (image gallery, maps y chart)[1] y uno para atributos (star rating).

El código de los user controls está disponible y se distribuye con GeneXus, los pueden ver en la carpeta iOS/UserControls/src (build superior a 44297)

Como decía más arriba, hay dos tipos de user controls: los que aplican a una lista y los que aplican a un item (un atributo por ejemplo). La forma de implementarlos es distinta, y de hecho heredan de clases diferentes.

Así que si alguien tiene alguna idea de un user control que quiera desarrollar, me avisa que le paso la versión alfa de la documentación. Eventualmente quedará disponible en el Wiki, pero por ahora no está...

Les dejo una foto del Star Rating, que fue el otro control en el que estuve trabajando.


[1] Cabe aclarar que los controles map y chart no los hice yo... yo solo los moví a otro proyecto.

Actualización, 9/6/2011 9:50: @a_cardoso actualizó la documentación en el wiki. Pueden ver acá y acá.

viernes, 13 de mayo de 2011

User Controls para Smart Devices

La primera tarea que me tocó en mi nuevo trabajo en Artech, fue la de desarrollar un User Control para el generador de iOS, para poder mostrar una lista en forma de galería de imágenes.

El control se llama "SD ImageGallery", y ya estaba disponible para Android. Acá les dejo la documentación que hay en el wiki.

La versión para iOS va a estar disponible en la próxima versión del KB Navigator... Está basado en el control KTPhotoBrowser (con algunas modificaciones), que tiene una licencia MIT.

Para usarlo, es muy fácil. Simplemente en el patter Work With Smart Devices se selecciona el View correspondiente a la lista (el pattern define vistas para el master, que es una lista, y para el detail, que muestra un item determinado), y se cambia la propiedad "ControlType" a "SD ImageGallery".

Si no se configura nada más, toma la primer imagen que haya disponible en el registro (no es determinístico si es que hay más de una). Sin embargo se le puede decir, también en las propiedades, que atributo contiene la imagen que queremos mostrar, cual es el que tiene el título y cual el que tiene la descripción.

Pero lo interesante del caso, es que es un User Control. Esto quiere decir que en los generadores para Smart Devices, se van a poder definir controles implementados por terceros.

Por ahora el mecanismo para hacerlo está muy verde (o no está...), y este control en particular se desarrollo dentro del mismo proyecto que el resto del KB Navigator, pero la idea es poder hacerlo por fuera y que se pueda integrar de alguna forma.

Obviamente el desarrollo de User Controls no va a ser para cualquiera, porque requiere tener conocimientos en el desarrollo de la plataforma (Objective-C y la API para iPhone en este caso), pero va a abrir posibilidades para los que quieran publicar controles, como se hace hoy en web mediante el Marketplace.

Así es como se ve en el iPhone:

lunes, 2 de mayo de 2011

Cambio de trabajo

Hace unos 11 meses, anunciaba en el blog, después de unos cuantos años de estabilidad laboral, que iba a cambiar de trabajo. Hoy escribo para hacer un anuncio similar. Espero que no se me esté haciendo costumbre ;)

Desde junio de 2010 vengo trabajando full-time para Alkeo, una empresa francesa que se dedica al desarrollo de aplicaciones móviles (aunque había empezado a hacer alguna cosa con ellos desde noviembre de 2009). Todo este tiempo estuve trabajando en el desarrollo de aplicaciones para iPhone/iPad, y también algún back-end en Ruby on Rails.

El trabajo para Alkeo fue muy interesante, tanto por las cosas nuevas que tuve que aprender como por la modalidad de trabajo (a distancia, desde casa, con coordinación por mail), que era nueva para mi.

Pero ahora surgió otra oportunidad, así que decidí cambiar...

A partir de mañana (3 de mayo de 2011) voy a estar trabajando para Artech, en el equipo de desarrollo de GeneXus, en principio en el generador para iOS (iPhone y iPad).

jueves, 14 de abril de 2011

fbcmd: listar los próximos cumpleaños

Hace unos días escribí sobre fbcmd, como forma de consultar la actividad de los amigos en Facebook.

Lo que no encontré, fue una forma de ver cuales son los próximos cumpleaños, así que hice mi propio comando :)

Este es el código del nuevo comando:



Para usarlo, hay que seguir los siguientes pasos:

  1. Bajar el archivo
  2. Copiarlo a /usr/local/lib/fbcmd/support (en Mac OS X, no se en otros sistemas)
  3. Ejecutar php /usr/local/lib/fbcmd/support/birthdays_fbcmd.php BIRTHDAYS
  4. Se le puede pasar una lista de amigos y la cantidad de items a mostrar. Por ejemplo,

    php /usr/local/lib/fbcmd/support/birthdays_fbcmd.php BIRTHDAYS _familia 5
    lista los 5 primeros cumpleaños de los amigos que estén en la lista "familia".

miércoles, 13 de abril de 2011

El final de la democracia (representativa)

En Uruguay existe la llamada Ley de Caducidad, que da amnistía a policias y militares por los crímenes que cometieron (torturas, asesinatos, desapariciones, etc.) durante la última dictadura militar (1973-1985).

Es una ley que fue votada en el parlamento en 1986, confirmada en un referendum (ya que se juntaron firmas para intentar derogarla) en 1989, y confirmada nuevamente por la ciudadanía en un plebiscito en el año 2009, al no alcanzar el 50%+1 necesarios para su anulación.

Ayer el senado uruguayo, aprobó una ley interpretativa que la deja sin efecto, yendo en contra de la opinión del pueblo. Todavía falta que la apruebe la cámara de diputados, pero es un hecho que va a ser así.

Antes de seguir, quiero hacer dos aclaraciones:

  1. Cuando se me preguntó en 2009, voté por anularla. Por las dudas que alguno crea que escribo esto por estar en contra de este hecho en particular...
  2. No estoy de acuerdo en como se realizó el plebiscito de 2009. No había forma de no participar. Si uno quería anular la ley, debía poner una papeleta por el SÍ. Para dejarla como estaba, no había que hacer nada. Eso quiere decir que hubo gente que no puso papeleta ya sea por desconocimiento, o porque no quería participar, votando explícitamente al NO. Si además le sumamos que el SÍ alcanzó casi el 48%, creo que el resultado hubiera sido otro si el NO hubiera tenido también papeleta.
Así y todo, creo que un plebiscito es la máxima expresión de la democracia, por lo tanto respeto el resultado. Por eso me parece que es una burla lo que hicieron ayer los senadores.

Hace unos días Enrique Dans escribía en su blog un artículo titulado "Democracia frente a partitocracia", donde cuenta la realidad española, que tristemente aplica a la perfección a la realidad uruguaya. Eso es lo que tenemos hoy, una partitocracia. El ejemplo más claro de esto es el senador Eleuterio Fernandez Huidobro, quien renunció a su banca en el senado, pero antes votó la ley interpretativa por disciplina partidaria a pesar de estar en contra (según dice...).

Artigas dijo una frase que ha sido repetida innumerables veces: "mi autoridad emana de vosotros y ella cesa ante vuestra presencia soberana". Claramente los políticos de hoy en día no la respetan.

Cada vez estoy más convencido que la democracia representativa no es la forma adecuada de gobierno... Es, sin duda, lo mejor a lo que podíamos aspirar en el siglo XX. Pero en pleno siglo XXI, creo que se podría hacer mejor.

La democracia representativa era necesaria, porque era prácticamente imposible hacer participar a toda la población en las decisiones. Hoy en día, la tecnología hace posible que la participación popular se haga en tiempo real, por lo que ya no necesitamos representates.

Lo veo como algo muy difícil de implementar, porque siempre es complicado luchar contra la inercia del sistema actual, pero creo que sería hora de replantear lo que entendemos como democracia, y diseñar un sistema nuevo, de cero, que sea más justo y que permita a la población (a los que les interese) participar en forma directa.

miércoles, 6 de abril de 2011

Sobre el uso de Facebook

Soy usuario de Facebook desde hace tiempo, pero nunca lo llegué a usar "de verdad". Hay varias cosas que no me convencen del todo...

Para publicar contenido, me gusta más Twitter. En alguna ocasión use Facebook para compartir algo semi-privado, solo con la gente que me interesaba (fotos de algún viaje, por ejemplo), pero no es algo a lo que me acostumbre.

Lo que sí quiero usarlo es para consumir contenido. Hay gente que usa Facebook para publicar, que sí me interesa saber lo que están diciendo.

El problema con Facebook, es que trata a todos los amigos por igual, y esa no es la mejor forma de encarar el tema, porque en realidad hay amigos que me interesan más que otros. Muchas veces lo que publican estos amigos (los que quiero saber en que andan), queda perdido entre lo que publican otros tantos, que si tengo tiempo los leo, pero si no, quiero poder acceder rápido a lo que me interesa.

Además Facebook en su página web me muestra cosas que en general no me interesan, como por ejemplo cuando alguien comenta una foto o una nota de uno de sus amigos (que no es amigo mio). Eso hace que sea todavía más difícil encontrar las cosas que de verdad me interesan.

Por último, el otro problema que le veo es que la página con las noticias está demasiado sobrecargada. Hay demasiadas cosas que distraen, como publicidad, sugerencia de amigos, etc. También las cosas que ya leí, que igual siguen apareciendo.

Estuve leyendo un poco sobre la API de Facebook como para intentar hacer algo que me convenza, pero no tuve necesidad de avanzar mucho, porque encontré una herramienta que hace lo que quiero :)

La herramienta se llama fbcmd, y permite acceder a Facebook desde una línea de comandos. Sí, ya se, una herramienta así no es para cualquiera, pero a mi me sirve.

Tiene muchas más cosas que las que yo necesito, como por ejemplo permite publicar álbumes de fotos. Yo en realidad uso algunos pocos comandos.

Para consultar la actividad de la gente que más me interesa:
fbcmd fstream _familia,_amigos new
donde "familia" y "amigos" son grupos de gente que cree en Facebook. En realidad definí un alias
alias fb='fbcmd fstream _familia,_amigos'
por lo que el comando pasa a ser
fb new
Para consultar la actividad de todos mis contactos
fbcmd fstream =all new
o usando otro alias
fball new
Además de pasarle "new", que muestra solo lo que hay nuevo, se le puede pasar un número que indica la cantidad de items que muestra. Por ejemplo
fb 10
muestra los últimos 10 items.

Para ir a la página de Facebook a ver un item determinado (de la lista que devuelven los otros comandos, que está numerada)
fbcmd go post 3
donde 3 es el número de item en la lista.

Además tiene funcionalidades para comentar desde la línea de comandos, hacer un "like", etc. Pueden ver los comandos disponibles en la página correspondiente del Wiki de fbcmd.

Por último, la aplicación es open source, escrita en PHP y bastante bien documentada, por lo que no debería ser difícil de extender. Igual por ahora con lo que tiene me alcanza y me sobra.

jueves, 31 de marzo de 2011

Por qué es probable que no use Google +1

Ayer Google anunció el lanzamiento de "+1", un sistema de recomendación de páginas web similar al "me gusta" de Facebook.

Básicamente el "+1" es un ícono que aparece al lado del link en los resultados de las búsquedas. Cuando encuentro algo que me interesa compartir, aprieto el botón "+1" para que todo el mundo vea que me pareció interesante.

Esta información la va a usar luego Google para mejorar los resultados de su algoritmo de búsqueda.

El problema es que después que hice una búsqueda, entré a varios links a ver cual me servía y encontré uno que tenía lo que estaba buscando, es muy difícil que vuelva a la página de la búsqueda para decirle a Google cual fue el que me sirvió.

Es verdad que también hay un botón que se puede poner en las páginas web, otra vez igual que el "me gusta" de Facebook, pero ese tampoco le veo demasiado uso.

Ahora cuando quiero compartir algo lo hago en Twitter. No voy a dejar de compartir las cosas en Twitter, y por supuesto tampoco voy a compartir en todas las redes sociales en las que participo... Para eso es público lo que pongo en Twitter, que Google lo tome de ahí.

Acá tienen más información sobre +1.

miércoles, 2 de marzo de 2011

iPad 2

En el día de hoy Apple realizó un evento para lanzar la nueva versión del iPad.

Como todo evento de Apple, este generó mucha espectativa en los blogs de tecnología, generando muchas especulaciones.

Ahora que ya se conoce como será el iPad 2, aparece con algunas cosas que era evidente que iba a tener, otras que eran esperables y no aparecieron, y algunas sorpresas.

Lo esperable


Procesador más rápido. El iPad 2 tiene un procesador A5, dual-core, que dicen es 2 veces más rápido que el anterior y 9 veces más rápido para los gráficos.

Dos cámaras. Desde que el iPhone 4 incorporó una cámara frontal además de la cámara trasera que ya tenían los modelos anteriores, y además liberaron un producto para videoconferencias (FaceTime), se hizo bastante evidente que el iPad no iba a quedarse atrás.

Más delgado, más liviano.

Misma duración de batería. La duración de la batería (10 horas) es uno de los puntos más fuertes, era razonable que buscaran mantenerla.

Lo que faltó

Retina display. Creo que se podía esperar que el iPad 2 viniera con la tecnología de retina display que trae el iPhone 4, y que en dicho dispositivo multiplica la resolución por 4. Sin embargo el iPad 2 viene con la misma resolución de pantalla que el iPad original, 1024x768 pixels.

Reducción de precio. Cuando salió el iPhone 2, salió a un precio menor que el iPhone original, por lo que podía esperarse una versión más barata del iPad. Sin embargo esto no se dio, el precio de 499 dólares es suficientemente barato de todas formas para que la competencia tenga problemas para alcanzarlo.

Las sorpresas

Steve Jobs en el anuncio. Se había especulado mucho si Jobs aparecería en el escenario o no, dado que hace unas semanas anunció que se tomaba licencia médica. Al final estuvo...

Fecha de disponibilidad. Se especulaba que el iPad 2 podría estar disponible para abril, sin embargo la fecha de lanzamiento es el próximo 11 de marzo en Estados Unidos y dos semanas después en varios países más (no en Uruguay, por supuesto).

Lo que era difícil que estuviera (y no estuvo)

Multiusuario. Creo que el iPad es un dispositivo más familiar que un iPhone, por lo que sería bueno que en algún momento agregaran la posibilidad de tener varios usuarios, cada uno con sus configuraciones, preferencias y aplicaciones. No era esperable que estuviera, y por supuesto no estuvo.

iPad de 7 pulgadas. Se especulaba que podía haber un iPad más chico, y por supuesto tampoco estuvo.

Conclusión

Claro que después del anuncio es más fácil hacer predicciones... En general creo que el iPad 2 es más o menos lo que se esperaba.

Ahora hay que ver si para el año que viene, cuando anuncien el iPad 3, tiene algún competidor serio. Por ahora es y seguirá siendo el lider indiscutido del mercado.

martes, 22 de febrero de 2011

Text macros en XCode

Acabo de "descubrir" una funcionalidad de XCode que no sabía que existía: text macros.

En realidad es algo que sí sabía que estaba, porque muchas veces cuando uno empieza a escribir algo, le aparece código automáticamente para completar.

Por ejemplo, si uno escribe "if", aparece
if (<#condition#>) {
    <#statements#>
}
y apretando Enter o Space se agrega el código permitiendo completar las cosas que faltan.

Lo que no sabía, es que podía definir mis propios macros y como usarlos...

Hay una explicación muy completa de como hacerlo en esta nota, pero a mi me gusta más editarlo en modo texto que usando el editor de propiedades, así que acá va como lo hice yo...

En una ventana del Terminal.app:
cd /Developer/Applications/Xcode.app/Contents
cd PlugIns/TextMacros.xctxtmacro/Contents/Resources
edit ObjectiveC.xctxtmacro
donde "edit" se puede cambiar por cualquier editor de texto de su agrado (en mi caso en particular abre TextWrangler).

Ir al final del archivo, y agregar lo siguiente:
{
    Identifier = objc.singleton;
    BasedOn = objc;
    IsMenuItem = NO;
    Name = "Singleton Pattern";
    TextString = "#pragma mark -\n#pragma mark Singleton pattern\nstatic <#class#> *instance = nil;\n+ (<#class#> *) shared {\n @synchronized(self)\n {\n if (instance == nil) {\n instance = [[self alloc] init];\n }\n }\n return instance;\n}";
    CompletionPrefix = singleton;
    OnlyAtBOL = YES;
},
Esto agrega un nuevo text macro, que se activa escribiendo "singleton" seguido de Ctrl-. o de la tecla Escape, y que se expande a
#pragma mark -
#pragma mark Singleton pattern
static <#class#> *instance = nil;
+ (<#class#> *) shared {
    @synchronized(self)
    {
        if (instance == nil) {
            instance = [[self alloc] init];
        }
    }
    return instance;
}

Una explicación de los campos que se deben configurar en el archivo xctxtmacro:
  • Identifier: el identificador del macro
  • BasedOn: por lo que vi, vale siempre "objc"
  • IsMenuItem: si debe aparecer en el menú Edit -> Insert Text Macro en XCode
  • Name: nombre del macro
  • TextString: el texto que se va a expandir cuando se ejecute el macro, se pueden agregar "placeholders" encerrándolos entre <# y #>
  • CompletionPrefix: el texto que se tiene que digitar para que se dispar el macro
  • OnlyAtBOL: si solo es válido en una linea vacía o no (BOL = begin of line)

Eso es todo. Una vez agregados los nuevos macros, hay que reiniciar XCode y ya quedan disponibles.

viernes, 11 de febrero de 2011

Blocks en Objective-C (iOS 4)

Me acabo de enterar, que a partir de iOS 4, el lenguaje Objective-C soporta blocks. ¡Espectacular!

Les recomiendo que lean:

La sintaxis para declarar un block, es un tanto extraña... Por ejemplo, si queremos declarar un block que recibe un número entero y devuelve otro número entero, por ejemplo multiplicando el parámetro por 3, se declara así:
^ (int num) {
    return num * 3;
}
Este block se puede asignar a una variable, por ejemplo con
(int)(^por3)(int) = ^ (int num) {return num * 3;};
y luego invocarlo con:
int result = por3(7);  // result = 21
o se puede pasar como parámetro a algún método que reciba un block con el tipo dado:
[someObject someMethodWithBlock:^ (int num) {return num * 3;}];
Los blocks no están tan integrados al lenguaje como lo están por ejemplo en Ruby, pero es bueno ver que en iOS 4 Apple agregó a varias clases la posibilidad de pasarles blocks cuando resulta útil. Citando lo que dice la documentación oficial:
One obvious motivation for using blocks is that an increasing number of the methods and functions of the system frameworks take blocks as parameters. One can discern a half-dozen or so use cases for blocks in framework methods:
  • Completion handlers
  • Notification handlers
  • Error handlers
  • Enumeration
  • View animation and transitions
  • Sorting

jueves, 10 de febrero de 2011

DGI, facturación y declaraciones juradas

En Uruguay, la DGI (Dirección General de Impositiva), es quien se encarga de recaudar los impuestos de las empresas y las personas físicas.

Existe una modalidad, que es la que usamos los profesionales, que se llama Empresa Unipersonal, para las cuales el flujo de trabajo es el siguiente (no conozco como funcionan las demás, pienso que deben ser más complicadas):

  1. La empresa hace facturas a sus clientes, sin que la DGI se entere
  2. Una vez por mes o cada dos meses (depende de la modalidad de la empresa) se pagan los impuestos: IVA, IRAE, IRPF o lo que corresponda. Para el pago la empresa tiene que imprimir un boleto de pago en blanco, lo llena con los importes que correspondan, y paga eso. Todo esto sin intervención de la DGI, o sea, cada uno paga "como quiere".
  3. Una vez al año o cada 6 meses (depende de la modalidad de la empresa), se hace una declaración jurada donde uno declara lo que facturó, lo que compró y los pagos que hizo. Esto es un papel que es totalmente independiente de las facturas y de los pagos. Con los pagos, la DGI puede cruzar la información, pero con las facturas en principio no.
No se a ustedes que les parece, pero a mi me suena un tanto arcaico todo el proceso. Es de una época cuando la contabilidad se llevaba en libros, y por lo tanto no había una forma fácil de hacer algo determinístico, y lo mejor que se podía hacer era presentar una declaración jurada para asegurarse que la empresa pague lo que le corresponde.

El problema con esto es que implica que uno debe saber muchas cosas: que impuestos debe pagar y como calcularlos, qué declaraciones juradas debe presentar y como hacerlas. En general no son cosas triviales, y creo que generan bastante inseguridad porque no es algo en lo que quiera tener errores.

Creo que hoy en día se podría hacer mejor... Alguno me va a odiar por plantear algo así (los contadores por ejemplo... o alguno que quiera estafar a la DGI), pero a mi solo me interesa simplificarme el proceso.

No deberían existir las declaraciones juradas. La DGI debería tener toda la información disponible, verificable y segura. No tiene sentido que cada uno tenga que hacer las cosas por su cuenta sin que la DGI pueda verificarlo (salvo con una inspección).

Para eso, se debería poder generar la factura mediante el uso de un servicio brindado por la DGI. Yo hoy tengo una libreta de facturas, pero en realidad, eso tampoco tiene razón de ser así. Si yo pudiera entrar al sitio web de DGI, autenticarme de alguna forma (hoy ya hay usuarios que se autentican con una contraseña, podría ser eso), ingresar la factura que quiero hacer y mandarla automáticamente a mi cliente, quedaría toda la información registrada. Es más, la factura ni siquiera tendría que estar en papel, sería un link al sitio de la DGI... Si alguien la quiere en papel, la puede imprimir desde ahí.

Ahora, si la DGI tiene toda la información de las facturas que hago y de las facturas de las compras que hice (o las debería poder ingresar al sitio durante la transición), me podría decir exactamente cuanto tengo que pagar de cada impuesto, y me podría generar el boleto de pago con toda la información.

Si existiera un servicio así, yo sería más feliz.

A propósito... si alguien está en una situación similar y tiene un contador o contadora que le haga los cálculos de impuestos y declaraciones juradas, que me pueda recomendar, que me mande un mail a marcos arroba crispino punto info...

lunes, 24 de enero de 2011

Sudoku Solver

Hace unos días, se anunció que Google Goggles para Android es capaz de resolver un Sudoku, tomando una foto del mismo. Incluso hay un video que muestra como funciona:



También hace unos días, leyendo Coders at Work (buen libro, se recomienda), en la entrevista a Peter Norvig, comenta:
It’s also important to know what you’re doing. When I wrote my Sudoku solver, some bloggers commented on that. They said, “Look at the contrast—here’s Norvig’s Sudoku thing and then there’s this other guy, whose name I’ve forgotten, one of these test-driven design gurus. He starts off and he says, “Well, I’m going to do Sudoku and I’m going to have this class and first thing I’m going to do is write a bunch of tests.” But then he never got anywhere. He had five different blog posts and in each one he wrote a little bit more and wrote lots of tests but he never got anything working because he didn’t know how to solve the problem.
Así que, me dije... ¿qué tan difícil puede ser hacer un programa que resuelva un Sudoku? (no la parte de sacar la foto e interpretarla, solo el algoritmo). Resulta que no es tan difícil...

Pueden ver el código en GitHub: https://github.com/mcrispino/sudoku-solver. Ahí están también las instrucciones para bajarlo y ejecutar el programa.

El programa está escrito en Ruby, mi nuevo lenguaje favorito :) En una próxima nota explicaré alguna parte del código y por qué me gusta como se resuelven en el lenguaje.

El algoritmo es bastante sencillo. Creo que además el código es bastante simple de leer, pero acá va una explicación:

  • se parte de un tablero (clase Board), que es una matriz de 9x9, donde cada elemento es un array con todos los valores posibles, inicialmente todos los números del 1 al 9
  • para cada valor en el tablero original, se carga ese valor en el lugar correspondiente en la matriz, y se elimina de todos los lugares donde ya no puede estar (fila, columna y sub-matriz de 3x3)
  • una vez ubicados todos los números "fijos", se buscan posiciones de la matriz que hayan quedado con un array con un solo elemento (solo hay un posible valor), y para estos se repite el proceso anterior de cambiar el array por el valor y eliminarlo de los posibles valores de las posiciones donde ya no puede estar
  • esto se repite hasta que no hayan más arrays (se encontró una solución), o hasta que no queden arrays con un solo elemento
  • si quedan arrays con más de un elemento, entonces se hace una copia del tablero, se elige uno de los valores posibles, y se intenta resolver
  • si se encuentra una solución, entonces ya está
  • si no se encuentra, se hace backtracking.
Con este algoritmo, la solución se encuentra de forma instantánea. Probé también solo con el backtracking, pero nunca llegó a terminar (tampoco le tuve demasiada paciencia).

Para los que sepan Ruby, se agradecen comentarios, correcciones y sugerencias. Es una buena forma de aprender :)