Friday, May 5, 2006

Consejos para programadores

Tim Allen

He sido programador desde el momento que escribí mi primer programa de FORTRAN utilizando tarjetas de Holerith cuando tenía 15 años (imprimió la fecha de la boda de Carlos y Diana-- mi madre lo tiene en un cajon en algún sitio). Ha sido más o menos una adicción desde entonces. Pensaba aprender japones y trasladarme a Tokyo para escribir juegos electronicos por Nintendo. En cambió, aprendí castellano y me trasladé a Barcelona para escribir programas de bases de datos. Los sueños de la juventud...

En los más de 20 años que llevo programando, he aprendido un par de cosas. He hecho practicamente todos los errores posibles (y tal vez imposibles) que se pueden hacer. Y no sólamente como programador, sino como empleado, jefe, entrenador, estudiante... soy como una máquina de errores. Sin embargo, como dijo Socrates, "Quién sabe lo que no sabe es lo más sabio". Cada error me ha ensanyado mucho (a veces he disfrutado tanto de la lección que he vuelto a hacer el mismo error varios veces).

Bueno, basta de farfullar-- os voy a explicar unos cuantos de los errores que evitar, porqué evitarlos, y cómo evitarlos. Tal vez os sirve de algo:


Errores de Programación

Error: No tener plan ningúno:

Posiblemente lo más habitual. La mayoría de los programadores se sientan más cómodos programando que hablando con el cliente. Sabemos más de nuestros lenguajes y sistemas operativos que negocios. Por eso existen analistas.

Para sistemas pequeños, a veces tiene sentido que el plan sea "Empecemos programando ahora mismo y veamos que sacamos". Esto no es ningún pecado-- la mayoría de los programas que escribo para mi hijo y mi mujer empiezan así. Mientras tengo en mente que ése es el plan, no tiene nada de malo.

Pero con sistemas más grandes, a menudo el problema no se entiende bien la primera vez que se explica (ni la segunda, la tercera....) Si empezamos con el problema en mente en la forma original en que lo hemos entendido, el peligro es que vestigios de esa primera impresión equivocada se queden en el sistema hasta la versión 10.3 (vease Windows).

Error: Asumir que entendamos el problema cuando no sea cierto:

En base, este error se puede reducir a un problema de comunicación. El cliente habla en su dialecto ("Quieremos un sistema que gestione ventas de la línea 3542 (verano)"). Los analistas hablan en el suyo ("Quieren un sistema de Business Intelligence con Balanced Scorecard como sistema de DSS"). Y nosotros hablamos en el nuestro ("Quieren unas bases de datos Oracle con datacubes y los front-end en Java y PHP"). Añades el lenguaje de los vendedores ("Hace tiempo que no vendemos un sistema de Darwin-- este cliente es perfecto") y tenemos lo que se llama una maraña.

William James dijo algo al afecto que la manera más rápida de no aprender algo era asumir que ya lo entendiamos. Lo más sensato es llevar una sensación de incertidumbre sobre lo que hace el sistema en cada momento. No tengáis miedo de preguntar a los demás del equipo o incluso al cliente qué significa algo si no lo entendéis completamente. El problema aquí es que a nadie le gusta parecer tonto o que no hacía caso en algún momento. Pero la mera verdad es que casi nadie puede captar todas los matices de un problema en la primera vista. Por eso el analisis y la programación son procesos iterativos. A lo mejor lo preguntas al cliente qué significa la línea 3542 (verano) y no lo sabrá tampoco.

Error: Utilizar el prototipo como base del sistema final

A veces hace falta hacer alguna maqueta para entender el problema. Lo ensenyamos a los analistas, ellos hacen sugerencias, lo cambiamos, los analistas se quedan felices, lo demostramos al cliente, y después de unos cuantos cambios, él también queda convencido de la interfaz. Bien.

Ahora, ¿qué hacer con la maqueta? Lo más habitual es llevarlo a la oficina y empezar el primer borrador del sistema con él. Pecado mortal. Ya lo sé, porque lo he hecho vez y otra vez. Odio el concepto que he hecho un montón de trabajo en la maqueta y ya lo tengo que hacerlo otra vez. Pero hay buenas razones para reiniciar el desarollo:

  • Ya que entendemos el problema, puede que la maqueta no sea escrita en el lenguaje más adecuado. Un buen ejemplo de esto es que una maqueta de un programa te puede costar un día de programar en Perl/Tk o Visual Basic, tener buen aspecto, funcionar de maravilla en la demostración, y fallar completamente cuando tenga que operar contra datos reales. Pero utilizando los mismos conceptos de la interfaz de la maqueta en un sistema final escrito en C++, el rendemiento se mejora. La misma maqueta escrita en C++ te hubiera costado dos semanas, así que hemos aprovechado de las fases de maquetar y de finalizar el sistema en la mejor manera.
  • En el proceso de hacer la maqueta, a lo mejor hemos empezado por un sendero, lo hemos dejado, hemos empezado por otro, hemos decidido que el primero era mejor... al final hay muchos cabos sin atar. Lo puedes ver en sistemas escritos en Visual Basic-- casi siempre hay una ventana llamada "Form1" (el nombre por defecto de nuevas ventanas) que tiene dos o tres botones encima y no está conectada al programa de ninguna manera. Cuando tengo que arreglar uno de estos, triplico mis estimaciones del tiempo de cumplir.
  • Empezar escribiendo el sistema otra vez nos exige entender bien el problema. En el proceso de maquetar, el enfoque está en hacerlo funcionar. Pero tal vez no hemos hecho mucho caso a todos los detalles del analisis, intentando cumplir los requerimientos más importantes. En la versión final, podemos aprovechar del hecho de que ya (esperamos) entendemos mejor el problema.

Error: Poner datos de prueba/mensajes de error tontos/obscenos/políticos

Ya lo sé, la tentación de hacerlo es tremendo-- tienes que inventar cien personas de prueba para comprobar que los datos se leen bien. Y ningun nombre te ocurre otro que Jordi Pujol o Jose María Aznar. O estás en la fase de depurar y hay un bug que no se va, así que (con un poco de frustración), escribes un gestor de errores con un mensaje como, "El maldito cliente ha hecho click en el maldito botón dos malditas veces, leche!".

Pues, os tengo un par de historias sobre el tema que contar. Primero: erase una vez, en un reino no tan distante, un programador de Visual Basic trabajando en el Ministro de Presupuestos del Presidente de Los Estados Unidos. La noche anterior de la demostración ante el cliente, el programador estaba trabajando hasta las tantas intentando arreglar un bug de lectura de datos. Lo habia localizado en un módulo global (fijados en la palabra "global"), y el arreglo era tan elegante, tan inteligente, que el programador, feliz en el hecho de que sus cuatro años de universidad le habia ensenyado algo, puso el mensaje de error, "Apuesto que el cliente nunca verá este error." Bastante inocente.

Y menos mál, porque el día siguiente, el programador, aun convencido de sus poderes ultra-programadoriales, hizo la demostración. Os recuerdo que el módulo de nuestro heroe era global, o sea, todo clase de función en el programa acudía a ese modulo para obtener datos. El programador arrancó el programa, tocó el botón de mostrar los primeros datos, y: Apuesto que el cliente nunca verá este error. Nuestro programador itenerante sonrió, explicó que era una pequeña broma, y siguió con su presentación. El único lugar en que no salió el error Apuesto que el cliente nunca verá este error era en la pantalla en que salió el error durante sus pruebas originales. Por semanas mis compañeros me decían, "Apuesto que el cliente nunca verá este error!". Desde entonces, 1) No trabajo hasta las tantas el día anterior a la demo, y 2) Mis mensajes de error siempre son:


Código de error: xxx
Un error ha ocurrido: ....

Otra historia, un poco más fuerte. En 1998, la compañia AutoDesk sacó al mercado una nueva versión de su producto AutoCad Mechanical. Cien mil copias se vendieron en los primeros meses. Cien mil copias, todos con un mensaje de ayuda que dijo:

Click this to display an overview of this dialog box, idiot.
Haga clic en esta pantalla para ver una explicación, idiota

Como os imagináis, AutoCad tuvo que reemplazar todas las copias del programa. El presidente de la compañía tuvo que enviar una carta disculpando AutoCad del hecho. ¿Y el programador? Se quedó en paro, y supongo que ya es un taxista (no digo que hay nada mal en ser taxista, pero a mi me gusta programar).

Ni siquiera pongo mensajes tontos en mis propios programas que escribo en casa. ¿Porqué? Por que el día de mañana me daré cuenta que el problema en que estoy trabajando tiene solución en ese programa que escribí para mi hijo Daniel hace dos semanas. Copiar, pegar, y funciona, sin que tenga que revisarlo a ver si hay algo que no quiero que el cliente vea.

Por cierto, ese consejo también se puede aplicar facilmente al mundo de los analistas. Alguna vez habeis visto un documento de analisis con una sección que dice:



Technical Architecture
El Tim aún no me ha dicho nada de eso...

Queda un poco mal. Mejor que otra persona mire tu documento antes de entregarlo. Lo cual nos lleva al próximo punto:

Error: Depurar tu propio programa

Cada persona usa el ordenador de forma distinta. Yo, por ejemplo, no suelo utilizar el ratón mucho (que dinosauro soy). Veo a otras personas utilizando un programa que he escrito y me soprende bastante que hacen cosas que a mi me parece completamente a reves. Así que, casi seguro que cuando yo arranco mi propio programa, no me va a fallar. Pero el usuario puede hacer acciones que a mi nunca me ocurriría. Por ejemplo, cuando hago un programa de Web, y sale un campo para poner un numero de teléfono, suelo poner el número de la oficina, o mi casa, o otro que sea un valor "legal". Pero tal vez mi usuario no tiene teléfono. Pone "No lo tengo" en el campo. Y si no he depurado bien, el programa falla.

No soy genio. Hay muy pocos, y suelen ser aun más despistados que yo. A Einstein le costó 2 años descubrir que habia hecho un error simple en su teoría de la curvatura del espacio-tiempo, lo cual no se resolvió hasta que su amigo David Hilbert miró sus ecuaciones y descubrió el error. Si lo pudiera pasar al mismisimo Einstein, seguro que me pasa a mi.

Napoleon tenía un caporal a quien le explicó todos sus planes. Si el caporal no lo entendió, sabía que el plan no iba a funcionar. En muchas empresas, hay una persona no técnica que sirve como "El caporal de Napoleon". Es la persona que hace pruebas del programa, y explica si el interfaz es imposible entender a una persona no técnica.

Los depuradores profesionales suelen ser gente no muy populares con los programadores.

Error: No documentar, o olvidar sacar comentarios "muertos"

Los programadores tenemos fama de ser gente a quien no le gusta hacer documentación. No soy una excepción. Hay un refran de los programadores: buen código se auto-documenta. Y un jamón. La verdad es que cuando miro mi propio código a una semana después de escribirlo, me pregunto lo que estaba intentando hacer. Aquí os pongo un ejemplo:


#include <stdio.h>
main() {
double n,d,a;
for (a=0,n=1.0,d=1.0;d<10000;a+=n/d,d+=2,n*=-1)
printf("%.6f\n",a*4.0); }

Este es un programa completamente legal en ANSI C. Incluso funciona bien y rápido. Pero es muy difícil entender lo que hace y cómo. Si tuviera que arreglar el programa, tendría que encontrar el programador original (y no le hablaría con mucha calma).

Aquí está el mismo programa, formateado y con comentarios. Se ve facilmente cómo funciona, incluso por no programadores:


/* Programa: pi.c
* Autór: Tim Allen
* Descripción: Implementa el algoritmo de la serie infinita de Arctangente
* descubierto independientamente por James Gregory (1638-1675) y
* Gottfreid Wilhelm Leibniz (1646-1716).
* La serie funciona así:
* x^3 x^5 x^7
* arctan(x) = x - --- + --- + --- + ...
* 3 5 7
*
* y como arctan 1 = π / 4, sigue que π = 4 * arctan(1)
* Referencia: http://www.escape.com/~paulg53/math/pi/greg
*/

/* Incluir la biblioteca estándar de entrada/salida */
#include <stdio.h>
/* definimos constantes */
#define MAX_DENOM 10000
#define EXITO 0
int main() {
/* declaramos y inicializamos valores de la ecuación */
double numerador = 1.0;
double denominador = 1.0;
double arctan = 0.0;
/* un bucle para implementar la serie infinita */
for (denominador=1.0; /* inicializamos el denominador a 1 */
denominador < MAX_DENOM; /* bucleamos hasta que el denom > 10000 */
denominador+=2) /* después de cada bucle, incrementamos el denom */
{
/* incrementamos el valor del arctan del próximo
* valor de la serie */

arctan += numerador / denominador;
/* imprimimos el resultado multiplicado por 4 */
printf("%.6f\n",arctan * 4.0);
/* cambiamos el signo del próximo valor en la serie */
numerador *= -1;
}
/* devolvemos el valor de exito al sistema operativo */
return EXITO;
}

Os mentiría si dijera que siempre hago comentarios tan extensos para programas-- por ejemplo, un programador no suele necesitar comentarios para entender cómo funciona un bucle for. Incluso puede resultar molesto si hay demasiados comentarios. Pero mejor demasiado que demasiado poco.

Otro problema en poner comentarios en el código es olvidar borrar comentarios "muertos". Si cambiamos de idea medio rumbo, hay que acordarnos que los comentarios haciendo referencia a la idea original ya son invalidos.

Consejo: Separa la interfaz de la parte funcional

Es un error concentrate en la interfaz demasiado temprano. Es posible que pases todo el tiempo alocado arreglando dónde van los botones y el color de los iconos y pierdes algo importante en los requerimientos. Si se puede separar la interfaz completamente de la parte funcional del sistema, mejor. Esto te deja la posibilidad de desarrollar varios interfaces para el mismo programa sin duplicar trabajo.

La extensión avanzada de esta idea es el scenario Cliente-Servidor. Aquí, la parte funcional del programa se ubica en otra máquina que la interfaz. A menudo hay mejores en rendimiento importantes en sistemas construidos así. Incluso existe el concepto de la arquitectura "3-tier" en que una máquina se encarga de los datos, otra del programa, y otra de la interfaz.

Consejo: Trucos para la demostración

Hacer una demostración del producto es como pedir que falla algo. No es mi tarea preferida. Pero tarde o temprano el cliente querrá ver el progreso de la obra. Así que he compilado una lista de truquillos para suavizar el proceso un poco:

  • Evita enseñar cada caracteristica del producto. Resulta monotono para el cliente. Lo mejor es hablar mucho y concentrate en como hemos cumplido los requerimientos del cliente.
  • Escucha las preguntas del cliente atentamente. Si piden algo que sabes no existe o que no funciona, repitalo al cliente: "Le gustaría que haga...", apuntalo, y sigue con la presentación. Intenta no comprometer a añadirlo al producto, porqué es posible que piden algo que está afuera del alcanze del proyecto. En íngles, el fenómeno que resulta de este tipo de pedido es "Scope Creep" (que significa que el proyecto crece sin parar.)
  • Si es posible, arranque dos copías del producto. Si falla la primera durante la presentación, ponte en frente de la pantalla un momento y charla sobre algun aspecto del programa mientras cambias a la otra copia del programa. En el 90% de los casos, el cliente no se entererá del fallo. Apuntalo mentalmente que hay que arreglar esa parte, y evita mostrarlo otra vez. ¿Honesto? Bueno, no mucho. ¿Funciona? Casi siempre.

Consejos profesionales

Consejo: Concentrate en la solución

Es facil caer en el error de pasar todo el rato quejandote de que mal ha sido el analisis, o que no hay un estación de trabajo para ti, o otra mil razones porque no se puede cumplir el proyecto. Sí son problemas, pero hay soluciones también-- o habrán, una vez que las has hecho.

Consejo: Nunca criticad al sistema que estáis reemplazando

Esto he hecho. Estaba modernizando un sistema de MVS-- uno de los viejos, con pantalla verde y todo. El cliente me lo enseñó, y mi primera reacción era decir, "Puaaa, que feo. No me estraña que quieres reemplazarlo." Lo has adivinado: el mismo cliente habia escrito el programa.

Consejo: Ojo con el email, chatear, bajar MP3...

Casi no hace falta comentar en este consejo. La tentación de utilizar la conexión de Internet del trabajo para finales personales es fuerte. Como norma general, nunca visito Hotmail en el trabajo. He deinstalado el sistema de chat en mi máquina. Y nunca he bajado un MP3 (tengo convicciones personales sobre robar obras de artistas-- pero eso para otro clase.)

Compañías que tienen mucha gente chateando en el trabajo suelen fallar. Soy una persona bastante tranquila, pero si veo a alguíen en mi cargo chateando, y si no es con la línea de ayuda de IBM o parecido, la primera vez lo documento, la segunda, despido.

También tengo cuidado en tener una cuenta personal de email ajena del trabajo. Por buenas razones: un día, cuando estaba trabajando en Oracle, me llegó un email de un desconocido. Era un email personal (muy personal) que habia enviado a una amiga. Aparentamente, el escritor quería enviar una copía a su dirección personal, lo cual tenía el alias "home". Desafortunadamente, Oracle también tenía una lista de email llamado "home" para nosotros que trabajabamos desde casa. La lista tenía más de 500 direcciones. El chico habia enviado su email a 500 empleados de Oracle, quejándose, entre otras cosas, de que él estaba bebiendo mucho últimamente y pensaba que tal vez era alcohólico, que su jefe era imbecil, que las chicas no le hacian caso.... Basta con decir que nunca, nunca utilizo mi cuenta profesional para mensajes personales, es demasiado peligroso.

Consejo: Vistedos mejor que el cliente

Esto he aprendido aquí: en Estados Unidos, es común que el CEO de la compañía llega a la oficina en tejanos. Pero las aparencías cuentan por mucho aquí. Es importante entender que el cliente nos ve como un servicio-- nos ha comprado. La impresión más destacada en su mente debe ser una de competencía, eficaz, etc. Si llegas a la oficina del cliente vestido en una manera no llamativa, te das la oportunidad de destacar tus talentos antes de tu sentido de estilo. Aunque el cliente viene al trabajo muy informal, mejor no hacerlo tú.

Aunque tenemos un día informal el viernes, es importante recordaros que siempre puede salir un imprevisto. Te pueden llamar a la oficina del cliente sin avisar. No llevo traje el viernes, pero tampoco vengo vestido en tejanos.

Consejo: No liguéis en el trabajo

No comment. Peligroso al máximo. Especialmente no ligues con el cliente. Lo he hecho; confia en mi, no es muy recomendable.

Consejo: Utilizad más las orejas que la boca

Especialmente al principio de un proyecto, es vital que el cliente nos ve como receptivo a sus ideas. La mejor manera de conseguir esto es escucharlo sin comentar mucho, pedir clarificaciones si hace falta, y después repetir lo que acabas de oir al cliente. Es preciso no formular conclusiones basados en la mitad de la información.

Consejo: En cursos, aprendad, no enseñéis

Lo habeis visto. En cada curso, hay algún listillo que quiere demostrar que sabe más que nadie (incluso el instructor). Preguntas como, "¿Y no ves el protócolo IPv6 como una extensión pre-anticuada del actual?" son habituales en este tipo de estudiante. Tenemos que acordarnos que en los cursos, estamos para aprender. Después del curso, nadie recordará que Tim sí sabía mucho de Unix. En cursos en que he tomado ese papel (sí, lo he hecho), no aprendí practicamente nada.

Consejo: Conoce al portero...

...y la secretaria y la señora de la limpieza.... Perece poca cosa, pero especialmente si eres el único de la compañía en la oficina del cliente, resulta agradable (y útil) tener contactos no conectados con el proyecto. Adamás, no te gustaría que la gente te tratara como si fueras un mueble de la oficina. A ellos tampoco.

Cómo aprender un nuevo lenguaje de programación

Aprender escribir en un lenguaje de programación es como aprender escribir en un lenguaje hablado. Cada persona lo hace de una manera diferente. Aprender uno nuevo, especialmente si es uno de los primeros que has aprendido, puede resultar dificil. Pero vale la pena: "si sólo tienes un martillo, todos los problemas parecen clavos". Tener elección en cual lenguaje utilizar es bueno. A mi me han funcionado bien estos consejos:

Consejo: Consigue un buen libro

Nadie puede aprender programar leyendo un libro. Pero ayuda mucho tener una referencia al lado cuando empiezas. Normalmente cojo algo simple ("Aprender C++ en 21 Días") que tiene mucho ejercicios.

Consejo: Haz amigos con un experto

A veces un concepto de 20 páginas en un libro se puede explicar en 5 minutos con la persona adecuada.

Consejo: Lee el código de otros

Así puedes ver la manera en que se usa el lenguaje habitualmente. En estos días de fuente abierto, es fácil conseguir copías de el fuente de programas.

Consejo: Usa el nuevo lenguaje por todo

Esto te hace crecer en conocimientos rapidamente. Aunque sabes que el mismo programa te costaría tan sólo tres minutos en Visual Basic, aprenderás mucho más intentandolo en el nuevo lenguaje. Puede que no sea el lenguaje más indicado para el problema, pero no importa. La idea es aprender.

No comments:

Post a Comment

I moderate comments blog posts over 14 days old. This keeps a lot of spam away. I generally am all right about moderating. Thanks for understanding.