21 de diciembre de 2009

Un mensaje rápido

Hola, solo un mensaje rápido para decirles que últimamente he estado literalmente "tapado" de trabajo, lo que me ha dificultado enormemente el poder seguir con los posts. Afortunadamente Alcides ha seguido, esperemos que esto se siga moviendo, pues.

Por otro lado, hay algunas cuestiones existenciales que me han asaltado últimamente y me gustaría compartirlas con ustedes y que me dieran su opinión:

  • ¿Qué es más importante, ser experto en la plataforma/lenguaje/entorno/framework/base de datos con la que trabajo cotidianamente en mi trabajo actual o ser un profesional más "redondeado" que se mueva con soltura entre distintos entornos, etc?
  • ¿Qué tan importante es la teoría en sus trabajos/proyectos actuales? ¿Es útil o incluso necesario aprender sobre teoría relacional, álgebra de conjuntos, etc. para usar efectivamente el DBMS del proyecto o solo necesito aprender a usar el generador de queries que trae mi IDE actual? ¿Y que tal la teoría de la programación (si es que existe tal cosa)?
  • En su trabajo/proyecto actual, ¿Tiene sentido invertir en código limpio, documentación completa (me atrevería incluso a decir... correcta) o incluso como mencionó nuestra amiga Tere hace poco tiempo, llegar a tener una "lógica aprueba de balas"?
  • ¿Qué nos es más gratificante, "sacar la chamba" o hacer un buen trabajo? ¿Es posible lograr ambos?

Espero en verdad leer sus comentarios al respecto. A la mayoría de esas preguntas les he tenido una respuesta tajante durante varios años. Sin embargo, creo que mi visión al respecto estaba en cierta forma influenciada por el hecho de trabajar para el área de sistemas de una empresa o por lo menos, en un proyecto a mediano o largo plazo.

Hoy en día mi función como "consultor" se limita a alcances de muy corto plazo en los cuales parece que la lógica económica no concuerda necesariamente con la ética profesional o por lo menos a lo que yo he llamado así los últimos años de mi vida.

Saludos

29 de noviembre de 2009

El Paradigma OOP (Parte 3)

Después de algunas semanas en las cuales tuvimos varios contratiempos incluidos uno que otro "bomberazo" no raros por desgracia en la vida de un programador profesional. Y después de finalizar también este fin de semana una migración y actualización del sistema operativo de mi computadora a mi sistema operativo favorito (Debian GNU/Linux). Ahhh... ¡por fin! me siento nuevamente como en casa :-)...feliz de poder estar usando nuevamente Debian mientras escribo estas líneas.

Pero bueno, paulo majora canamus ... entremos en la materia que nos ocupa en este blog. En la entrada anterior terminamos mostrando un pequeño programa en Squeak Smalltalk comparándolo con la versión en java del mismo programa. Alguien dirá que siendo Squeak un entorno gráfico la comparación contra el programa de línea de comandos "nomedad.java" transcrito en la entrada anterior no sería completamente adecuada.

Pues bien, a continuación transcribo la versión para línea de comandos en GNU-Smalltalk del programita en cuestión

"nomedad.st"
| nombre edad |
Transcript show: 'Hola, ¿Cual es tu  nombre? '.
nombre := stdin nextLine.
Transcript show: '¿En que año naciste? '.
edad := (stdin nextLine) asInteger.
edad := 2010 - edad.
Transcript show: 'Hola '; show: nombre; cr;
          show: 'En el año 2010 tendrás ';
          show: edad printString;
          show: ' años.'; cr.
!

Como se puede apreciar, esta versión de línea de comandos comparada con la versión anterior gráfica ¡¡no cambió casi en nada!!.

Mencionábamos que en esta primera aproximación a Smalltalk, pueden apreciarse algunas características del lenguaje que son muy importantes para entender el paradigma de programación que nos ocupa en este blog. Veamos cuáles son algunas de ellas.

  1. La primera es desde luego que Smalltalk hace honor a su nombre y es un lenguaje breve y conciso, sin verborrea ("small") en pocas palabras y como decía Alfredo en su post anterior, es un lenguaje terso. Smalltalk es un lenguaje muy simple y es fácil de aprender. Solamente tiene cinco palabras reservadas (super, self, true, false, nil) y solamente hay unos pocos principios básicos que el usuario tiene que saber para poder utilizar el lenguaje. Además, como veremos la sintaxis de Smalltalk es parecida al lenguaje natural.

  2. Lo que vendría siendo nuestra declaración de variables

    | nombre edad |
    que en un lenguaje híbrido/procedural tendrían que ir acompañadas de su declaración de tipo, aquí en Smalltalk solamente necesitan declararse sus nombres. Esto se debe a que en Smalltalk como seguiremos viendo más adelante, todo, absolutamente todo es un objeto (números, cadenas, etc. vaya hasta el código mismo) por lo tanto cuando se declara una variable simplemente se está declarando una referencia a un objeto, y no importa si esta referencia tendrá valores numéricos, de caracteres, será un arreglo, etc. Para Smalltalk es un objeto y punto. No necesitamos saber de antemano el tipo del mismo para poder trabajar con él, ya veremos porqué.

  3. En Smalltalk las instrucciones se construyen como una serie de mensajes que se envían a los diferentes objetos del programa para que hagan alguna tarea específica. Tomemos como ejemplo la primera línea del programa después de la declaración de las variables:

         Transcript show: 'Hola, ¿Cual es tu nombre? '.
       
    Aquí le estamos enviando al objeto Transcript el mensaje show: (o #show: en Smalltalk idiomático ya veremos porqué) el cual a su vez requiere un objeto String (mas propiamente dicho una instancia de la clase String) que en este caso es el letrero 'Hola, ¿Cual es tu nombre? '. Tanto en Smalltalk como en Pascal las cadenas se delimitan con comillas simples. Y el punto al final del renglón significa el fin del mensaje.

Este último concepto de los mensajes queridos amigos y lectores es de las ideas mas fundamentales (en mi caso fue la más fundamental de todas) para poder entender a cabalidad el paradigma de programación orientado a objetos. Y es que no, no y tres veces no, no es lo mismo y nunca será lo mismo enviar un mensaje que "invocar un método". Esta distinción conceptual y semántica tiene profundas implicaciones.

Los métodos en los lenguajes híbridos procedurales se han implementado como llamadas a procedimientos y funciones. Esto dificulta todavía mas la comprensión del paradigma original.

Sobre el concepto de los mensajes haremos a continuación algunas definiciones muy importantes.

Al conjunto de mensajes que un objeto es capaz de entender y responder se le denomina su protocolo. Este protocolo de mensajes de un objeto es a lo que en otros lenguajes como Java se le denomina una "interfaz" (interface). Ya antes mencionábamos que no necesitamos saber de antemano el tipo de los objetos que vamos a usar y esto es porque lo realmente importante es que los objetos que utilicemos se conformen al protocolo de mensajes que les vamos a enviar, esto es: que entiendan y respondan al los mensajes que les vamos a mandar. El protocolo de mensajes es lo que define las características y el comportamiento (responsabilidades) de los objetos. A la descripción de un conjunto de objetos con protocolos similares se le denomina Clase. Y a un elemento del conjunto de objetos descrito por una Clase se le denomina Instancia.

Esta es una definición mucho mejor y mas acertada que aquella que varios de nosotros aprendimos (o mas bien sufrimos) cuando estudiantes cuando se nos dijo que "una clase era a un tipo lo que una variable a una instancia". No mucho que ver. La analogía solo es aparente pues como veremos después las clases a su vez también son instancias de sus meta-clases y existen tanto protocolos de clase como protocolos de instancia. Valga decir que ésta última definición en su momento fue un obstáculo mas en nuestro camino hacia la comprensión del verdadero paradigma.

Queridos amigos y lectores el tiempo y el espacio se nos han agotado el día de hoy. Continuaremos escribiendo más sobre este tema en nuestra siguiente entrega.

Espero sus comentarios. Saludos.

20 de octubre de 2009

La Importancia del Lenguaje

Aprovechando la inercia creada por los últimos posts de Alcides, quiero dedicar una pequeña nota a la importancia de los lenguajes de programación.

Existe una hipótesis en lingüística y psicología denominada como el Principio de Relatividad Lingüística, también llamada la Hipótesis Saphir-Whorf. Esta hipótesis sostiene que la lengua que se habla tiene una influencia en la manera de pensar, conceptualizar y en la forma de experimentar el mundo.

Esta es una hipótesis muy debatida, ya que por un lado, hay proponentes de esta hipótesis que aseguran que el lenguaje condiciona completamente al pensamiento, mientras que por otro lado, se afirma que el pensamiento es anterior al lenguaje y no al revés. Ahora, dejemos que los científicos hagan su trabajo y últimamente concluyan si fue primero la gallina o el huevo. Lo que si es innegable es que la lengua que usamos para comunicarnos si tiene un impacto en la manera en que componemos e hilamos nuestros pensamientos.

No sé si a ti amable lector, que eres bilingüe o incluso políglota, te ha pasado que al pensar sobre cierto tema particular te sientes más cómodo al hacerlo en una lengua que en otra. A mi en lo particular, me ciento más cómodo pensando sobre programación en ingles que en español. No es malinchismo ni nada que se le parezca. Simplemente que cuando comenzaba a aprender sobre el tema, eran relativamente pocos los libros y revistas que había disponibles en español (ni hablar que algunas traducciones eran de plano pésimas, pero esa es otra historia), por lo cual me vi obligado a satisfacer mi curiosidad y mis necesidades académicas con publicaciones escritas en la lengua de Shakespeare.

Ahora bien, ¿alguna vez nos hemos puesto a pensar en el impacto que tiene el Lenguaje de Programación que usamos para nuestro trabajo diario en la efectividad con la que desempeñamos el mismo? En otras palabras, el lenguaje que estoy usando en mi proyecto actual ¿Ayuda o inhibe el proceso mental que me permite hallar respuestas a los problemas que enfrento el día de hoy?

Debemos recordar que si bien todos los lenguajes de programación son, de hecho Equivalentes Turing, eso no significa que todos sean igualmente adecuados para cada tarea.

Por ejemplo, hay muchos filósofos e intelectuales que han comentado que los mejores lenguajes para el pensamiento son el latín, el griego y el alemán (…) Es curioso notar que a pesar de ser la lengua más hablada del mundo, nadie ha afirmado jamás que el ingles sea una buena lengua para el pensamiento. Pensemos en ello un momento.

Recordemos que el desarrollo de software es una actividad eminentemente intelectual. Es quizás, junto con la poesía y otras formas de creación literaria, una de las actividades más puramente intelectuales en las que se puede embarcar el ser humano. Nuestro trabajo consiste 80% o un 90% en pensar, y después un 10% o un 20% en otras cosas como teclear, etc.

Entonces, ¿hay acaso lenguajes que son mejores para el pensamiento que otros?, ¿cuales? y por otro lado, el hecho de que la mayor parte de los proyectos, libros y artículos de revistas se escriban en Visual Basic, C# y Java ¿no es razón suficiente para concentrar mis esfuerzos en esos lenguajes?

De hecho, hay lenguajes que son mejores para el pensamiento que otros: smalltalk, lisp y posiblemente ruby, son algunos de ellos. Aunque en muchos aspectos estos lenguajes difieren enormemente entre sí (como el griego y el alemán también lo hacen), tienen una característica que a mi modo de ver es esencial: son lenguajes tersos.  ¿A qué me refiero con eso? A que:

Permiten un contenido semántico rico con un mínimo de elementos sintácticos.

Esto no significa otra cosa que el hecho de que estos lenguajes permiten expresar una gran cantidad de conceptos utilizando muy pocas palabras reservadas, puntuación, operadores, etcétera.

Ahora bien, no estoy afirmando que todos debiéramos renunciar a nuestros trabajos actuales o ponernos en huelga para exigir que los proyectos se desarrollen exclusivamente en lisp. Sería fantástico que todos tuviéramos por lo menos una vez la experiencia de desarrollar un proyecto grande en estos lenguajes. Sin embargo, esto no siempre es posible. Desgraciadamente, aunque no es un buen lenguaje para el pensamiento, el ingles sigue siendo la lengua más hablada en el mundo, y una gran cantidad de ciencia, tecnología e incluso literatura se realizan todos los días utilizando esa lengua.

¿Entonces porqué aprender griego clásico o smalltalk? Porque nos dan más y mejores herramientas para pensar. En varias ocasiones me he tenido que romper la cabeza tratando de darle la vuelta a un problema que parece que no tiene solución en Visual Basic o en Javascript. Y en muchas de esas ocasiones lo que me ha salvado el día es pensar “¿Cómo lo resolverías si el lenguaje no fuera una limitante?”… Usualmente recuerdo una técnica o idea que aprendí en Python o en Lisp que me permiten destrabar mi proceso mental y llegar a una solución práctica.

Alguna vez leí que Google contrata mejores programadores que su competencia porque la mayoría de sus programadores programa en dos o tres lenguajes distintos que no son necesariamente los lenguajes más comerciales del momento.

Esto me lleva a un corolario de la hipótesis Saphir-Whorf con la que comencé esta nota:

El lenguaje de programación no es un condicionante para escribir código malo.

Me gustaría leer sus comentarios.

Saludos

16 de octubre de 2009

El Paradigma OOP (Parte 2)

En la entrada anterior finalizé haciendo referencia al lenguaje de programación SmallTalk. En esta entrada continuaré con el tema que venía desarrollando.


Así como Pascal fué en su momento, el paradigma de la programación estructurada ( Algoritmos + Estructuras de Datos = Programas). Smalltalk ha sido hasta ahora el paradigma de la programación orientada a objetos.


Otros lenguajes tales como C++, Java y Object Pascal, no son realmente orientados a objetos en toda la extensión de la palabra; son mas bien lenguajes híbridos, lenguajes procedurales con algunas extensiones que permiten programar con objetos, pero nada que ver con la orientación a objetos pura y real de Smalltalk, en donde incluso un bloque de código es un objeto, y como tal tiene un protocolo de mensajes definido. Vaya, incluso lo que en los lenguajes procedurales conocemos como "estructuras de control", en Smalltalk son mensajes y sus parámetros son bloques de código. Nada que ver con los lenguajes procedurales híbridos, esto en sí mismo representa una forma radicalmente distinta de ver el código.


Así pues, fué que reconociendo mi ignorancia y por tanto mis carencias y necesidades, decidí que fuera precisamente Smalltalk quien me sacara del paradigma de la programación procedural y me enseñara el verdadero paradigma de la programación orientada a objetos.


Comencé entonces a hacer mis primeros pininos en Smalltalk y me sorprendió muy gratamente.
De entrada transcribí mi programa mascota "NomEdad" un programita sumamente simple que pide una cadena y un número y despliega como resultado una suma en un letrero.


La versión en Java de este programita es la siguiente:

/* nomedad.java */
import java.io.*;
class nomedad {
    public static void main (String[] args) throws IOException {
        Integer   edad;
        String   strnombre;
        BufferedReader   brin;
        int   n;
        /* Inicialización */
        brin = new BufferedReader(new
InputStreamReader(System.in));
        /* Comienza rutina principal */
        System.out.print("Hola, ¿Cuál es tu nombre? ");
        strnombre = new String(brin.readLine());
        System.out.print("¿En que año naciste? ");
        edad = new Integer(brin.readLine());
        n = 2006 - edad.intValue();
        System.out.print("Hola, ");
        System.out.println(strnombre);
        System.out.print("En el año 2006 tendrás ");
        System.out.print(n);
        System.out.println(" años");
    }
}

Pues bien este programita que al escribirlo en Java por primera vez me causó algunos dolores de cabeza debido a las sutilezas del lenguaje, que copia la sintaxis de C pero no necesariamente su semántica, debido a que las variables se crean pero no se inicializan, debido a que el Standard Output si puede usarse directamente pero el Standard Input no, debido a la sintaxis para declarar excepciones y debido a otras linduras tales como el kilométrico import ...bla bla bla... class ... bla bla ba ... public static void main ( String [] args ) throws ...bla bla bla... etc, etc. (Años después sufriría yo igual o peor con Visual Basic .NET y toda su verborrea).

Este mismo programa en Smalltalk ( Squeak) lo pude escribir en poco más de cinco líneas de código claro, legible y entendible:

"nomedad.st"
| nombre edad |
    nombre := FillInTheBlank request:'Hola, ¿Cual es tu nombre?'.
    edad := FillInTheBlank request:'¿En que año naciste?'.
    edad := 2006 - (edad asInteger).
    Transcript show:'Hola '; show: nombre; cr.
    Transcript show:'En el año 2006 tendras '; show: edad; show:'
años'; cr.

¡¡Que gran diferencia!! ¡¡Solo seis líneas de código, claro y entendible !!.

Esto a pesar de no ser necesariamente Smalltalk idiomático.


Es impresionante saber que en 1980, Smalltalk ya tenía su propia máquina virtual, su propio byte-code, compilador JIT, entorno de programación IDE, ambiente gráfico, implementación del patrón de diseño Model-View-Controller (MVC), entre otras cosas. Elementos que mas de diez años después se venderían como "innovaciones" por parte de Sun con Java y más de veinte años después por parte de Micro$oft con .NET (quien por cierto apenas está logrando cuajar bien su implementación del MVC).


Esta primera aproximación nos muestra ya algunas características del lenguaje Smalltalk que son importantes para entender el paradigma que nos ocupa de las cuales seguiremos escribiendo en nuestro siguiente post.


15 de octubre de 2009

El paradigma de programación orientada a objetos

¿¿Paradig... queee?? diríamos algunos. Y aquí comienza precisamente el viaje que menciona Alfredo en su introducción a este blog ... :-)

Paradigma en su sentido original tradicional significa «modelo / ejemplo» y, en su sentido más amplio contemporáneo implica «cosmovisión», es decir:

La forma de entender y percibir el mundo y a nosotros mismos.

Y es que muchos de nosotros no solo ignoramos el significado real del término, sino que ni si quera nos percatamos de su existencia en la vida cotidiana y mucho menos nos enteramos que existen otros paradigmas diferentes a los que conocemos, vaya: otras formas de ver y entender el mundo (otros modelos y puntos de vista igualmente válidos) además de la nuestra.

En mi experiencia personal, esto sucedió allá por el verano del año 2002, en aquel entonces me sentía orgulloso de haber programado mi último proyecto de sistemas totalmente en C++ (¡válgame Dios! Tal era mi ignorancia). Fue en aquel año cuando Alfredo me hizo favor de compartirme algo sobre el Refactoring y los Patrones de Diseño (yo la verdad en ese tiempo estaba mucho más dedicado al estudio y aprendizaje de otros sistemas operativos tales como GNU/Linux, FreeBSD y MacOS). Al comenzar a investigar mas sobre el tema, me di cuenta de un par de cosas que no había notado antes.

  • Primero: Me di cuenta que no entendía realmente bien la terminología Orientada a Objetos (OO), a pesar de haberla conocido y usado durante varios años (y de haber programado en C++ mi último sistema)
    (P.ej. el caso del tan llevado y traído concepto de polimorfismo, que cada quien entiende a su manera aún en los libros «de texto» sobre la materia, pero bueno ese es otro tema...)

  • Segundo: Me di cuenta que no solamente no entendía bien la terminología sino que ignoraba total y absolutamente (vaya no tenía ni la menor idea) los conceptos reales detrás de la misma.
    En otras palabras me di cuenta de que estaba yo frente algo totalmente nuevo, diferente y desconocido para mí hasta ese momento y que además no se parecía en nada a todo lo que yo conocía hasta ese entonces y tampoco se parecía en nada a lo que me habían explicado ni en la escuela ni a lo que venía escrito en los libros de programación «orientada a objetos».

Fué entonces cuando experimenté lo que ahora sé que se llama un «cambio de paradigma» (o « paradigm shift» como le dicen en inglés)… Ese famoso «A-ha!» que se menciona en la introducción de este blog.

Fue entonces cuando, reconociendo mi supina ignorancia en la materia, me dí a la tarea de comenzar a aprender realmente lo que significaba este paradigma de programación que tal vez sea (por lo menos en México) el mas malinterpretado de todos; para lo cual, en lugar de recurrir a los lugares y libros de texto comunes (C++, Java, Object-Pascal, etc, de hecho tenía y había leído ya varios de ellos), decidí ir a la raíz del asunto y remitirme a las fuentes originales.

Resulta bastante notorio y algo sumamente indicativo que de una misma comunidad hayan surgido el Refactoring, los Patrones de Diseño, las Pruebas Unitarias, los Métodos Agiles, y en los 70's las interfaces gráficas, los IDE's y las máquinas virtuales. Y que además varios de sus miembros sean distinguidas autoridades en la materia ( Kent Beck, Ward Cunningham, Martin Fowler, Ralph Johnson, Joseph Yoder, et al, entre muchos otros)

Y me estoy refiriendo precisamente a la comunidad creada alrededor de uno de los mejores lenguajes de programación que se hayan inventado jamás: SMALLTALK.


14 de octubre de 2009

El antipatrón flecha y el idioma "Dí, no preguntes"

Porque a un objeto nunca se le deben preguntar las cosas... ¡y menos sobre sus partes íntimas!

Hace algún tiempo tenía una conversación con mi amigo Alcides, respecto a unos métodos que él estaba implementando para la capa de datos de un proyecto en el que estaba trabajando. De inmediato noté una configuración familiar: el antipatrón flecha.

Básicamente lo que vemos en un antipatrón flecha es algo así:

   if foo then begin
     if bar then begin
       if baz then begin
         DoSomething()
       end{if}
     end{if}
   end;{if}

Como pueden ver, la disposición del código es algo parecido a la forma de una flecha y de ahí su nombre.

Ahora bien, ¿porqué se considera un antipatrón? Hay varias razones para ello. En primer lugar, obscurece el propósito del código. Es realmente difícil entender que es lo que se está tratando de hacer en medio de esa maraña de if's anidados (si piensan que esto no esta tan mal, agreguen los else's correspondientes). Lo que es más, los seres humanos solo tenemos una capacidad limitada para seguir mentalmente los detalles de lo que estamos haciendo. Por lo general, más allá de 3 niveles de anidación las cosas se vuelven muy difíciles de seguir.

Las causas de que este patrón son muchas y variadas:

  • Seguir ciegamente la regla de "un solo punto de entrada y un solo punto de salida por función".
  • Combinar condiciones complejas y ciclos.
  • Lenguajes de programación sin evaluación booleana por circuito corto.
  • Programadores que no saben que significa el punto anterior... ejem... but I digress...
  • Simple y llana "cultura".

No voy a entrar en una controversia teológica sobre el punto uno, ya que para muchas personas es tan intocable como la divinidad de Elvis Presley.

En código escrito en lenguajes estructurados (sin soporte para objetos), este código es muy común y realmente es difícil llegar a una alternativa para el mismo, fuera de la factorización continua y cuidadosa. Sin embargo, una de las causas de raíz por las que siguen surgiendo incluso en código orientado a objetos, es porque seguimos pensando en términos estructurados.

En lenguajes estructurados, normalmente pensamos de la siguiente manera: llamar-función, obtener-resultado, evaluar-resultado, decisión. Esto está bien en un modelo que favorece el control centralizado de todo lo que sucede en mi programa, sin embargo no están adecuado para un modelo orientado a objetos.

Cuando pensamos en objetos, debemos recordar que estos forman una "red" de entidades que colaboran para lograr un objetivo. Cuando un objeto necesita realizar una acción y para ello requiere del servicio de otro objeto, simplemente va y le pide a aquel objeto que realice la acción necesaria de su parte.

Esto es similar a lo que podría suceder en una oficina cualquiera:

  • Si el jefe es una persona que anima a sus subalternos a tomar responsabilidad de su trabajo, es más probable que delegue en su equipo las actividades para las que están mejor calificados, dejando libre tiempo para que él se concentre en la visión más amplia de las cosas y la planeación estratégica.
  • En cambio, si el jefe es del tipo "controlador", querrá seguir paso a paso cada una de las acciones que llevan a cabo sus empleados, literalmente "respirando sobre sus hombros", para "asegurarse que no cometan errores".

Ok con la nota social, pero ¿Qué tiene que ver eso con los objetos?. Bueno, veamos un caso típico.

Cuando programamos operaciones en una base de datos, es común el manejo de transacciones lógicas, como por ejemplo, al guardar un pedido, se crea una entrada en la tabla de pedidos y una en la tabla de detalle por cada elemento en el pedido. Si por alguna razón alguna de las partes no puede guardarse, toda la transacción debiera abortarse. Ok, una forma típica de codificar esto es:

Conexion.Begin();
...
if Orden.GuardaNueva() then begin
  if Orden.GuardaDetalle() then begin
    if Cliente.IncrementaSaldo(Order.Total()) then begin
      Conexion.Commit()
    end{if}
    else begin
      MensajeError := "No se pudo actualizar el saldo del" +
                      " cliente";
      Conexion.Rollback()
    end{else}
  end{if}
  else begin
    MensajeError := "No se pudo guardar el detalle de la" +
                    " orden";
    Conexion.Rollback()
  end{else}
end;{if}
else begin
  MensajeError := "No se pudo crear la orden";
  Conexion.Rollback()
end{else}

Nada bonito, ¿verdad? Sin embargo, lo de menos es la apariencia. Estas cosas tienen la pésima costumbre de crecer. Es difícil seguir la lógica. Y ¿qué tal si falla la primera condición? ¡Miren hasta donde está su else!

Una opción puede ser aplicar el consejo de Brian Kernighan en The Practice of Programming e invertir el sentido de los if's y unirlos mediante else's:

Conexion.Begin();
...
if not Orden.GuardaNueva() then begin
  MensajeError := "No se pudo actualizar el saldo del" + 
                  "cliente";
  Conexion.Rollback()
end{if}
else if not Orden.GuardaDetalle() then begin
  MensajeError := "No se pudo guardar el detalle de la" +
                  "orden";
  Conexion.Rollback()
end{if}
else if not Cliente.IncrementaSaldo(Order.Total()) then begin
  MensajeError := "No se pudo crear la orden";
  Conexion.Rollback()
end;{if}
else begin
  Conexion.Commit()
end{if}

esto es definitivamente una mejora. Sin embargo, ¿qué pasa si hacemos esto mismo a la usanza de la POO? Tendremos lo siguiente:

Conexion.Begin();
...
Orden.GuardaNueva();
Orden.GuardaDetalle();
Cliente.IncrementaSaldo(Order.Total());
Conexion.Commit();

Esta es la esencia del idioma "tell, don't ask". No necesitamos estar micro-administrando a cada objeto que participa en nuestro código. No debemos hacerlo.

Está bien usar funciones y propiedades para obtener el estado de un objeto, siempre y cuando no se utilize el resultado para tomar decisiones «fuera» de dicho objeto. Cualquier decisión basada enteramente en el estado de un objeto debe hacerse «dentro» del objeto en sí.

Cada objeto tiene sus propias responsabilidades, incluyendo la de verificar que las cosas hayan salido bien y notificar en caso contrario—la forma en que normalmente se hace esto es mediante el uso de “signals” o excepciones, pero eso es material de otro post.

Saludos

25 de septiembre de 2009

Ámbitos y Alcance en Javascript

Dependiendo de los lenguajes programación en los que hemos programado con anterioridad, en Javascript nos podemos topar con algunas sorpresas, y no todas ellas son agradables, Específicamente, puede ser un problema si venimos de un background de lenguajes con alcance de bloque (c, c++, java, etc.) o sin él (basic, pascal, etc.). Ya que el alcance en Javascript puede ser la fuente de bugs muy difíciles de encontrar, a continuación hacemos un pequeño recuento de cómo funcionan los ámbitos de variable en Javascript.

El ámbito "global"

En la mayor parte de los navegadores web actuales, el objeto window es el espacio global que contiene todas las funciones base del lenguaje y todas las variables y funciones que serán definidas en este.

Si se declara una variable, usted verá que usted puede hayarla en el objeto window:

var miAncho = 100;
miAltura = 200;

alert( window['miAncho'] ); // "100"

alert( window.miAncho );    // también muestra "100"

alert( window['miAltura'] ); // "200"
alert( window.miAltura === miAltura ); // "true"

Obviamente, no todo es accesible desde el objeto window, ya que en Javascript podemos usar el ámbito de nivel de función.

Declaración de variables

Tal vez esto sea obvio para muchos, pero para mi inicialmente fue una duda que durante algún tiempo limitó mi entendimiento de Javascript. En Javascript, es perfectamente válido declarar una variable con la palabra reservada var ¡O sin ella! (a todos los que hemos programado en Basic alguna vez, nos trae hermosos recuerdos de lo grandioso que nos parecía esta "característica"... hasta que nos ocasionó nuestro primer dolor de cabeza).

La idea básica que debemos entender es que var no es solo lo que la abreviación parece indicar: una declaración de una variable, sino por el contrario, es la definición del alcance de la misma. En el ejemplo anterior hemos usado ambas notaciones y podemos ver que en el caso del alcance global, el ámbito de la variabe no se modifica.

// Al estar en el ámbito global, ambas lineas
// son equivalentes
var miAltura = 100;
miAltura = 100;

En el especio de nombres global, la instrucción var no tiene ninguna repercusión, por lo que podemos hacer algo como esto:

var miAltura = 100;
miAncho = 100;

function muestraVariables() {
 alert( miAltura + ' y ' + miAncho);
}

Las variables declaradas en el ámbito global serán accesibles desde dentro de todas las funciones, pues todas están también contenidas en el objeto window. Sin embargo, las cosas cambian cuando usamos var en el contexto de funciones. A continuación vemos un ejemplo en el que var modifica el alcance de una variable:

var miAltura = 100;
miAncho = 100;

function muestraVariables() {
 alert( miAltura + ' y ' + miAncho);
 var miColor='#000000';
 miFondo='#FFFF00';
}

function muestraColores() {
 alert( miColor + ' y ' + miFondo );
}

muestraVariables(); // "100 y 100"
muestraColores();   // "undefined y #FFFF00"

Aquí es conveniente prestar mucha atención a la manera en que muestraVariables define variables. La variable miColor está definida usando var, mientras que miFondo no la usa. De hecho, cuando una variable es definida sin utilizar var dentro de una función, tras bambalinas esto es como Javascript lo interpretaría:

function muestraVariables() {
 alert( miAltura + ' y ' + miAncho);
 var miColor = '#000000';
 window.miFondo = '#FFFF00';
}
Cada variable que no se defina usando la instrucción var en el contexto de una función, será asignada al objeto window y por lo tanto se convierte en una variable global.

Una variable definida dentro de una función con la palabra var se vuelve inaccesible desde el exterior, y es por ello que podemos decir que efectivamente se convierte en una variable privada.

También es posible crear funciones dentro de otras funciones:

function muestraVariables() {
 var miColor ='#000000';

 var miOtraVariable = function () {
     return miColor;
 }

 alert( miOtraVariable() );  // "#000000"
}

// fuera de la función
alert( miOtraVariable() );   // ¡Error!

Las variables definidas dentro de muestraVariables son inaccesibles fuera de ella, aunque miOtraVariable guarde una referencia a una función. Sin embargo, podemos ver que la función anidada si tiene acceso a miColor, ya que la función misma está definida dentro de muestraVariables.

Por lo anterior, podemos concluir que se debe evitar colocar variables e incluso funciones en el ámbito global, ya que por ejemplo, si se usa el mismo nombre de variable o función en dos archivos JS distintos, el último de ellos “sobreescribe” las definiciones del anterior, lo que en un momento dado implica que ¡Es posible que no estemos trabajando con las funciones o variables que pensamos!

En Javascript, el último en llegar gana.

En realidad, esto no es muy relevante si solo usamos una o dos funciones en una página web, pero cuando tenemos que trabajar en un equipo de desarrollo, cuando utilizamos o tenemos que convivir con código de terceros o cuando incorporamos bibliotecas externas en nuestra aplicación y si todos ellos colocan sus variables y funciones en el contexto global es posible que tengamos un mal rato tratando de entender porqué no obtenemos los resultados que esperamos, ¡Pensando incluso que se trata de un bug en nuestro código!

Alcance de nivel de bloque

En Javascript no existe el ámbito de variables a nivel de bloques, por lo que debemos estar atentos al hecho de que cualquier variable definida dentro de un bloque de código (for, while, if, switch, etc) será accesible desde el ámbito inmediato superior (siguiendo las reglas explicadas anteriormente con respecto al uso de var).

if( miAncho == 100) {
   var miAltura=200;
}
alert( miAltura ); // "200"

Esta es una diferencia fundamental con respecto a Java, en el cual el tiempo de vida de una variable termina al cerrarse el bloque que la contiene.

for(var i=0; i<=100; i++) {
   miColor=i;
}

for(; i<50; i++) {
   miAncho=i;
}

alert(miColor); //100
alert(miAncho); //error

Al definir la variable i con la palabra reservada var no se le da alcance de bloque dentro del ciclo for. Por lo tanto, al entrar al siguiente ciclo, el valor de i es 100, por lo que nunca se entra al segundo ciclo.

Esto no significa que no debamos definir variables dentro de bloques. Es importante que las variables se declaren lo más cerca posible del lugar en el que se usarán para aumentar la claridad de nuestro código. En este aspecto, es similar a utilizar Dim en Basic para declarar una variable dentro de un IF o un WHILE. Aunque posición de la declaración no cambia la semántica de la misma, si tiene un efecto en el potencial de comunicación de esta.

Objetos, Funciones y alcance

Hemos visto que la palabra var solo tiene significado dentro del contexto de una función, lo que nos habilita a tener variables privadas y globales si así lo deseamos. Sin embargo, las funciones nos posibilitan un nivel más de alcance: el “nombre” de la función.

Hemos visto que todas las variables definidas dentro de una función sin la instrucción var son asignadas al objeto window. Ok, pero digamos que queremos escribir código limpio y evitar el uso de variables globales, ¿Cómo podemos hacerlo?

De hecho, fuera de una función, en el ámbito global, podemos usar otro método para referirnos al objeto window mediante otra palabra reservada: this.

La palabra this tiene un papel muy importante en Javascript, pero al mismo tiempo es una fuente de confusión cuando se comienza a programar en este lenguaje.

Poniéndolo de forma llana, this siempre “apunta” al contexto actual en el que se está ejecutando nuestro código. Veamos por ejemplo:

miColor = 100;

alert( this.miColor );    // 100
alert( window.miColor );  // 100
alert( window === this ); // true

Como podemos ver, this en el ámbito global hace referencia al objeto window.

Por otro lado, las funciones también nos permiten utilizar this, pero en este caso, this no se referirá al objeto window. ¿Entonces a qué?

Como se mencionó anteriormente, todas las funciones están siempre asociadas a un objeto. Si la función se declara globalmente, entonces están asociadas al objeto window; si son “métodos” de un objeto, entonces están asociadas a ese objeto. Y this siempre apuntará al contexto dentro del cual se ejecuta una función, por lo que dependiendo de la forma en que llamemos a una función, puede afectar el contexto al que apunta this:

function miFunc() {
  alert( this === window );
}
miFunc();     // true
new miFunc(); // false

En este caso, this está apuntando a algo más que no es el objeto window. Para entender qué es ese algo, veamos cómo interpreta Javascript la última linea del ejemplo:

new miFunc();
 temp = new Object();

 temp.miFunc = miFunc;
 temp.miFunc()

Cuando se usa una función para inicializar un objeto (usando la palabra new, se dice que esta función es el constructor de ese objeto y el nombre de esa función se convierte en la clase del objeto.

Podemos comprobar que this se refiere a un objeto con el nombre de la función utilizando el operador instanceof, que nos dice si un objeto es de una “clase” específica o bien la propiedad constructor:

function miFunc() {
  alert(this instanceof miFunc);
  alert(this.constructor == miFunc);
}

miFunc();     // false, false
new miFunc(); // true, true

Todo esto puede sonar un poco confuso. Trataré de explicarme: Al usar la palabra reservada new se crea un objeto temporal en el background por nosotros, mismo que se asociará al nombre de nuestra función. Pero, ¿para qué nos sirve esto?

Bueno, en primer lugar nos habilita a utilizar un nivel más de alcance, el de objeto, que es similar al concepto de variables de instancia de los lenguajes orientados a objetos tradicionales. Con esto tenemos 3 niveles distintos:

function pruebaAlcance() {
    global = 100;

    var privada = 200;

    this.publica = 300;

    this.metodoPublico = function() {
         alert( 'puedo ser usado desde el objeto pruebaAlcance' );
    }
    var metodoPrivado = function() {
        alert( '¡No puedes llamarme desde el exterior!' );
    }
}
pruebaAlcance();

alert( global ); // 100

alert( privada ); // error

alert( pruebaAlcance.privada ); // undefined

alert( pruebaAlcance.publica ); // 300

alert( publica ); // undefined

alert( pruebaAlcance.metodoPublico() ) // 'puedo ser... etc'

alert( metodoPublico() ) // error

alert( pruebaAlcance.metodoPrivado() ); // error

alert( metodoPrivado() ); // error

Los niveles de alcance de Javascript pueden parecer extraños en un principio y puede costar trabajo acostumbrarse a ellos en un principio, pero también pueden ser una herramienta poderosa al momento de construir bibliotecas o convivir con código de terceros sin pisar los dedos de nadie más.

Las diferentes formas de declarar variables o métodos dentro de una función u objeto es la base mediante la cual se pueden simular espacios de nombres (namespaces) en Javascript y son la base de las técnicas orientadas a objetos del mismo.

Espero haya sido de su interés.

Este post fue publicado originalmente el 30 de Septiembre de 2008 en un blog anterior y posteriormente perdido en un crash de servidor.

23 de septiembre de 2009

Antipatrón: Requerimientos lanzados sobre la pared

Siguiendo con la discusión sobre requerimientos, recordé que alguna vez leí sobre el antipatrón llamado "Requiremens Tossed Over The Wall".

Básicamente el contexto es el siguiente:

Al equipo de desarrollo se le da una visión de muy alto nivel sobre el sistema y se le pide (como parte del "proceso", claro está) que desarrolle una propuesta completa y detallada. El experto del lado del negocio revisa la propuesta y hace varios comentarios sobre algunos errores obvios. Si los desarrolladores tienen alguna duda durante la fase de construcción, se concertará una cita para una reunión o, dado que las reuniones son asuntos relativamente caros, elaboran una lista de preguntas que son enviadas via e-mail. El experto eventualmente responderá a las dudas del equipo cuando tenga algo de tiempo disponible. Finalmente, el sistema es entregado y el cliente trata de utilizarlo, pero informa al equipo que hay varios "errores" que deben ser corregidos.

¿Suena conocido? Bueno, no es de extrañar, ya que de hecho es la forma en que se desarrollan la gran mayoría de los proyectos. Pero, ¿qué onda con el nombre raro? Bueno se debe a que mayormente, el desarrollo de requerimientos cesa en el momento en que la codificación comienza. Simplemente, los lanzo por encima de la pared y me olvido de ellos: "ya no es mi problema".

Cruelmente, la realidad suele ser bastante distinta. En realidad, esta forma de pensar asume que los requerimientos del sistema son de hecho estables, o que permanecerán estables el tiempo suficiente como para entregar el sistema terminado. A menos que trabajemos en un dominio en el que los requisitos dependan más del ambiente físico (el sistema de aviónica de un 747, por ejemplo) que del cambiante mundo de los negocios, generalmente las cosas no son así.

En cuanto al usuario, no quisiera adoptar una postura radical como la expresada en la primera edición de "Extreme Programming Explained: Embrace Change" de Kent Beck, en la que básicamente ベック先生 nos dice que todos los proyectos deben tener a un usuario del lado del negocio asignado al 100% durante la duración del mismo, y trabajando en el mismo lugar que el equipo. Si bien es cierto que eso sería lo deseable, en muchos casos no es posible, ya sea por una verdadera imposibilidad operativa o bien por cuestiones de idiosincrasia. Sea cual fuere la razón, incluso el mismo Beck ha flexibilizado su postura al respecto con el tiempo.

Lo que no ha cambiado en lo absoluto es el hecho de que una gran parte de responsabilidad sobre el éxito o fracaso del proyecto recae en que el usuario se involucre directamente en él. Muchos usuarios hoy en día siguen creyendo que el desarrollo de software es como mandar hacer un closet, para lo cual basta elegir un modelo del muestrario del carpintero, que éste último tome medidas y esperar un número de días acordado para recibir aquello por lo que pagué.

Seamos realistas. Si este fuera el modelo a seguir, todos los usuarios podrían irla llevando solamente usando software COTS. Sin embargo en el mundo real, las cosas no son así. La mayoría de los negocios tienen particularidades que los hacen únicos. Los gerentes y directivos aplican estrategias que los diferencian de su competencia. Sus políticas son diferentes. Sus procesos son diferentes. No importa cuantos sistemas de control de producción se hayan programado, jamas se hacen dos iguales. Si, hay una gran área común entre sistemas para diferentes empresas dentro de una misma industria (y es aquí donde la experiencia ganada en una ventaja), pero finalmente quien realmente sabe cómo llevar el negocio es... si, el usuario.

En México tenemos un proverbio muy folclórico, pero muy atinado:

A ojo del amo crece el caballo.

Si de este sistema depende el poder aprovechar una oportunidad de negocio o no, el poder atacar un problema recurrente en mi organización o dejarlo como está, el obtener información fidedigna hoy para poder tomar las decisiones correctas sobre el rumbo a tomar mañana, ¿no debería entonces yo por lo menos dedicar por lo menos una parte de mi tiempo o la de algún colaborador que conozca el negocio lo suficientemente bien, para asegurarme que las personas que van a desarrollar el proyecto hayan entendido correctamente mis necesidades? ¿que hayan entendido cual es el problema que se pretende atacar, el valor de negocio que se pretende obtener?

Esto no solo disminuye sensiblemente el riesgo de llegar 6 meses después a la fecha de entrega para darnos cuenta de que el sistema está mal, sino permite aprovechar la experiencia y el talento del equipo de desarrollo para obtener soluciones más creativas que las que inicialmente podríamos haber imaginado.

El valor real de los requerimientos bien levantados y desarrollados es que dan la oportunidad al equipo de desarrollo de expresar en el lenguaje del usuario cuales son sus necesidades y expectativas, y así asegurarse de que las ha comprendido correctamente. Los requerimientos escritos (especialmente los casos de uso o "especificaciones funcionales") son antes que nada una herramienta de comunicación:

  • entre el usuario y el equipo de desarrollo
  • entre miembros del equipo de desarrollo
  • entre miembros actuales y futuros del equipo
  • entre miembros actuales y futuros del negocio

Si, la comunicación directa y frente a frente es la más efectiva, pero los requerimientos pueden ser también altamente efectivos cuando se usan correctamente y se desarrollan por las razones correctas; esto es, cuando aportan valor al proyecto.

Y por el amor de Dios... no pidamos documentar 400 páginas de requerimientos que nadie piensa leer con la única justificación de que "el proceso lo exige".

17 de septiembre de 2009

¿Casos de uso ágiles?

Pues si. Mi última aventura ha involucrado el delicioso asunto de documentar casos de uso que nadie va a leer jamás. O por lo menos no lo suficiente como para justificar el esfuerzo requerido en ello.

No me malinterpreten. En realidad yo no creo que toda la documentación, el levantamiento de requerimientos y la elaboración de casos de uso sea una perdida de tiempo. Pero si lo son cuando se elaboran exclusivamente para "cumplir con el requisito".

But I digress... lo que realmente quiero comentar aquí es la manera en que atacamos el problema de la documentación de requerimientos. Una de las partes más frustrantes del proceso es la casi infinita variabilidad en cuanto a los formatos "oficiales" que manejan las empresas para estos menesteres. Es verdaderamente desmotivante el hecho de tener que hacer un cierto trabajo, querer hacerlo bien (porque por más que nos desagrade, aún tenemos nuestra ética) y descubrir que no puedes avanzar como quisieras por que tienes que estar lidiando con las idiosincrasias del procesador de palabras, en lugar de poder concentrarte en lo que realmente importa de la documentación (aunque muchas personas lo duden): el contenido.

La solución que encontramos es utilizar una tecnología a la que desde hace varios le tengo un especial cariño: XSLT (Transformaciones del Lenguaje Extensible de Hojas de Estilos).

La idea es definir un esquema sencillo XML para el documento principal (el contenido) y utilizar XSLT y CSS para formatear el documento final. Nuestro esquema tenia elementos como <caso>, <flujoPrincipal>, <paso>, etc. Esto nos permitió olvidarnos durante la mayor parte del tiempo del formato del documento y concentrarnos en escribir casos de uso que fueran claros y tan completos como fuera posible. Además, ¿no es eso lo que predican las reglas del buen diseño?

Desacoplar el modelo de las vistas.

O como lo dirían los diseñadores Web:

Separar el contenido y el formato.

Una gran ayuda fue la utilización de Komodo Edit para la edición del documento HTML, ya que este editor permite tener una vista previa del documento final y tiene una función de corrección de ortografía muy útil. Como utiliza los mismos diccionarios que Firefox y Thunderbird, es muy sencillo de utilizar y extender.

Otra herramienta que fue invaluable fue el programa Prince XML, que permite generar un documento en formato PDF a partir de un XML o HTML. Nos dio un gran control sobre el layout de la página con sus extensiones para CSS. Verdaderamente una herramienta fantástica.

Finalmente, el que para mi es la estrella de la película es GNU make. Seguramente que alguien se podrá preguntar "¿Qué? ¿make? ¿Qué eso no es para programadores en C?". Bueno, si lo es. Pero no necesariamente debe tratarse de un proyecto en C para que make sea útil. En realidad, Prince es una herramienta genial, pero cuando tienes que generar un documento PDF de alrededor de 380 páginas, el proceso se vuelve algo lento.

El poder de make para verificar dependencias y generar (o regenerar) partes o artefactos de forma automática, es un lujo que muchos programadores de hoy en día nunca han tenido y muchos programadores con algunos años de experiencia ya no recuerdan. Lo que es más, nos permitió validar nuestros documentos en tiempo de "compilación". Al momento de aplicar la hoja XSL, nuestro makefile hace una llamada a msxls para validar el documento contra el esquema. Eso por sí mismo nos ahorró muchos problemas (en especial cuando el documento comenzó a crecer y tanto Komodo como Stylus Studio se comenzaron a poner lentos). Además antes de pasar el resultado a prince, make lo pasaba primero a través de tidy para verificar el código generado por nuestra hoja XSL.

Un detalle que pasamos completamente por alto y que pudo ser de gran ayuda fue el uso de XSL-FO (XSL Formatting Objects). La primera vez que escuché de esa tecnología todavía estaba muy cerca del "bleeding edge" como para considerarla seriamente, pero parece que hoy en día se encuentra mucho más madura. Tendré que hacer una nota mental para estudiarla seriamente un día de estos

Mientras que sigo dudando que el proceso de documentar casos de uso se vuelva alguna ves una de mis actividades favoritas, con algunas de las cosas que aplicamos en este proyecto, me parece que no debe ser tan oneroso después de todo.

9 de septiembre de 2009

Antipatrones

Steven R. Covey menciona en su libro "El poder de los 7 hábitos" que una manera efectiva de estudiar algo es estudiar su opuesto.

Bueno, mientras que al tema de los patrones (especialmente los de diseño) se le ha dedicado una gran cantidad de "lip service" durante los últimos años, un tema paralelo y en mi opinión, igualmente importante, es el de los antipatrones.

¿Qué es un antipatrón?

Un antipatrón es una solución común que se da a problemas recurrentes en un contexto dado, que trae consecuencias negativas para el proyecto en el que se aplican.

En otras palabras y como decimos en México: el remedio es peor que la enfermedad.

¿Porqué es importante el estudio y difusión del conocimiento en antipatrones? ¡¡Porqué desgraciadamente son mucho más comunes de lo que deberían ser!!

Estas "soluciones", son consideradas como alternativas viables por muchos profesionales e incluso, algunos han hecho de ellos una forma de vida.

Para muestra basta un botón:

Programación de copiar y pegar (copy and paste programming):
Programar copiando y modificando código existente en lugar de crear soluciones genéricas.

Ahora bien, todos lo hemos hecho, ¿o no? y todos deberíamos saber a estas alturas las consecuencias de hacerlo de manera indiscriminada durante algún periodo de tiempo:

  • Redundancia innecesaria
  • Mayor complejidad inherente
  • Pobre mantenibilidad
  • Alta propensión a errores, etcétera

Sin embargo, hace pocos años tuve una compañera de trabajo que a los nuevos programadores que entraban a su cargo los adiestraba con su "metodología" de desarrollo, más o menos así:

Bajas el módulo X del control de versiones y haces una copia. Le cambias el nombre al módulo y lo pegas en el proyecto donde lo vayas a ocupar. Después te copias el texto del módulo "globales" del proyecto original y lo pegas todo en el "globales" de tu proyecto y comentas todas las variables. Después comienzas a descomentarlas una por una hasta que compile bien.

Lo que intento decir es que algunos de los problemas que describen los antipatrones son cosas que hacemos todos los días sin darnos cuenta de las consecuencias que traerán al proyecto. Algunas las hemos hecho desde que aprendimos a programar. Algunas nos fueron enseñadas explícitamente por nuestros maestros y otras han estado con nosotros desde los albores de la programación.

La única forma de detener la diseminación de estas malas prácticas es la educación, tomando responsabilidad de nuestra propia práctica como profesionales.

En futuras entradas, tengo la intención de discutir con mayor detalle algunos de los antipatrones conocidos. Hasta entonces, les dejo algunos links:

8 de septiembre de 2009

Presentación

Antes de comenzar, quiero contestar una pregunta que seguramente alguien que pasa por esta página se pueda hacer: ¿Porqué necesitamos otro blog sobre programación?

Bueno, la respuesta que tengo es algo ambigua: No lo necesitamos. O por lo menos no creo que nadie en el mundo necesite mis opiniones al respecto. Esto es algo que me gustaría dejar bien claro. No quiero asumir que poseo la verdad absoluta sobre algún tema o presumir que soy más inteligente que nadie más o que los lectores que pudiesen leer este blog sean más tontos que yo. Esa clase de blogs hay muchos y muy variados allá afuera.

Más bien, lo que pretendo (algo así como la "visión" para este blog) es solamente compartir mis experiencias al aprender y aplicar lo aprendido sobre desarrollo de software.

Durante años (me inicié en este asunto por allá de de 1989) creí que sabía bastante sobre programación de computadoras. Conocía varios lenguajes, entre los que se incluían Pascal, C++ y ensamblador. Más aún, en su momento aprendí a utilizar las extensiones de objetos de Pascal y C++ y creía que lo entendía perfectamente: son estructuras de datos con sub-rutinas integradas.

Bueno, todo mi mundo de sueños y la ilusión que tenía se vinieron abajo cuando llegó a mis manos una copia de "Refactoring: Improving the Design of Existing Code" de Martin Fowler. Ese libro cambió mi vida. No solamente me dio una perspectiva totalmente nueva de lo que yo creí que sabía, sino que me hizo darme cuenta que no entendía ni una palabra de lo que era la Programación Orientada a Objetos... y que la gran mayoría de los libros, profesores, cursos y colegas programadores que había conocido a través de los años, ¡Tampoco lo entendían!

Al poco tiempo y de nuevo, gracias a Mr. Fowler, descubrí los Patrones de Diseño, los Métodos Ágiles y a figuras enormes (como Kent Beck, Ward Cunningham, Robert C. "Uncle Bob" Martin, entre otros) que poco a poco transformaron mi forma de ver y entender el desarrollo de software.

Hoy, casi 10 años después de aquel momento "¡¡Ajá!!", sigo aprendiendo y sigo intentando aplicar a mi trabajo de todos los días, lo poco o mucho que he absorbido de esos gigantes a los que yo humildemente llamo "私の先生" (mis maestros), mis "role models".

Este blog es solo un intento de relatar los éxitos y frecuentemente, los fracasos en esa búsqueda. Espero que mis amigos que se me han unido en mi obsesión me acompañen nuevamente en esta nueva aventura y que ud. amable lector, encuentre algo de interés y cómo no, me ayude con sus comentarios, dudas, críticas y correcciones.