Martín Cerdeira: Intención del código (o, me descargo un poco)

Este post, probablemente, parezca una pelotudez. Probablemente alguien diga "esto es obvio"o "no me digas", pero, es que lo he visto tantas veces, me he topado con esto tanto, que empiezo a creer que no es tan obvio.


Me ha tocado leer/mantener código que no fue escrito por mi. Es decir, meterme a tocar, mejorar, fixear, código ajeno en vez de escribirlo desde cero. En esos casos, me he topado con cosas como esta (*):

Function Foobar(n){
    n = n * 3
    return n
}


El tema es el siguiente, dada una función escrita en algún lenguaje de programación, puedo saber si está bien?

Esa función, es correcta o no es correcta?? Digamos, desde el punto de vista de la sintaxis (suponiendo que eso es la sintaxis de algún lenguaje) puede no fallar. Pero, está bien? Cómo se que intención tenía? Qué se supone que hace? O que esperar? Por qué nos cuesta tanto documentar eso en comentarios?

En casos peores, he visto cosas como:

Function Foobar(n){ //Devuelve n multiplicado por 3
    n = n * 3
    return n
}


Donde, no solo sigo teniendo el problema de no saber si está bien o no, sino que, además, me dice algo que es obvio.

Entonces, queridos amigos programadores, cuando comentemos procuremos poner la intención de ese cacho de código. NO quiero que me digan lo que puedo ver leyendo el código, sino, justamente, lo que se les pasó por la cabecita cuando lo escribieron. Por qué? Porque es mucho más sencillo arreglarla (si fuera necesario) sabiendo que se supone que hace, que tener que deducirlo teniendo en cuenta quien la llama, por ejemplo. Además, si la función estuviera mal, es más complejo deducir que en realidad, quisieron poner, no se, n = n + 3, por decir algo, aumentando mis posibilidades de romper algo que estaba bien, pero que parecía mal.

Gracias

(*) Aclaración para los despistados, esa función es solo ilustrativa, no es un caso real =)

Maximiliano Robaina: django y base de datos heredadas

En un proyecto en el que estamos trabajando, el cual básicamente consiste en migrar una aplicación de escritorio a un entorno web, decidimos mantener la herramienta que venimos usando justamente para todo lo que sea desarrollo web, es decir, django.

Ahora, el tema con django es simple cuando se empieza un proyecto desde cero, pero en este caso, ya heredamos la base de datos con la que debemos trabajar y por lo tanto tenemos que atarnos a esto. Además, la base de datos que debemos utilizar es Firebird SQL ( si, firebird :) ), y django no dispone de soporte “out the box” para este motor de base de datos, pero por suerte hay un grupito de gente (autobombo)[1]  que se interesa por dar este soporte ;) y por lo tanto tenemos un módulo que nos permite trabajar con django y firebird.

Uno de los primeros temas que se nos planteó al tener que usar una base de datos legacy, es con el tipo de datos Boolean.
Firebird, al igual que otros motores de base de datos SQL, no tiene un tipo de datos nativo que represente un Boolean, es decir, que permita trabajar con valores True o False.
Si bien esto no es un inconveniente ya que en estos caso se reemplaza por un tipo de datos que permite almacenar, por ejemplo, un valor entero (1 = True, 0 = False) o un valor de tipo caracter, que era nuestro caso el cual utiliza el valor “S” para verdadero (true) y “N” para falso (false).

Django dispone de un tipo de datos para soporte de Booleans y como no todos los motores de base de datos soportan True y False (por ej, MySQL para el cual django tiene soporte “de fabrica”, tampoco tiene un dato nativo boolean y por lo tanto se implementa generalmente como un Smallint con los valores 1 y 0 para True / False respectivamente), pero por defecto trabaja con valores 1 y 0.

¿Cómo hacemos entonces para usar los valores S y N heredados como si fuesen booleans nativos?

Herencia al rescate.!

No me voy a poner a explicar como se hace en django para escribir tipos de campos personalizados. La documentación de django es muy completa y explica todo al respecto.

http://docs.djangoproject.com/en/1.2/howto/custom-model-fields/

Pero si quería exponer como quedó nuestra implementación de BooleanField, al cual llamamos en un arranque furioso de creatividad, BoolField.

class BoolField(models.BooleanField):
    __metaclass__ = models.SubfieldBase

    def db_type(self, connection):
        return “CHAR(1) NOT NULL CHECK (%s IN (’S’,‘N’))”
   
    def get_prep_value(self, value):
        if value:
            return u’S’
        return u'N’
   
    def to_python(self, value):
        if isinstance(value, basestring):
            if value.strip() == ’S’:
                return True
            return False
        return value


Y con esto, ya tenemos nuestro BooleanField ala Firebird.


[1] http://code.google.com/p/django-firebird/

Maximiliano Robaina: Por qué elegir python

Hace un par de años atrás (fines de 2009) un cliente de españa al cual le ofrezco servicios de outsourcing, me envió un mail solicitandome mi punto de vista para el reemplazo de su herramienta de desarrollo: Delphi 6.

Acá expongo entonces los fragmentos principales de mi respuesta y mi opinión sobre por que elegir python como herramienta de desarrollo de software.

DISCLAIMER: hay que tener en cuenta que este mail lo escribí hace 2 años atrás donde además expuse pensamientos sobre investigaciones que hacía 4 o 5 años antes (2005-2006) inclusive.

Hace un tiempo, digamos unos 3 años (en realidad fue un poco más, quizás 5 años pero decididamente hace 3), empecé a buscar alternativas a Delphi. Por un montón de cosas: el lenguaje no evolucionaba, la incertidumbre de que iba a pasar con la herramienta, si seguia Borland o no, etc. Entonces empecé a buscar herramientas (más precisamente un lenguaje de programación) que cumplan con la siguiente características:

1. Que sea multiplataforma: que me permita ejecutar mi programa tanto en Windows como en Linux sin cambiar nada o al menos muy poco.
2. Que sea open source: quiero poder ver como esta hecha, y si fuese necesario, mejorarla y/o adaptarla a mi necesidades sin restricciones de licencias.
3. Influenciado por el punto anterior (2), que tenga una buena comunidad de usuarios que la respalden.
4. Que pueda hacer desarrollos tanto de aplicaciones de escritorio, como aplicaciones web sin tener que aprender otro lenguaje.
5. Un lenguaje de programación que sea intuitivo y permita un rápido desarrollo, que sea fácil de aprender. Es decir, que sea productivo, que acorte los tiempos de desarrollo.
6. Que tenga una buena base de librerías para desarrollar y sobre todo completa: (acceso a base de datos, mails, tratamiento de imagenes, etc.)

Primeramente, empece viendo Java: supongo que porque tiene mucho marketing, hay empresas grandes atrás de este producto. Me conseguí un par de libros, hice un curso básico inicial, traté de hacer alguna que otra cosa más o menos productiva, etc. Conclusión: no me gustó, si para hacer un pequeño programita que imprima “Hola mundo” tengo que escribir más de 10 líneas no me parece muy productivo. Java es muyyyyy grande hay un monton de cosas, ni hablar de que para hacer aplicaciones de tipo empresariales hay que saber usar Java EE que es un mundo aparte. Además de los recursos necesarios para ejecutar una aplicación en Java, por ejemplo un entormo de desarrollo como NetBeans necesitas por lo menos 2 GB de memoria (para una aplicación medianamente grande) y aún así le cuesta.

En el transcurso de mi incursión por Java, también vi .NET, más precisamente C#. Más de lo mismo, mucho código para hacer poco. Quería algo más consiso. El lenguaje (C#) en sí tiene cosas muy interesantes, pero es muy parecido a Java. Y bueno, solo me permitiría usarlo en Windows, no era lo que buscaba. (hay una implementación de .NET para Linux que se llama Mono, pero no se que empuje le pueda dar Microsoft a esto). También el punto de que .NET es de Microsoft y por lo tanto no es Libre. No contemplaba varios de los puntos que expuse anteriormente.

Finalmente caí en Python, bueno no, mentira, primero en Ruby influenciado por el framework Ruby on Rails que es para desarrollo web y que tiene mucha publicidad últimamante (de hecho hay un “Delphi” para Ruby que se llama 3rdRail) . Lo probé un tiempo pero luego lo abandoné, quizás más por falta de tiempo o poque había algo que no me convencia del todo.
Entonces, como decía, empece a ver Python, tenía casi todo lo que buscaba:
- Multiplataforma: sin cambiar una línea de código funcionaba perfecto tanto en Linux como en Windows (salvo que hagas cosas especificas de la plataforma). Es más tambien corre en Mac OSX (el sistema operativo de Apple). De hecho python viene por defecto en todas las distribuciones de Linux.
- Es libre-open source: tiene una gran comunidad que lo respalda.
- Es super fácil de aprender y por lo tanto super productivo. Por su característica de ser muy expresivo es muy fácil de enteder lo que el programador quiere poner en el código, casí como si fuese pseudocódigo.
- Tiene una gran librería estandar (así como Delphi viene con la VCL): pero creo yo, mucho más completa que la de Delphi.
- Poder hacer una aplicación de escritorio o una aplicación web muy fácil y rápido sin tener que aprendar nada nuevo del lenguaje (salvo aprender el framework que resuelva el problema en cuestión).
- En fin, un lenguaje muy completo, de muy alto nivel. Un programador con un poco de experiencia, en 15 días más o menos, ya lo tiene aprendido lo principal

Ahora, no es la pancea, hay cosas que no son para hacer con Python (o al menos no directemente), pero si para todo lo que yo buscaba en ese momento.
Por ejemplo, con respecto al acceso a base de datos: hice un sistema para una entidad del gobierno (un seguro materno infantil de salud)  todo hecho con python.  El framework que use para base de datos me permite, solo tocando un parámetro, usar  Firebird, Oracle, SQL Server, MySQL, etc. practicamente cualquiera. Hoy uso Firebird  pero si mañana quiero usar Oracle: creo toda  la estructura de base de datos en Oracle, migro los datos y a mi aplicación solo le digo que ahora se va a conectar a un motor Oracle, no programo una línea.

Bueno, no me voy a poner a explicar las caracteristicas del lenguaje acá porque no termino más :D pero acá van algunas referencias:

http://es.wikipedia.org/wiki/Python

http://www.python.org/
http://www.python.org/about/
http://www.python.org/about/success/

Y por sobre todo esto:  ¿Quién usa Python?

Google ( y lo usa mucho) - You tube
Yahoo
N.A.S.A.
IBM
Disney
The US Navy
Nokia.
Washington Post (washingtonpost.com)
http://popego.com/
etc, etc, etc…

http://pythonology.org/success

Mariano Reingart: Novedades PyAfipWs -Factura Electrónica- (instalador nsis, pythoncom, soap)

Recientemente liberé una nueva actualización de la biblioteca PyAfipWs, con varias mejoras:
http://www.pyafipws.com.ar/anuncios/nuevoinstalador106ayejemplosparawsfev1
A continuación se detallan los temas técnicos:

Extension a py2exe para generar un instalador NSIS:

Inicialmente usaba un .BAT para generar el instalador (7-zip autoextraible), para simplificar y mejorar el proceso (detectar archivos en uso, desinstalar copia previa, mostrar licencia, elegir directorio, internacionalización), desarrollé nsis.py, una extensión para py2exe, que agregando dos lineas a un setup.py crea un paquete unico con todo incluido, usando Nullsoft Scriptable Install System:

from nsis import build_installer
setup(
...
cmdclass = {"py2exe": build_installer}
)

Más info en:
http://code.google.com/p/pyafipws/source/browse/setup_wsfev1.py
http://code.google.com/p/pyafipws/source/browse/nsis.py

El código está adaptado de una ejemplo de py2exe para Inno Setup. 

PythonCOM y la ruta de instalación

Para poder acceder a archivos locales en un ambiente empaquetado con py2exe, en general es trivial salvo que el script sea una DLL, ya que el interprete Python se "embebe" dentro del programa anfitrión, y los métodos estándard para determinar donde está ubicado el script fallan.
La solución mas simple fue usar:

  • sys.executable para cuando el script es un .EXE
  • win32api.GetModuleFileName(sys.frozendllhandle) para cuando el script es un .DLL
  • __file__ cuando se ejecuta directamente el .PY

Más info en:
http://code.google.com/p/pyafipws/source/browse/wsfev1.py#129

Type Library y PythonCOM:

Algunos lenguajes de tipado estático (C#, versiones de Cobol) necesitan para las interfaces COM una librería de tipos (mejor conocidas como .TLB) para referenciar y determinar los métodos, parámetros y valores devueltos, ya que Python es un lenguaje dinámico que no ofrece dicha información.
Para mi sorpresa, las implementaciones en lenguajes de tipado estático tampoco parecen ofrecerla, y es necesario en todos los casos usar un compilador de un lenguaje especial de MS (IDL):
http://code.google.com/p/pyafipws/source/browse/pyafipws.idl
Para que lo reconozca hay que agregar al objeto python los atributos _typelib_guid_, _typelib_version_, _com_interfaces_
http://code.google.com/p/pyafipws/source/browse/pyafipws.py#57

Igualmente todo este tema esta deshabilitado ya que el tipado estático ocasiona más problemas que los que resuelve (sobre todo con el registro, DLL hell, falta de flexibilidad, etc.), y hay métodos alternativos más simples para acceder a PythonCOM desde C# y lenguajes similares.

Mi agradecimiento a Mark Hammond (el creador de python-win32) por señalar al ejemplo "pippo" en el directorio win32com\test, como muestra de una asociación entre un objeto Python COM y su TLB.

Mejorando la performance SOAP WSDL:

El protocolo SOAP es complejo, y analizar el XML de la descripción de un webservice (WSDL) para poder comunicarse con el, es un proceso un poco costoso.
Gracias a Python la solución se simplificó bastante, ya que permite guardar y recuperar las estructuras de datos ya procesadas, sin necesidad de artefactos o código generado como en otros lenguajes (.NET, Java, etc.):
http://code.google.com/p/pysimplesoap/source/browse/pysimplesoap/client.py#244

Con el módulo cPickle de la librería estándar (implementado en C) se mejoro el tiempo para cargar un WSDL de 0.4 segundos a aproximadamente a 0.001 segundos, ~ 400 veces más rápido. Con pickle nativo (implementado en python) la mejora era un poco menos significativa (~ 40 veces más rápido).
Los test fueron realizados en una netbook para un webservice medianamente complejo, YMMV

Juan Pedro Fisanotti: Review Alienware M11X R2

Ayer finalmente me llegó la máquina nueva: una Alienware M11X R2.
No voy a hacer una super review detallada, ya hay unas cuantas en la web (que me leí antes de comprarla), sino que solo voy a poner mi visión resumida.

Pero antes, las especificaciones:

Micro: Intel Core i7 640UM (quadcore, 2.26 Ghz)
RAM: 4GB DDR3 de 800Mhz (dual channel)
Video: Nvidia GeForce GT 335M (1GB de memoria)
Disco: 500GB SATA II de 7200rpm
Pantalla: WLED de 11', 720p
Otros: bluetooth, HDMI, display port, card reader, cámara, etc.

Puntos a favor:

  • Potencia: vuela, así de simple. Corre el COD4 Modern Warfare 2 con todos los gráficos en máximo, y ni lo siente.
  • Tamaño: tiene el tamaño de una netbook de 12', entra perfecto en la mochila, es portable. No entiendo todavía cómo entran las cosas que tiene dentro de un espacio tan reducido.
  • Diseño: futurista, me gusta más que cuando lo veía en fotos. Se ve y se siente muy robusta.
  • Duración de batería: 6 horas con poca exigencia, 2 horas jugando, es bastante.
  • Chiches: Se pueden personalizar los colores de todas las luces, tiene un indicador de batería abajo para cuando está apagada, puede cargar energía a otros aparatos por USB estando apagada, etc.

Puntos en contra:

  • Peso: acostumbrado a una netbook de 1kg, los 2kg y algo que pesa me resultan no tan cómodos en la espalda.
  • Pantalla reflexiva: la pantalla refleja demasiado, muy molesto usarla en ambientes bastante iluminados.
  • Soporte para Linux: desde Linux no puedo hacer varias cosas, como cambiar el color de las luces, o elegir qué aceleradora utilizar.
  • Puerto VGA: no tiene, tengo que conseguir un adaptador para poder usar mi monitor.

Fotos :)

Maximiliano Robaina: frostbyte.com.ar Blog en hosting gratis. Fail !

Como mencione en el primer post, el primer intento de tener mi blog terminó fallando. ¿Y cuál fue el problema?

En realidad no es que haya habido un problema, creo que lo que no estuvo bien fue la solución elegida para mi necesidades. Veamos…

Posibilidades para tener un blog:

1. Usar un servicio de blog como blogger, wordpress.com, tumblr, etc  [0]

2. Contratar un hosting e implementar directamente ahí la herramienta. La mayoría de los hostings ya vienen con instaladores de blogs y cms.

4. Tener nuestro propio web server :D

3. Usar un hosting gratis (mi caso)

5. ¿Otros?

El problema con un hosting gratis es que generalmente tienen algunas restricciones o imposiciones, como por ejemplo te tenés que comer que te inyecten banners.

En mi caso particular estuve usando www.000webhost.com/  que no está tan mal lo que ofrecen en el servicio free y además la respuesta de soporte fueron bastante rápidas, no te meten publicidad y características de administración bastante completas. Pero lo que pasa en con este hosting, bah, en realidad con la mayoría de los que son gratis es que si tu sitio tiene poco o casi ninguna actividad, te lo dan de baja. Ah, y además NO TE AVISAN ! por lo tanto perdés todo lo que tenías alojado en el mismo.

Conclusión: Como frostbyte.com.ar tenía casi cero (0) actividad me lo dieron de baja y perdí mi blog.

Ajá!  y los backups? Bueno, esto es otro tema :(

Trataré de ir completando esta entrada de manera que vaya quedando documentada la experiencia.

[0] de hecho ahora estoy usando tumblr.com

Maximiliano Robaina: Hello Word !! and a new hope

Despues de haber intentado (y fracasado rotundamente) tener mi blog en un hosting propio, cosa de la que comentaré en algún otro momento, voy a probar tumblr.

Lo que vi hasta ahora parace bastante interesante, sobre todo lo que refiere a no tener que preocuparse en demasia por la configuración del blog. Quizás parezca más un twitter con esteroides, con menos restricciones ¿?, pero bueno veamos…

Intentaré (nuevamente) mantener fluidez en las publicaciones.

See you.

Juan Pedro Fisanotti: La magia existe

La magia existe. Los magos existen.

Personas con poder para crear mundos enteros y manipular sus leyes para volar, hacerse invisibles, o cualquier cosa que sus mentes sean capaces de imaginar. Magia que construye, conoce, transforma o destruye.
Magos que dedican sus vidas ocultas a perfeccionar sus habilidades mágicas, con largas horas de estudios y experimentos impensables. Que forman cofradías en las cuales comparten conocimientos, técnicas y descubrimientos. Cofradías donde los aprendices reciben el arte de manos de gurúes poderosos, y donde muchos combinan sus poderes para lograr cosas aún más increíbles.
Tan increíbles que su magia ya está presente detrás de la vida cotidiana del mundo. Pero son solo los magos quienes conocen y comprenden su verdadero poder y lo continúan aprovechando para transformar la realidad a gusto, a veces para bien y otras no tanto. Al tiempo que para el resto, son solo personas con gustos extraños.
No son quienes conocen solo un poco de magia, y esta se convierte en un simple medio para algún objetivo temporal. Los verdaderos magos descubren el placer en el solo hecho de conocer la magia, experimentar, descubrir. Crean y conjuran nuevos hechizos solo para llevar su poder al límite, y así cultivar su habilidad, expandir su entendimiento.

La magia existe. Los magos existen. La gente los suele llamar "programadores".

Juan Pedro Fisanotti: Charlas en las Jornadas de Software Libre de Junín

Hace poco tuve la suerte de poder ir a las Jornadas de Software Libre que se organizan en Junín. El evento estuvo muy bueno, me sorprendió el nivel de la organización, y aprendí un montón en las charlas. Y de paso me invitaron a dar una charla de Django fuera de cronograma :)

Por suerte filmaron todas las charlas (algo que debería ser costumbre en este tipo de eventos), y hace unos días las subieron ya a blip.tv. Algunas de las charlas también se habían dado en PyConAr 2010, así que pueden aprovechar quienes se perdieron ese evento :)

Pueden ver todas las charlas aquí: http://unnoba.blip.tv/posts?view=archive&nsfw=dc

(y mi charla es esta)