Mi invitado esta vez es Mariano Koldobsky, un experimentado trabajador al que conozco desde hace años, a raíz de conocernos en una empresa en que él trabajaba y yo daba consultoría, y reencontrarnos más tarde en la comunidad ágil.
Tiempo después logramos trabajar juntos por un tiempo, hasta hace poco cuando Mariano empezó a trabajar para bvision, que tienen oficinas cerca de su casa en La Plata, capital de la provincia de Buenos Aires.
Con Mariano compartimos la pasión por la programación, la electrónica y recuerdos de nuestra generación, ya que somos los dos bastante veteranos. Pero casualmente esas dos primeras aficiones nos llevaron a elegir como tema de nuestra sesión un ejercicio de programación y cableado, utilizando una placa Arduino, que es una plataforma de hardware abierto, ideal para realizar prototipos e implementaciones sencillas y caseras de dispositivos de control.
Como verán en el video, la placa se conecta por USB (anteriormente por puerto serie) y se programa en un lenguaje de programación propio (una especie de Processing, pero basado en C++ en lugar de Java).
Algo interesante de Arduino es que es la plataforma que tomó de base Google para desarrollar su propio Android Open Accessory Development Kit, con lo que conocerla ahora puede significar algo más que un mero pasatiempo.
El video dura un poco menos de 15 minutos, y espero que les resulte tan divertido como a nosotros grabarlo. ¡Al menos por una vez van a ver algo más que código!
El próximo 21 de julio (de 18:30 - 20:00; GMT -3; horario de Buenos Aires) el amigo Juan Gabardini, viejo compañero de aventuras, estará presentando un Webinar (un seminario via web) patrocinado por la buena gente de Kleer.
El tema es el uso de casos de prueba basados en ejemplos utilizando FitNesse, la plataforma de pruebas de aceptación basada en wikis creada por el tío Bob Martin y amigos en base al FIT original de Ward Cunningham (ambas herramientas de código abierto y gratuito).
El evento es en línea y gratuita, pero los interesados deben registrarse porque hay una cantidad máxima de asistentes (aunque no se bien cuál).
La sesión se presentará utilizando GoToMeeting, un servicio de conferencias en línea de Citrix que soporta Windows y Mac OS y utiliza un cliente que se descarga al momento de la conexión, por lo que recomiendo conectarse unos 10 minutos antes para estar seguros de que todo funciona correctamente.
El temario, según la invitación, es el siguiente:
¿Cómo logramos que los requerimientos sean claros tanto para los usuarios como para los desarrolladores?
¿Cómo lograr validar continuamente y con bajo costo que el producto cumpla con los requerimientos?
Veremos las especificaciones por medio de ejemplos, una técnica utilizada para lograr estos objetivos, y Fitnesse, una herramienta libre que soporta la técnica.
Fitnesse permite escribir los ejemplos (requerimientos) como tablas o historias, y ejecutar automáticamente estos ejemplos contra la aplicación, informando si la aplicación cumple con los resultados esperados.
(gracias a José Romaniello por descubrirme este interesantísimo lenguaje)
Cobra es un lenguaje multi-plataforma y multi-paradigma que combina una cantidad de características sumamente interesantes.
Es obra de Charles Esterbrook, y su autor describe sus principios de diseño de la siguiente manera:
Programación rápida y expresiva
Rápida ejecución
Tipado estático y dinámico
Calidad soportada a nivel del lenguaje
Por supuesto que suena ambicioso y vendedor, pero en principio, es bastante realista. Veamos cómo se soporta cada cosa:
Programación rápida y expresiva
Cobra tiene una sintaxis basada en Python (sobre todo) y Ruby, lo que lo hace mucho más legible que los lenguajes "con llaves y punto y coma". Entre otras cosas, en Cobra los bloques se determinan por indentación, las listas y diccionarios se pueden declarar como literales, hay comandos como print y assert de uso sencillo y poderoso, la manera de iterar y dividir listas es simple, y mucho más.
Un ejemplo rápido de la sintaxis, con la definición de una clase:
class Person
"""
Declaración de una clase. Este comentario documenta la clase misma
"""
var _name as String # Declara variables de instancia (no estáticas)
var _age as int
cue init(name as String, age as int) # Inicializador (constructor)
base.init
_name = name
_age = age
def sayHello # Métodos
# Los corchetes interpolan valores en las strings
print 'Hello. My name is [_name] and I am [_age].'
def divide(i as int, j as int) as int
""" Este comentario documenta este método """
assert j > 0 # Si el divisor
return i / j
Rápida ejecución
Esto es logrado a través del uso de tipos estáticos con inferencia permanente, sin perder las capacidades dinámicas para los casos necesarios.
La implementación actual de Cobra utiliza la Infraestructura Comun de Lenguajes (CLI) de .NET/Mono, por lo que el compilador genera código intermedio (IL) que a su vez es es llevado a código nativo por el motor de ejecución de .NET/Mono como en otros lenguajes.
Tipado estático y dinámico
La mayor parte de la resolución es estática y en tiempo de compilación, mientras que siempre que haga falta puede utilizarse resolución dinámica en tiempo de ejecución, basada en Reflection de .NET y apoyándose en técnicas específicas de optimización.
Veamos un ejemplo sencillo de una misma función declarada estáticamente:
def add(a as decimal, b as decimal) as decimal
return a + b
... o dinámicamente:
def add(a, b) as dynamic
return a + b
En la práctica, no son la misma función, ya que la primera opera solamente con números decimales, y la segunda con cualquier tipo que soporte la operación suma.
Obviamente la primer función es más rápida, ya que se verifica y compila, y no requiere más recursos que los operandos de un largo conocido (decimal), mientras que la segunda, al resolverse dinámicamente, es verificada en tiempo de ejecución y requieres más recursos para la conversión de parámetros, etc.
Por otro lado, contar con ambas variantes es lo ideal, ya que podemos aprovechar el contrato estricto de los tipos estáticos para gran parte de la aplicación, pero con la flexibilidad de los dinámicos para las porciones que son más variables, o para facilitar el prototipado.
Nótese que el soporte a tipos dinámicos de Cobra, comparado con el de C# o VB (a partir de .NET 4), es sintácticamente más sencillo, mucho más integrado a nivel del lenguaje.
Calidad soportada a nivel del lenguaje
Cobra soporta contratos de código (algo proveniente de Eiffel que .NET 4 soporta parcialmente), pruebas unitarias, comentarios para documentación y verificación de valores nulos en tiempo de compilación, todo como parte de su sintaxis.
Veamos como las pruebas unitarias quedan embebidas directamente como parte de un método:
class Utils
shared
def countChars(s as String, c as char) as int
"""
Returns the number of instances of c in s.
"""
test
assert Utils.countChars('', c'x') == 0
assert Utils.countChars('x', c'x') == 1
assert Utils.countChars('X', c'x') == 0 # case sensitive
assert Utils.countChars(' ! ! ', c'!') == 2
body
count = 0
for ch in s
if c == ch
count += 1
return count
Las aserciones, además, pueden usarse en cualquier parte del código, y arrojan una excepción con información útil para depuración si no se cumplen (no son un IF).
Los contratos embebidos en el código permiten especificar pre y post-condiciones a los métodos, garantizando la consistencia antes de entrar y después de retornar el valor final. Por ejemplo:
class Customer
var _contacts as List<of Contact>
get contacts from var
def addContact(contact as Contact)
require # Arroja excepción si algo no se cumple ANTES de entrar
contact not in .contacts
contact.name
contact.customer is nil
ensure # Arroja excepción si algo no se cumple DESPUES de salir
contact.customer == this
.contacts.count = old .contacts.count + 1
body
contact.customer = this
_contacts.add(contact)
Y otra característica muy buena de seguridad es que los parámetros o tipos que pueden recibir nil (llamado como en Smalltalk o LISP), son los que se declaran como tales, agregando al sufijo "?" al tipo, como en:
def bar(s as String?)
if s # Es igual que preguntar "if s is not nil"
print Utils.countChars(s, c'x')
Cobra está escrito en Cobra
Una característica más que quiero remarcar es que este lenguaje está escrito sobre si mismo. Por supuesto hay una parte del compilador escrita para la plataforma nativa (C# en este caso), pero el resto está escrito en Cobra mismo, lo que hace que el lenguaje tenga un nivel de depuración y prueba mayor que otros que se construyen generalmente sobre lenguajes de más bajo nivel. Esto está sucediendo en otros lenguajes a posteriori, como en el caso de PyPy o Rubinius, pero en Cobra fue un principio de diseño.
Personalmente me parece uno de los lenguajes "experimentales" más interesantes y completos que he visto en los últimos tiempos, en parte porque se apoya en una plataforma que ya ofrece muchos servicios, y en parte por algunas de sus características maduras que y las herramientas con que ya cuenta (compilador, ejecutor de pruebas unitarias, generador de documentación, coloreador de sintaxis, etc).
Y también cuenta con soporte parcial en algunas IDEs y editores:
Visual Cobra es un complemento para Visual Studio que reconoce y colorea la sintaxis.
Naja es una IDE completa escrita en Cobra que ademas del coloreo de sintaxis tiene soporte para lista de tareas basada en comentarios, soporte para proyectos y un diseñador de formularios que genera código Cobra.
Y si uno prefiere un editor de texto hay muchos para los cuales hay complementos para soportar la sintaxis, incluyendo gedit, Notepad++, UltraEdit, Vim y TextMate (el que estoy usando yo), y mucho más para elegir según la plataforma que cada uno usa. Y para cualquier otro caso existe un detalle de las palabras clave y modificadores, de manera que en cualquier editor se puede partir del soporte para Python y cambiar estas listas.
Finalmente, dejo este video de la presentación de Esterbrook en el Lang .NET Symposium 2008. Aunque la implementación del lenguaje maduró bastante desde entonces, muchos de los principios siguen igual.
Apple realizó su conferencia principal para desarrolladores, como todos los años, e imagino que la mayoría ya debe haber visto al menos algún compilado de la sesión de apertura, en la que se lanzaron Mac OS Lion, iOS 5 y iCloud, entre otras cosas.
Para quienes no lo vieron, dejo al final el video de esa sesión completa, aunque advierto que dura 158 minutos (casi 2 horas).
Si no tienen tiempo, pueden buscar en la web alguno de los compilados que muestran los anuncios más sobresalientes. Los hay super-comprimidos de 60 segundos, y algunos más detallados de unos 10 minutos.
Sin embargo, quienes quieran abundar en más información, no menos, ya pueden ver en video todas las sesiones (un centenear) de la conferencia, incluyendo algunas que captaron mi interés como (mi usual lista arbitraria; el sitio requiere un usuario gratuito registrado):
En esa sesión mi par es Diogenes Moreira, amante de la Orientación a Objetos que a pasado por múltiples tecnologías desde Cobol y PowerBuilder hasta Java y C#, siempre con su corazón cerca de Smalltalk.
Diogenes trabaja actualmente para Ilon SA y aunque tiene múltiples responsabilidades no deja de programar junto a su equipo. Participó en varios proyectos de código abierto, incluyendo colaboraciones para Pharo.
Nos conocemos por amigos comunes y por el grupo Agiles de Buenos Aires, y casualmente durante una de las reuniones mensuales de éste nos escapamos un rato a grabar este video en que hacemos algunos ejemplos con Seaside, un framework web para Smalltalk.
Como acompañamiento del video, dejo esta presentación de Esteban Lorenzano, en la que se recorren varias de las características que Diogenes comenta mientras escribimos los ejemplos:
Sin más preámbulos, el video, que dura aproximadamente 35 minutos. Estoy usando un servicio que brinda mucho mejor calidad de video (sobre todo para el código), pero tengan paciencia porque el reproductor puede tardar varios segundos (a veces casi un minuto) en empezar.