73
Dedicatoria A los programadores de Hire.com. Tabla de Contenido 1. Introducción 2. Principiante Habilidades Personales Aprende a Depurar Cómo Depurar Dividiendo el Espacio del Problema Cómo eliminar un Error Cómo Depurar Usando una Bitácora Cómo Comprender Problemas de Desempeño Cómo Corregir Problemas de Desempeño Cómo Optimizar Ciclos Cómo Lidiar con el Costo de E/S Cómo Administrar la Memoria Cómo Lidiar con Bugs Intermitentes Cómo Aprender Habilidades de Diseño Cómo Conducir Experimentos Habilidades de Equipo Por Qué la Estimación es Importante Cómo Estimar el Tiempo de Programación Cómo Encontrar Información Cómo Utilizar a la Gente como Fuentes de Información Cómo Documentar Sabiamente Cómo Trabajar con Código Pobre Cómo Usar el Control del Código Fuente Cómo Probar Unidades Toma Descansos Cuando estés Confundido Cómo Reconocer Cuándo Ir a Casa Cómo Lidiar con Gente Difícil 3. Intermedio Habilidades Personales Cómo Permanecer Motivado Cómo ser Ampliamente Confiable Cómo Negociar Tiempo vs. Espacio Cómo Hacer Pruebas de Estrés Cómo Balancear Brevedad y Abstracción Cómo Aprender Nuevas Habilidades Aprende a Teclear Cómo Hacer Pruebas de Integración Lenguajes de Comunicación Herramientas Pesadas Cómo Analizar Datos Habilidades de Equipo Cómo Administrar el Tiempo de Desarrollo

Como Ser Un Programador. Un Resumen Corto, Comprensivo y Personal

Embed Size (px)

DESCRIPTION

Un resumen corto, compresivo y personal sobre como formarse como programador

Citation preview

DedicatoriaA los programadores de Hire.com.

Tabla de Contenido

1. Introducción2. Principiante

Habilidades PersonalesAprende a DepurarCómo Depurar Dividiendo el Espacio del ProblemaCómo eliminar un ErrorCómo Depurar Usando una BitácoraCómo Comprender Problemas de DesempeñoCómo Corregir Problemas de DesempeñoCómo Optimizar CiclosCómo Lidiar con el Costo de E/SCómo Administrar la MemoriaCómo Lidiar con Bugs IntermitentesCómo Aprender Habilidades de DiseñoCómo Conducir ExperimentosHabilidades de EquipoPor Qué la Estimación es ImportanteCómo Estimar el Tiempo de ProgramaciónCómo Encontrar InformaciónCómo Utilizar a la Gente como Fuentes de InformaciónCómo Documentar SabiamenteCómo Trabajar con Código PobreCómo Usar el Control del Código FuenteCómo Probar UnidadesToma Descansos Cuando estés ConfundidoCómo Reconocer Cuándo Ir a CasaCómo Lidiar con Gente Difícil

3. IntermedioHabilidades PersonalesCómo Permanecer MotivadoCómo ser Ampliamente ConfiableCómo Negociar Tiempo vs. EspacioCómo Hacer Pruebas de EstrésCómo Balancear Brevedad y AbstracciónCómo Aprender Nuevas HabilidadesAprende a TeclearCómo Hacer Pruebas de IntegraciónLenguajes de ComunicaciónHerramientas PesadasCómo Analizar DatosHabilidades de EquipoCómo Administrar el Tiempo de DesarrolloCómo Manejar Riesgos de Software de Terceras PartesCómo Manejar ConsultoresCómo Comunicar la Cantidad AdecuadaCómo Disentir Honestamente y SobrellevarloJuicioCómo Negociar Calidad Frente a Tiempo de DesarrolloCómo Manejar la Dependencia del Sistema de SoftwareCómo Decidir si el Software es Muy Inmaduro

Cómo Hacer una Decisión de Compra vs. ConstrucciónCómo Crecer ProfesionalmenteCómo Evaluar EntrevistadosCómo Saber Cuándo Aplicar Ciencia Computacional FantasiosaCómo Hablar con No Ingenieros

4. AvanzadoJuicio TecnológicoCómo Diferenciar lo Difícil de lo ImposibleCómo Utilizar Lenguajes EmbebidosEscogiendo LenguajesComprometiéndote SabiamenteCómo Combatir Presión de CalendarioCómo Comprender al UsuarioCómo Obtener una PromociónSirviendo a Tu EquipoCómo Desarrollar TalentoCómo Elegir Sobre Qué TrabajarCómo Obtener lo Máximo de Tus Compañeros de EquipoCómo Dividir ProblemasCómo Manejar las Tareas AburridasCómo Conseguir Apoyo para un ProyectoCómo Hacer Crecer un SistemaCómo Comunicar BienCómo Decirle a la Gente Cosas que No Desean EscucharCómo Lidiar con Mitos AdministrativosCómo Lidiar con el Caos Organizacional

GlosarioA.B. Historia (Como la de Febrero, 2003)C. Licencia de Documentación Libre de la GNU

PREAMBULOAPLICABILIDAD Y DEFINICIONESCOPIAR AL PIE DE LA LETRACOPIAR EN CANTIDADMODIFICACIONESCOMBINANDO DOCUMENTOSCOLECCIONES DE DOCUMENTOSAGREGACION CON TRABAJOS INDEPENDIENTESTRADUCCIONTERMINACIONFUTURAS REVISIONES DE ESTA LICENCIAADENDUM: cómo usar esta Licencia para tus documentos

Capítulo 1. Introducción

Ser un buen programador es difícil y noble. La parte más difícil de hacer real una visión colectiva de un proyecto de software es lidiar con los compañeros de trabajo y con los clientes de uno. Escribir programas de computadora es importante y requiere gran inteligencia y habilidad. Pero realmente es un juego de niños comparado con todo lo demás que un buen programador debe hacer para lograr que un sistema de software tenga éxito tanto para el cliente como para la miríada de colegas por quienes se es parcialmente responsable. En este ensayo intento resumir tan concisamente como sea posible esas cosas que desearía que alguien me hubiese explicado a mí cuando tenía veintiuno.

Esto es muy subjetivo y, por lo tanto, este ensayo está condenado a ser personal y algo testarudo. Me confino a mí mismo a los problemas que un programador muy probablemente tiene que enfrentar en su trabajo. Muchos de esos problemas y sus soluciones son tan generales a la condición humana que probablemente pareceré predicativo. A pesar de ello tengo fe de que este ensayo será útil.

La programación de computadoras es enseñada en cursos. Los excelentes libros: El Programador Pragmático (The Pragmatic Programmer) [Prag99], Código Completo (Code Complete) [CodeC93],Desarrollo Rápido (Rapid Development) [RDev96], y La Programación Extrema Explicada (Extreme Programming Explained) [XP99] todos enseñan la programación de computadoras y los aspectos más grandes de ser un buen programador. Los ensayos de Paul Graham [PGSite] y Eric Raymond [Hacker] ciertamente deberían ser leídos antes o junto con este artículo. Este ensayo difiere de esos excelentes trabajos al enfatizar los problemas sociales y resumir comprensivamente el conjunto completo de habilidades necesarias a como yo las percibo.

En este ensayo el término jefe se refiere a quien sea que te da proyectos para hacer. Uso las palabrasnegocio, compañía, y tribu, sinónimamente excepto que negocio implica hacer dinero, compañía implica el lugar moderno de trabajo y tribu es generalmente la gente con la que compartes lealtad.

Bienvenido a la tribu.

Capítulo 2. Principiante

Tabla de Contenido

Habilidades PersonalesAprende a DepurarCómo Depurar Dividiendo el Espacio del ProblemaCómo eliminar un ErrorCómo Depurar Usando una BitácoraCómo Comprender Problemas de DesempeñoCómo Corregir Problemas de DesempeñoCómo Optimizar CiclosCómo Lidiar con el Costo de la E/SCómo Administrar la MemoriaCómo Lidiar con Bugs IntermitentesCómo Aprender Habilidades de DiseñoCómo Conducir Experimentos

Habilidades de EquipoPor Qué la Estimación es ImportanteCómo Estimar el Tiempo de ProgramaciónCómo Encontrar InformaciónCómo Utilizar a la Gente como Fuentes de InformaciónCómo Documentar SabiamenteCómo Trabajar con Código PobreCómo Usar el Control del Código FuenteCómo Probar UnidadesToma Descansos Cuando estés ConfundidoCómo Reconocer Cuándo Ir a CasaCómo Lidiar con Gente Difícil

Habilidades Personales

Aprende a Depurar

La depuración es la piedra angular de ser un programador. El primer significado del verbo depurar es eliminar errores, pero el significado que realmente interesa es ver a lo interno de la ejecución de un programa mediante su examen. Un programador que no puede depurar efectivamente está ciego.

Los idealistas que piensan que el diseño, el análisis, o la teoría de la complejidad, o lo que no es, son más fundamentales no son programadores activos. El programador activo no vive en un mundo ideal. Incluso si eres perfecto, estás rodeado por y debes interactuar con código escrito por grandes compañías de software, organizaciones como GNU, y tus colegas. La mayoría de este código es imperfecto e imperfectamente documentado. Sin la capacidad de ganar visibilidad dentro de la ejecución de este código el más ligero golpe te tirará permanentemente. A menudo esta visibilidad puede ganarse solamente mediante la experimentación, es decir, la depuración.

La depuración trata de la ejecución de programas, no de los programas mismos. Si compras algo de una compañía de software grande, usualmente no consigues ver el programa. Pero inclusive ahí aparecerán lugares donde el código no se ajuste a la documentación (el aterrizaje de toda tu máquina es un ejemplo común y espectacular), o donde la documentación es muda. Por lo general, creas un error, examinas el código que escribiste y no tienes una pista de cómo puede estar ocurriendo el error. Inevitablemente, esto significa que alguna suposición que estás haciendo no es muy correcta, o que surge alguna condición que no anticipaste. Algunas veces el truco mágico de ver detenidamente el código fuente funciona. Cuando no, debes depurar.

Para conseguir visibilidad dentro de la ejecución de un programa debes ser capaz de ejecutar el código y observar algo acerca de él. Algunas veces esto es visible, como lo que se muestra en una pantalla, o el retardo entre dos eventos. En muchos otros casos, involucra cosas que no necesariamente deban estar visibles, como el estado de algunas variables dentro del código, cuáles líneas de código están siendo actualmente ejecutadas, o si ciertas afirmaciones se mantienen a través de una estructura de datos complicada. Esas cosas ocultas deben ser reveladas.

Las formas comunes de ver dentro de las 'entrañas' de un programa en ejecución pueden ser categorizadas como:

Usar una herramienta de depuración, Printlining --- Hacer una modificación temporal al programa, típicamente

adicionando líneas que impriman información, y Logging --- Crear una ventana permanente en la ejecución de los programas en

la forma de una bitácora.

Las herramientas de depuración son maravillosas cuando son estables y están disponibles, pero el printlining y el logging son aún más importantes. Las herramientas de depuración a menudo se retrasan detrás del lenguaje de desarrollo, de tal manera que en cualquier punto del tiempo pueden no estar disponibles. Además, debido a que la herramienta de depuración puede cambiar sutilmente la forma en que se ejecuta el programa puede no ser siempre práctica. Finalmente, hay algunos tipos de depuración, tal como el chequeo de una afirmación frente a una gran estructura de datos, que requiere escribir código y cambiar la ejecución del programa. Es bueno saber cómo

usar las herramientas de depuración cuando son estables, pero es crítico ser capaz de emplear los otros dos métodos.

Algunos principiantes temen depurar cuando ello requiere modificar código. Esto es comprensible---es un poquito similar a la cirugía exploratoria. Pero tú tienes que aprender a hurgar en el código y hacerlo saltar; tienes que aprender a experimentar en él, y comprender que nada que le hagas temporalmente lo empeorará. Si sientes este temor, busca un mentor---perdemos un montón de buenos programadores en la delicada iniciación de su aprendizaje debido a este temor.

Cómo Depurar Dividiendo el Espacio del Problema

La depuración es divertida, debido a que empieza con un misterio. Tú piensas que debería hacer algo, pero en lugar de ello hace algo más. No siempre es tan simple---cualesquiera ejemplos que yo pueda dar serán forzados o artificiales comparado a lo que algunas veces sucede en la práctica. La depuración requiere creatividad e ingenuidad. Si hay una clave sencilla para depurar es usar en el misterio la técnica divide y vencerás.

Supón, por ejemplo, que creaste un programa que debería hacer diez cosas en secuencia. Cuando lo ejecutas, aterriza. Puesto que no lo programaste para que aterrizara, ahora tienes un misterio. Cuando observas la salida, vez que las primeras siete cosas en la secuencia fueron ejecutadas exitosamente. Las últimas tres no son visibles en la salida, así que ahora tu misterio es más pequeño: 'Aterrizó en la cosa #8, #9, o #10.'

¿Puedes diseñar un experimento para ver en cuál cosa aterrizó? Seguro. Puedes usar un depurador o podemos agregar sentencias de impresión (o el equivalente en el lenguaje que sea en el que estés trabajando) después de la #8 y #9. Cuando lo ejecutamos de nuevo, nuestro misterio será más pequeño, puesto que 'Aterrizó en la cosa #9.' Encuentro que mantener en mente exactamente cuál es el misterio en cualquier punto del tiempo ayuda a mantenerse enfocado. Cuando varias personas están trabajando juntas bajo presión en un problema es fácil olvidar cuál es el misterio más importante.

La clave para dividir y vencer como una técnica de depuración es la misma que para el diseño de algoritmos: mientras hagas un buen trabajo dividiendo el misterio a la mitad, no tendrás que dividirlo demasiadas veces, y estarás depurando rápidamente. Pero ¿cuál es la mitad de un misterio? Ahí es donde entra la verdadera creatividad y la experiencia.

Para un verdadero principiante, el espacio de todos los posibles errores luce como cada línea del código fuente. No tienes la visión que más tarde desarrollarás para ver las otras dimensiones del programa, tales como el espacio de líneas ejecutadas, las estructuras de datos, el manejo de la memoria, la interacción con código foráneo, el código que es riesgoso, y el código que es simple. Para el programador experimentado, esas otras dimensiones forman un imperfecto pero muy útil modelo mental de todas las cosas que pueden ir mal. Tener ese modelo mental es lo que le ayuda a uno a encontrar la mitad del misterio efectivamente.

Una vez que has subdividido eventualmente el espacio de todo lo que puede ir mal, debes intentar decidir en cuál espacio yace el error. En el caso simple dónde está el misterio: '¿Cuál única línea desconocida hace aterrizar a mi programa?', puedes preguntarte a ti mismo: '¿Se ejecuta la línea desconocida antes o después de esa línea

que juzgo debe ser ejecutada cerca de la mitad del programa en ejecución?' Usualmente no serás tan afortunado como para saber que el error existe en una única línea, o aún en un único bloque. A menudo el misterio será más o menos como: 'O hay un puntero en ese gráfico que apunta al nodo equivocado, o mi algoritmo que agrega las variables en ese gráfico no funciona.' En ese caso puede que tengas que escribir un pequeño programa para chequear que los punteros en el gráfico son todos correctos a fin de decidir cuál parte del misterio subdividido puede ser eliminada.

Cómo eliminar un Error

He separado intencionalmente el acto de examinar la ejecución de un programa del acto de corregir un error. Pero por supuesto, depurar también significa eliminar el bug. Idealmente tendrás perfecta comprensión del código y alcanzarás un momento '¡Ajá!' donde perfectamente verás el error y cómo corregirlo. Pero debido a que tu programa a menudo usará sistemas insuficientemente documentados en los cuales no tienes visibilidad, esto no siempre es posible. En otros casos el código es tan complicado que tu comprensión no puede ser perfecta.

Al corregir un bug, deseas hacer el más pequeño cambio que corrija el bug. Puedes ver otras cosas que necesitan mejoría; pero no las corrijas al mismo tiempo. Intenta emplear el método científico de cambiar una y solamente una cosa a la vez. El mejor proceso para esto es ser capaz de reproducir fácilmente el bug, luego poner tu corrección en su lugar, y después reejecutar el programa y observar que el bug no existe más. Por supuesto, algunas veces debe ser cambiada más de una línea, pero aún deberías aplicar conceptualmente un único cambio atómico para corregir el bug.

A veces, hay en realidad varios bugs que se ven como uno. Es tu trabajo definirlos y corregirlos uno a la vez. Algunas veces no es claro qué debería hacer el programa o qué intentó el autor original. En ese caso, debes ejercitar tu experiencia y tu juicio y asignar tu propio significado al código. Decide qué debería hacer, y coméntalo o clarifícalo de alguna forma y luego haz que el código concuerde con tu significado. Esta es una habilidad intermedia o avanzada que es a veces más difícil de adquirir que el escribir la función original en primera instancia, pero el mundo real a menudo es desordenado. Puede que tengas que corregir un sistema que no puedes reescribir.

Cómo Depurar Usando una Bitácora

El logging es la práctica de escribir un sistema de tal manera que produzca una secuencia de registros informativos, llamado bitácora (log). El printlining consiste en producir tan solo una bitácora simple, usualmente temporal. Los verdaderos principiantes deben entender y usar bitácoras porque su conocimiento de la programación es limitado; los arquitectos de sistemas deben comprender y usar bitácoras debido a la complejidad del sistema. La cantidad de información que provea la bitácora debería ser configurable, idealmente mientras el programa está en ejecución. En general, las bitácoras ofrecen tres ventajas básicas:

Las bitácoras pueden proveer información útil sobre bugs que son difíciles de reproducir (tales como los que ocurren en el ambiente de producción pero que no pueden ser reproducidos en el ambiente de prueba).

Las bitácoras pueden proveer estadísticas y datos relevantes para el desempeño, tales como el tiempo que pasa entre sentencias.

Cuando son configurables, las bitácoras permiten que se capture información general a fin de depurar problemas específicos no anticipados sin tener que

modificar y/o reimplementar el código lo suficiente como para lidiar con esos problemas específicos.

La cantidad de salida a poner en la bitácora es siempre un compromiso entre información y brevedad. Demasiada información hace la bitácora costosa y produce ceguera de desplazamiento, haciendo difícil el encontrar la información que necesitas. Muy poca información y puede que no contenga lo que necesitas. Por esta razón, hacer configurable lo que es salida para la bitácora es muy útil. Típicamente, cada registro en la bitácora identificará su posición en el código fuente, el hilo que lo ejecutó si es aplicable, la hora precisa de ejecución, y, comúnmente, una pieza útil de información adicional, tal como el valor de alguna variable, la cantidad de memoria libre, el número de objetos de datos, etc. Esas sentencias de la bitácora están diseminadas a través del código fuente pero particularmente en los puntos de las funcionalidades más grandes y alrededor del código riesgoso. A cada sentencia se le puede asignar un nivel y solamente generará un registro si el sistema está actualmente configurado para generar salida de ese nivel. Deberías diseñar las sentencias bitácora para manejar problemas que anticipes. Anticipa la necesidad de medir el desempeño.

Si tienes una bitácora permanente, el printlining puede hacerse ahora en términos de los registros de la bitácora, y algunas de las sentencias de depuración probablemente serán añadidas permanentemente al sistema de registro de la bitácora.

Cómo Comprender Problemas de Desempeño

Aprender a comprender el desempeño de un sistema en ejecución es inevitable por la misma razón que tiene el aprender a depurar. Incluso si el código que comprendes perfectamente es justamente el costo del código que escribes, tu código hará llamadas a lo interno de otros sistemas de software sobre los que tienes poco control o visibilidad. Sin embargo, en la práctica los problemas de desempeño son un poco diferentes y un poco más fáciles que la depuración en general.

Supón que tú o tus clientes consideran que un sistema o un subsistema es muy lento. Antes de que intentes hacerlo más rápido, debes construir un modelo mental de por qué es lento. Para hacer esto puedes usar una herramienta de perfilación o una buena bitácora para determinar realmente dónde están siendo gastados el tiempo y los otros recursos. Hay un famoso dicho de que el 90% del tiempo será gastado en 10% del código. Yo añadiría a eso la importancia de los costos de entrada/salida (E/S) a los tópicos de desempeño. A menudo la mayor parte del tiempo se gasta en E/S de una forma u otra. Encontrar la E/S costosa y el costoso 10% del código es un buen primer paso para construir tu modelo mental.

Hay muchas dimensiones relacionadas al desempeño de un sistema computacional, y muchos recursos consumidos. El primer recurso a medir es el tiempo del reloj de pared, el tiempo total que pasa para la computación. Registrar en la bitácora el tiempo del reloj de pared es particularmente valioso debido a que él puede informar acerca de circunstancias impredecibles que surgen en situaciones donde otra forma de perfilación es impráctica. Sin embargo, esto podría no siempre representar toda la escena. Algunas veces algo que toma un poco más de tiempo pero que no quema tantos segundos del procesador será mucho mejor con lo que tienes que lidiar realmente en el ambiente computacional. Similarmente, la memoria, el ancho de banda de la red, la base de datos u otros accesos a servidores pueden, al final, ser mucho más costosos que los segundos del procesador.

La contención de recursos compartidos que están sincronizados puede causar estancamiento e inanición. El estancamiento es la incapacidad para proceder debido a la inapropiada sincronización o demanda de recursos. La inanición es la falla al calendarizar apropiadamente un componente. Si puede ser del todo anticipado, es mejor tener una forma de medir esta contención desde el inicio de tu proyecto. Aún si esta contención no ocurre, es muy útil ser capaz de afirmar eso con confianza.

Cómo Corregir Problemas de Desempeño

La mayoría de los proyectos de software pueden hacerse con relativamente poco esfuerzo de 10 a 100 veces más rápido de lo que son la primera vez que son liberados. Bajo la presión del tiempo de mercadeo, es tan sabio como efectivo elegir una solución que obtenga el trabajo hecho simple y rápidamente, pero menos eficiente que alguna otra solución. Sin embargo, el desempeño es una parte de la usabilidad, y a menudo debe eventualmente ser considerado más cuidadosamente.

La clave para mejorar el desempeño de un sistema muy complicado es analizarlo lo suficientemente bien para encontrar los cuellos de botella, o lugares donde se consumen la mayoría de los recursos. No tiene mucho sentido optimizar una función que cuenta solamente para el 1% del tiempo de cómputo. Como una regla de ganadores deberías pensar cuidadosamente antes de hacer algo a menos que pienses que va a hacer al sistema o a una parte significativa de él al menos dos veces más rápida. Usualmente hay una forma de hacer esto. Considera los tests y los esfuerzos de aseguramiento de la calidad que tu cambio requerirá. Cada cambio trae una prueba aparejada con él, de tal manera que es mucho mejor tener unos cuantos grandes cambios.

Después de que has hecho una mejora de dos pliegues en algo, necesitas al menos repensar y quizá reanalizar para descubrir el siguiente cuello de botella más costoso en el sistema, y atacar eso para obtener otra mejora de dos pliegues.

A menudo, los cuellos de botella en el desempeño serán un ejemplo de contar vacas mediante el conteo de piernas y dividiendo entre cuatro, en lugar de contar cabezas. Por ejemplo, he cometido errores tales como fallar al proveer un sistema de base de datos relacional con un índice apropiado sobre una columna que observé mucho, lo cual probablemente la hizo al menos 20 veces más lenta. Otros ejemplos incluyen hacer E/S innecesaria en ciclos internos, dejar sentencias de depuración que no se necesitaban más, asignación de memoria innecesaria, y, en particular, uso inexperto de bibliotecas y otros subsistemas que a menudo están pobremente documentados con respecto al desempeño. Este tipo de mejora es a veces llamada fruta de cuelgue bajo, que significa que puede ser fácilmente elegida para proveer algún beneficio.

¿Qué haces cuando empiezas a quedarte sin frutas de cuelgue bajo? Bien, puedes alcanzar las más altas, o derribar el árbol. Puedes continuar haciendo pequeñas mejoras o puedes rediseñar seriamente un sistema o un subsistema. (Esta es una gran oportunidad para usar tus habilidades de buen programador, no solamente en el nuevo diseño sino también en convencer a tu jefe que esta es una buena idea.) Sin embargo, antes de que argumentes por el rediseño de un subsistema, deberías preguntarte a ti mismo si tu propuesta lo hará o no de cinco a diez veces mejor.

Cómo Optimizar Ciclos

A veces encontrarás ciclos, o funciones recursivas, que toman un largo tiempo para ejecutarse y son cuellos de botella en tu producto. Antes de que intentes hacer el ciclo

un poco más rápido, invierte unos pocos minutos en considerar si hay forma de eliminarlo completamente. ¿Funcionaría un algoritmo diferente? ¿Podrías computar eso mientras computas algo más? Si no puedes hallar una manera de mejorarlo, entonces puedes optimizar el ciclo. Esto es simple: mueve material fuera. Al final, esto requerirá no solamente ingenuidad sino también una comprensión del costo de cada tipo de sentencia y expresión. He aquí algunas sugerencias:

elimina operaciones de punto flotante. No asignes nuevos bloques de memoria innecesariamente. Pliega constantes juntas. Mueve E/S a un búfer. Trata de no dividir. Trata de no hacer costosas conversiones de tipo. Mueve un puntero en lugar de recomputar índices.

El costo de casa una de esas operaciones depende de tu sistema específico. En algunos sistemas los compiladores y el hardware hacen esas cosas por ti. El código claro y eficiente es mejor que el código que requiere la comprensión de una plataforma particular.

Cómo Lidiar con el Costo de E/S

Para un montón de problemas, los procesadores son rápidos comparados al costo de comunicarse con un dispositivo de hardware. Este costo es usualmente abreviado E/S, y puede incluir costo de red, E/S de disco, consultas de bases de datos, E/S de archivo, y otro uso del algún hardware no muy cercano al procesador. Por lo tanto construir un sistema rápido es a menudo más una cuestión de mejorar la E/S que mejorar el código en algún ciclo ajustado, e incluso mejorar un algoritmo.

Hay dos técnicas muy fundamentales para mejorar la E/S: el cacheo y la representación. El cacheo es evitar la E/S (generalmente evitando la lectura de algún valor abstracto) mediante el almacenamiento local de una copia de ese valor de manera que no se ejecuta ninguna E/S para obtener el valor. La primer clave para el cacheo es hacer claro como el cristal cuál dato es el maestro y cuáles son lascopias. Hay solamente un maestro--- punto. El cacheo trae consigo el peligro de que la copia algunas veces no pueda reflejar los cambios instantáneamente al maestro.

La representación es el método de hacer la E/S más barata representando los datos más eficientemente. Esto está a menudo en tensión con otras demandas, como la legibilidad humana y la portabilidad.

Las representaciones pueden a menudo ser mejoradas por un factor de dos o tres de su primera implementación. Las técnicas para hacer esto incluyen usar una representación binaria en lugar de una que sea legible para los humanos, transmitir un diccionario de símbolos junto con los datos de tal manera que a la larga los símbolos no tengan que ser codificados, y, en el extremo, cosas como la codificación Huffman.

Una tercer técnica que es a veces posible es mejorar la localidad de referencia empujando la computación más cerca de los datos. Por ejemplo, si estás leyendo algunos datos de una base de datos y computando algo simple de ella, tal como una sumatoria, trata de hacer que el servidor de la base de datos lo haga por ti. Esto es altamente dependiente del tipo de sistema con el que estés trabajando, pero deberías explorarlo.

Cómo Administrar la Memoria

La memoria es un recurso precioso del que no puedes darte el lujo de adolecer. Puedes ignorarla por un momento pero eventualmente tendrás que decidir cómo administrarla.

El espacio que necesita para persistir más allá del alcance de una sencilla subrutina es a menudo llamado heap asignado. Un trozo de memoria es inútil, y por lo tanto basura, cuando nada lo referencia. Dependiendo del sistema que uses, puede que tengas que desasignar explícitamente la memoria tu mismo cuando está a punto de convertirse en basura. Muy a menudo puedes ser capaz de usar un sistema que proporcione un recolector de basura. Un recolector de basura nota la basura y libera su espacio sin ninguna acción requerida por el programador. La recolección de basura es maravillosa: reduce los errores e incrementa la brevedad del código y la concisión de forma barata. Úsala cuando puedas.

Pero aún con la recolección de basura, puedes llenar toda la memoria con basura. Un error clásico es usar una tabla hash como un caché y olvidar eliminar las referencias en dicha tabla. Puesto que las referencias se mantienen, el referente es no recolectable sino inútil. Esto es llamado una fuga de memoria. Debes observar y corregir temprano las fugas de memoria. Si tienes tiempo de estar corriendo sistemas puede que la memoria nunca se agote durante las pruebas pero será agotada por el usuario.

La creación de nuevos objetos es moderadamente costosa en cualquier sistema. La memoria asignada directamente en las variables locales de una subrutina, sin embargo, es usualmente barata debido a que la política para liberarla puede ser muy simple. Deberías evitar la creación innecesaria de objetos.

Un caso importante ocurre cuando puedes definir un límite superior en el número de objetos que necesitarás a la vez. Si todos esos objetos toman la misma cantidad de memoria, puedes ser capaz de asignar un único bloque de memoria, o un búfer, para contenerlas todas. Los objetos que necesitas pueden ser ubicados y liberados dentro de este búfer en un patrón de rotación fijo, por lo cual esto es llamado a veces un búfer circular. Esto es usualmente más rápido que la asignación heap.

Algunas veces tienes que liberar explícitamente el espacio asignado de tal forma que pueda ser reasignado en lugar de confiar en la recolección de basura. Luego debes aplicar cuidadosamente la inteligencia para cada trozo de memoria asignada y diseñar un método para que sea desasignada en el momento apropiado. El método puede diferir para cada tipo de objeto que crees. Debes asegurarte que cada ejecución de una operación de asignación de memoria coincida eventualmente con una desasignación de memoria. Esto es tan difícil que los programadores a menudo implementan simplemente una forma rudimentaria de recolección de basura, tal como un conteo de referencia, para hacer esto por ellos.

Cómo Lidiar con Bugs Intermitentes

El bug intermitente es primo del escorpión espacial invisible de 50 pies. Esta pesadilla ocurre tan raras veces que es difícil de observar, pero lo suficientemente a menudo como para que no pueda ser ignorado. No puedes depurarlo porque no puedes encontrarlo.

Aunque después de 8 horas empezarás a dudarlo, el bug intermitente tiene que obedecer a las mismas leyes de la lógica que todo lo demás. Lo que lo hace difícil es que ocurre solamente bajo condiciones desconocidas. Trata de registrar las

circunstancias bajo las cuales ocurre el bug, de tal manera que puedas adivinar realmente en qué yace la variabilidad. La condición puede estar relacionada a los valores de los datos, tales como 'Esto sólo sucede cuando introducimos Wyoming como valor.' Si eso no es la fuente de la variabilidad, la próxima sospecha debería ser la concurrencia inapropiadamente sincronizada.

Trata, trata, trata de reproducir el bug de una forma controlada. Si no puedes reproducirlo, configura una trampa para él mediante la construcción de un sistema de registro de sucesos (logging), una especial si tienes que hacerlo, que pueda registrar lo que supones que necesitas cuando realmente ocurre. Resígnate a ti mismo a que si el bug solamente ocurre en producción y no a tu antojo, este sea quizá un largo proceso. Las pistas que obtengas de la bitácora puede que no proporcionen la solución pero pueden darte suficiente información para mejorar el registro de sucesos. El sistema mejorado de registro de sucesos puede requerir un largo tiempo para estar en producción. Luego, tienes que esperar a que reaparezca el bug para obtener más información. Este círculo puede seguir por algún tiempo.

El bug intermitente más estúpido que he creado fue en una implementación multi-hilo de un lenguaje de programación funcional para un proyecto de clase. Me había asegurado cuidadosamente de la correcta evaluación concurrente del programa funcional y la buena utilización de todas las CPUs disponibles (ocho, en este caso). Simplemente olvidé sincronizar el recolector de basura. El sistema podría correr un largo tiempo, a menudo finalizando cualquier tarea que comenzara, antes de que algo notable fuese mal. Estoy avergonzado al admitir que había comenzado a cuestionar al hardware antes de que mi error me pusiera en evidencia.

En el trabajo recientemente teníamos un bug intermitente que nos tomó varias semanas encontrar. Tenemos servidores de aplicación multi-hilados en Java™ detrás de servidores web Apache™. Para mantener cambios de página rápidos, hacemos toda la E/S en pequeños conjuntos de cuatro hilos separados que son diferentes de los hilos cambia páginas. Aparentemente cada cierto tiempo esos hilos se 'clavaban' y cesaban de hacer cualquier cosa útil, hasta que nuestro registro de sucesos nos permitió determinarlo, por horas. Puesto que teníamos cuatro hilos, esto no era en sí mismo un problema gigante---a menos que los cuatro se clavaran. Luego esas colas vaciadas por esos hilos rápidamente llenarían toda la memoria disponible y hacían aterrizar nuestro servidor. Nos tomó cerca de una semana entender esto, y aún no sabíamos qué lo causaba, cuándo sucedía, e incluso qué estaban haciendo los hilos cuando se 'clavaban'.

Esto ilustra algunos riesgos asociados con software de terceros. Estábamos usando una pieza de código licenciada que eliminó las etiquetas HTML del texto. Debido a su lugar de origen nos referíamos a él entrañablemente como 'el stripper francés.' Aunque teníamos el código fuente (¡bondadosa gracia!) no lo habíamos estudiado cuidadosamente hasta cuando activamos el registro de sucesos en nuestros servidores que finalmente nos dimos cuenta que los hilos del email estaban clavando en el stripper francés.

El stripper se desempeñaba bien excepto en algunos largos e inusuales tipos de textos. En esos textos, el código era cuadrático o peor. Esto significa que el tiempo de procesamiento era proporcional al cuadrado de la longitud del texto. Si esos textos hubieran ocurrido comúnmente, hubiésemos encontrado el bug de inmediato. Si no hubieran ocurrido del todo, nunca hubiésemos tenido un problema. Como suele suceder, nos tomó semanas para finalmente comprender y resolver el problema.

Cómo Aprender Habilidades de Diseño

Para aprender cómo diseñar software, estudia la acción de un mentor estando físicamente presente cuando él está diseñando. Luego estudia piezas de software bien escritas. Después de eso, puedes leer algunos libros sobre las últimas técnicas de diseño.

Luego debes hacerlo tú mismo. Empieza con un proyecto pequeño. Cuando finalmente hayas terminado, considera cómo falló o cómo tuvo éxito el diseño y cómo divergiste de tu concepción original. Luego muévete hacia proyectos más grandes, preferentemente en conjunto con otras personas. El diseño es una cuestión de juicio que toma años adquirir. Un programador inteligente puede aprender los fundamentos adecuadamente en dos meses y puede mejorar a partir de ahí.

Es natural y útil desarrollar tu propio estilo, pero recuerda que el diseño es un arte, no una ciencia. La gente que escribe libros sobre el tema tiene un marcado interés en hacerlo parecer científico. No te vuelvas dogmático acerca de estilos de diseño particulares.

Cómo Conducir Experimentos

El gran Edsger Dijkstra ha explicado elocuentemente que la Ciencia de la Computación no es una ciencia experimental [ExpCS] y no depende de computadoras electrónicas. Como él lo señaló refiriéndose a los 1960s [Knife],

...el daño estaba hecho: el tópico se volvió conocido como “la ciencia de la computadora”---lo cual, de hecho, es como referirse a la cirugía como “la ciencia del cuchillo” --- y fue firmemente implantado en las mentes de las personas que la ciencia de la computación es acerca de máquinas y sus equipos periféricos.

La programación no debe ser una ciencia experimental, pero la mayoría de los programadores activos no tienen el lujo de encajar en lo que Dijkstra quiso dar a entender por ciencia de la computación. Debemos trabajar en el campo de la experimentación, igual que algunos, pero no todos, los físicos. Si dentro de treinta años la programación puede ser realizada sin experimentación, será un gran logro para la Ciencia de la Computación.

Los tipos de experimentos que tendrás que realizar incluyen:

Probar sistemas con pequeños ejemplos para verificar que se ajustan a la documentación o para comprender sus respuestas cuando no hay documentación,

Probar pequeños cambios en el código para ver si realmente corrigen un bug, Medir el desempeño de un sistema bajo dos diferentes condiciones debido al

conocimiento imperfecto de sus características de desempeño, Chequear la integridad de los datos, y Recolectar estadísticas que podrían dar pistas para la solución de bugs

dificultosos o difíciles de repetir.

No creo que en este ensayo pueda explicar el diseño de experimentos; tendrás que estudiar y practicar. Sin embargo, puedo ofrecerte dos pequeños consejos.

Primero, trata de ser muy claro acerca de tu hipótesis, o la afirmación que estás tratando de probar. También ayuda el escribir la hipótesis, especialmente si te encuentras a ti mismo confundido o estás trabajando con otros.

A menudo te encontrarás a ti mismo teniendo que diseñar una serie de experimentos, cada uno de los cuales está basado en el conocimiento ganado a partir del último. Por lo tanto, deberías diseñar tus experimentos para que proporcionen la mayor información posible. Desafortunadamente, esto está en conflicto con el mantener cada experimento simple---tendrás que desarrollar este juicio a través de la experiencia.

Habilidades de Equipo

Por Qué la Estimación es Importante

Tener un sistema de software funcional en uso activo tan rápidamente como sea posible no solamente requiere planear el desarrollo, sino también planear la documentación, la implementación y el mercadeo. En un proyecto comercial ello también requiere ventas y finanzas. Sin la previsibilidad del tiempo de desarrollo, es imposible planear esas cosas efectivamente.

La buena estimación proporciona previsibilidad. Los administradores la aman, tan bien como deberían. El hecho de que es imposible, tanto teórica como prácticamente, el predecir exactamente cuánto tiempo tomará desarrollar software está a menudo perdido en los administradores. Se nos pide hacer este imposible todo el tiempo, y debemos encararlo honestamente. Sin embargo, sería deshonesto no admitir la imposibilidad de esta tarea, y cuando sea necesario, explicarla. Hay mucho espacio para los problemas de comunicación sobre los estimados, puesto que la gente tiene una sorprendente tendencia a pensar deseosamente que la oración:

Estimo que, si comprendo realmente el problema, hay 50% de probabilidades de que estará listo en cinco semanas (si nadie nos molesta durante ese tiempo).

realmente significa:

Prometo tenerlo hecho en cinco semanas.

Este común problema de interpretación requiere que explícitamente discutas qué significa el estimado con tu jefe o cliente como si ellos fueran unos simplones. Replantea tu suposiciones, no importa cuán obvias te parezcan.

Cómo Estimar el Tiempo de Programación

La estimación toma práctica. También conlleva trabajo. Requiere tanto trabajo que puede ser una buena idea estimar el tiempo que tomará hacer el estimado, especialmente si se te pide estimar algo grande.

Cuando se nos pide proporcionar un estimado de algo grande, la cosa más honesta por hacer es detenerte. La mayoría de los ingenieros son entusiastas y propensos a agradar, y el que detengas ciertamente desagradará al detenido. Pero un estimado al vuelo probablemente no será preciso ni honesto.

Mientras estás en standby, puede que sea posible considerar el hacer un prototipo de la tarea. Si la presión política lo permite, esta es la forma más exacta de producir el estimado, y constituye un progreso real.

Cuando no es posible tomarse tiempo para alguna investigación, deberías establecer primero el significado del estimado muy claramente. Replantea ese significado como la primera y última parte de tu estimado escrito. Prepara un estimado escrito descomponiendo la tarea en subtareas progresivamente más pequeñas hasta que cada una de esas pequeñas tareas no exceda más que un día; idealmente a la mayoría en duración. Lo más importante es no dejar nada fuera. Por ejemplo, la documentación, la prueba, el tiempo para la planeación, el tiempo para comunicarse con otros grupos, y las fechas de vacaciones son también todas muy importantes. Si pasas una parte de cada día lidiando con cabezaduras, incluye un ítem para eso en el estimado. Ello le da a tu jefe la visibilidad de en qué está usándose tu tiempo hasta el mínimo, y podría procurarte más tiempo.

Conozco buenos ingenieros que rellenan estimados implícitamente, pero te recomiendo que no lo hagas. Uno de los resultados de rellenar es confiar en que pueden reducirte. Por ejemplo, un ingeniero podría estimar tres días para una tarea que realmente piensa que tomará un día. El ingeniero puede planear el pasar dos días documentándolo, o dos días trabajando en algún otro proyecto útil. Pero será visible que la tarea fue hecha en solamente un día (si resulta ser así), y nacerá la apariencia de flojera o sobreestimación del tiempo. Es mucho mejor brindar una apropiada visibilidad de lo que realmente estás haciendo. Si la documentación toma dos veces más tiempo que la codificación y el estimado así lo dice, se gana una tremenda ventaja al hacer esto visible al administrador.

En su lugar rellena explícitamente. Si una tarea probablemente tomará un día---pero podría tomar diez si tu método no funciona---has notar esto de algún modo en el estimado si puedes; si no, al menos haz un promedio ponderado por tus estimados de las probabilidades. Cualquier factor de riesgo que puedas identificar y asignarle un estimado debería ir en el calendario. Es poco probable que una persona pueda estar enferma en alguna semana dada. Pero un proyecto grande con muchos ingenieros tendrá algún tiempo de enfermedad; al igual que tiempo para vacaciones. ¿Y qué hay de la probabilidad de un seminario de entrenamiento obligatorio para toda la compañía? Si puede ser estimado, inclúyelo. Existen por supuesto, desconocidos desconocidos, o unk-unks (del inglés unknown-unknowns). Los unk-unks por definición no pueden ser estimados individualmente. Puedes intentar crear un ítem global para todos los unk-unks, o manejarlos de alguna otra forma para que puedas comunicárselo a tu jefe. No puedes, sin embargo, permitir que tu jefe olvide que ellos existen, y es endiabladamente fácil para un estimado convertirse en un programa sin que sean considerados los unk-unks.

En un entorno de equipo, deberías tratar de tener a la gente que hará el trabajo de elaborar el estimado, y deberías intentar tener un consenso con el equipo en general sobre los estimados. La gente varía ampliamente en habilidad, experiencia, preparación, y confianza. La calamidad golpea cuando un programador fuerte estima para él mismo y luego se le mantiene este estimado a los programadores débiles. El hecho de tener de acuerdo al equipo completo en una base de línea por línea del estimado clarifica la comprensión del equipo, al igual que permite la oportunidad para la reasignación táctica de recursos (por ejemplo, intercambiar carga de trabajo de miembros del equipo más débiles a otros más fuertes).

Si existen grandes riesgos que no puedan ser evaluados, es tu deber establecerlos lo suficientemente fuerte como para que tu administrador no se comprometa a ellos y luego se avergüence cuando sucedan los riesgos. Hopefully en tales casos se hará lo que sea necesario para disminuir el riesgo.

Si puedes convencer a tu compañía de usar la Programación Extrema, solamente tendrás que estimar cosas relativamente pequeñas, y esto es tan divertido como productivo.

Cómo Encontrar Información

La naturaleza de lo que necesitas saber determina cómo deberías encontrarlo.

Si necesitas información sobre cosas concretas que son objetivas y fáciles de verificar, por ejemplo el último nivel de parcheo de un producto software, pregunta cortésmente a un gran número de personas buscándolas en la Internet o colocando mensajes en un grupo de discusión. No busques en la Internet algo que sabe o tiene un dejo de opinión o interpretación subjetiva: el nivel de tonterías en las que confiar es demasiado alto.

Si necesitas conocimiento general sobre algo subjetivo como la historia o lo que la gente ha pensado acerca de ella, ve a la biblioteca (el edificio físico en el cual hay libros almacenados). Por ejemplo, para aprender sobre matemática u hongos o misticismo, ve a la biblioteca.

Si necesitas saber cómo hacer algo que no es trivial consigue dos o tres libros sobre el tema y léelos. Podrías aprender cómo hacer algo trivial, como instalar un paquete de software, desde la Internet. Puedes incluso aprender cosas importantes, como buenas técnicas de programación, pero puedes fácilmente pasar más tiempo buscando y ordenando los resultados e intentar adivinar la autoridad de los resultados que lo que tomaría leer la parte pertinente de un sólido libro.

Si necesitas información que nadie más podría esperarse que sepa por ejemplo, '¿funciona esta nueva marca de software sobre conjuntos de datos gigantescos?', aún debes buscar en la Internet y la biblioteca. Después de que esas opciones estén completamente agotadas, puedes diseñar un experimento para comprobarlo.

Si quieres una opinión o un juicio de valor que tome en cuenta alguna circunstancia única, habla con un experto. Por ejemplo, si quieres saber si es una buena idea o no el construir un sistema de manejo de base de datos en LISP, deberías hablar con un experto en LISP y a un experto en bases de datos.

Si quieres saber qué tan probable es que exista un algoritmo más rápido para una aplicación particular que no haya sido publicado, habla con alguien que trabaje en ese campo.

Si quieres hacer una decisión personal que solamente tú puedes hacer como si deberías o no empezar un negocio, intenta poner por escrito una lista de argumentos a favor y en contra de la idea. Si eso falla, considera la adivinación. Supón que has estudiado la idea desde todos los ángulos, haz hecho toda tu tarea en casa, y analizado en tu mente todas las consecuencias y pros y contras, y todavía estás indeciso. Ahora debes seguir a tu corazón y decirle a tu cerebro que se calle. La multitud de técnicas de adivinación disponibles son muy útiles para determinar tus propios deseos

semiconscientes, puesto que cada uno de ellos presenta un patrón aleatorio y completamente ambiguo al que tu propio subconsciente asignará significado.

Cómo Utilizar a la Gente como Fuentes de Información

Respeta el tiempo de cada persona y balancéalo frente al tuyo propio. El hacer a alguien una pregunta conlleva mucho más que sólo recibir la respuesta. La persona aprende sobre ti, tanto al disfrutar de tu presencia como al escuchar la pregunta particular. Tu aprendes sobre la persona de la misma forma, y puedes aprender la respuesta que buscas. Esto es usualmente mucho más importante que tu pregunta.

Sin embargo, el valor de esto disminuye entre más lo repitas. Estás, después de todo, usando la comodidad más preciada que una persona tiene: su tiempo. Los beneficios de la comunicación deben ser sopesados frente a los costos. Además, los costos y los beneficios particulares derivados difieren de persona a persona. Creo firmemente que un ejecutivo de 100 personas debería invertir cinco minutos de su tiempo al mes hablando con cada persona de su organización, lo cual representaría cerca del 5% de su tiempo. Pero diez minutos podrían ser demasiados, y cinco es demasiado si tienen mil empleados. La cantidad de tiempo que inviertes hablando con cada persona en tu organización depende de su rol (más que de su posición). Deberías hablar con tu jefe más que con el jefe de tu jefe, pero deberías hablar un poco con el jefe de tu jefe. Puede ser incómodo, pero creo que tienes el deber de hablar un poquito con todos tus superiores, cada mes, no importa de qué.

La regla básica es que todos se benefician de hablar un poquito contigo, y entre más hablen contigo, menos beneficio deriva. Es tu trabajo proporcionarles ese beneficio, y obtener el beneficio de comunicarte con ellos, manteniendo el beneficio en balance con el tiempo invertido.

Es importante respetar tu propio tiempo. Si hablas con alguien, incluso si ello les costará tiempo, te ahorrará una gran cantidad de tiempo, entonces deberías hacerlo a menos que pienses que su tiempo es más valioso que el tuyo, para la tribu, por ese factor.

Un raro ejemplo de esto es el interno de verano. No puede esperarse que un interno de verano en una posición altamente técnica logre mucho; puede esperarse de él que importune el infierno de todos ahí. Entonces ¿por qué es tolerado? Porque los importunados están recibiendo algo importante del interno. Ellos tienen la oportunidad de enseñar algo. Tienen la oportunidad de escuchar algunas ideas nuevas, quizá; Tienen la oportunidad de ver las cosas desde una perspectiva diferente. También pueden estar intentando reclutar al interno, pero aún si este no es el caso hay mucho que ganar.

Deberías pedirle a la gente un poco de su sabiduría y juicio las veces que honestamente creas que tienen algo que decir. Esto los adula y tu aprenderás algo y les enseñarás algo. Un buen programador no necesita a menudo el consejo de un Vicepresidente de Ventas, pero si alguna vez lo necesitas, asegúrate de pedirlo. Una vez pedí escuchar unas pocas llamadas de ventas para comprender mejor el trabajo de nuestro staff de ventas. Esto no tomó más de 30 minutos pero pienso que el pequeño esfuerzo causó una impresión en las fuerzas de ventas.

Cómo Documentar Sabiamente

La vida es demasiado corta como para escribir basura que nadie leerá; si escribes basura, nadie la leerá. Por lo tanto un poco de buena documentación es mejor. Los administradores a menudo no comprenden esto, debido a que aún la mala documentación les da un falso sentido de seguridad de que ellos no son dependientes de sus programadores. Si alguien insiste absolutamente en que escribas verdadera documentación inútil, di "si'' y calladamente empieza a buscar un mejor empleo.

No hay nada tan efectivo como poner un estimado preciso de la cantidad de tiempo que tomará producir buena documentación en un estimado para reducir la demanda de documentación. La verdad es fría y dura: la documentación, como las pruebas, pueden tomar períodos de tiempo mucho más largos que el desarrollo de código.

Escribir buena documentación es, antes de todo, cuestión de buena escritura. Te sugiero buscar libros sobre escritura, estudiarlos y practicar. Pero incluso si eres un mal escritor o tienes un pobre dominio del lenguaje en el cual debes documentar, la Regla de Oro es todo lo que necesitas: "Haz a los otros lo que te gustaría que te hicieran a ti.'' Toma tiempo pensar realmente acerca de quién estará leyendo tu documentación, qué necesitan sacar de ella, y cómo puedes enseñarles eso. Si haces esto, serás un escritor de documentación por encima del promedio, y un buen programador.

Cuando se trata de documentar código por sí mismo, como algo opuesto a producir documentos que realmente puedan ser leídos por no programadores, los mejores programadores que he conocido tienen un sentimiento universal: escribe código autoexplicativo y solamente documenta el código en los lugares que no puedes hacerlo claro mediante el código mismo. Hay dos buenas razones para esto. Primero, cualquiera que necesite ver la documentación a nivel de código será capaz en la mayoría de los casos y preferirá leer el código de todas formas. Reconocidamente, esto parece más fácil para el programador experimentado que para el principiante. Más importante sin embargo, es que el código y la documentación no pueden ser inconsistentes si no hay documentación. El código fuente en el peor de los casos puede estar equivocado y confuso. La documentación, si no está escrita perfectamente, puede mentir, y eso es mil veces peor.

Esto no facilita las cosas para el programador responsable. ¿Cómo escribe uno código autoexplicativo? ¿Qué significa incluso eso? Ello significa:

Escribir código sabiendo que alguien tendrá que leerlo; Aplicar la regla de oro; Elegir una solución que sea directa, incluso si cuentas con otra solución más

rápida; Sacrificar pequeñas optimizaciones en lugar de ofuscar el código; Pensar en el lector e invertir algo de tu precioso tiempo en hacerlo más fácil

para él; y ¡Nunca usar una función con nombres como "foo'', "bar'', o "Hazlo''!

Cómo Trabajar con Código Pobre

Es muy común tener que trabajar con código de pobre calidad que alguien más ha escrito. Sin embargo, no pienses muy pobremente de ellos, hasta que hayas caminado con sus zapatos. A ellos se le pudo haber pedido muy conscientemente hacer algo rápidamente para cumplir con la presión del calendario. Sin que esto importe, a fin de trabajar con código poco claro debes comprenderlo. Comprenderlo toma tiempo de aprendizaje, y ese tiempo tendrá que salir del cronograma, de alguna parte, y debes

insistir en ello. Para comprenderlo, tendrás que leer el código fuente. Probablemente tendrás que experimentar con él.

Este es un buen momento para documentar, incluso si es solamente para ti mismo, debido a que el acto de intentar documentar el código te forzará a considerar ángulos que podrías no haber considerado, y el documento resultante puede ser útil. Mientras estás haciendo esto, considera lo que tomaría reescribir alguna parte o todo el código. ¿Realmente ahorraría tiempo reescribir parte de él? ¿Podrías confiar mejor en él si lo reescribes? Se cuidadoso aquí con la arrogancia. Si lo reescribes, será más fácil para ti lidiar con él, pero ¿realmente será más fácil para la próxima persona que tenga que leerlo? Si lo reescribes, ¿cuál será la carga de la prueba? ¿Sobrepasará la necesidad de recomprobarlo cualquier beneficio que pudiera ganarse?

En cualquier estimado que hagas para trabajar frente a código que no escribiste, la calidad de ése código debería afectar tu percepción del riesgo de problemas y los unk-unks.

Es importante recordar que la abstracción y la encapsulación, dos de las mejores herramientas de un programador, son particularmente aplicables al mal código. Puede que no seas capaz de rediseñar un gran bloque de código, pero si puedes añadir cierta cantidad de abstracción a él puedes obtener algunos de los beneficios de un buen diseño sin reelaborar todo el desorden. En particular, puedes intentar identificar las partes que son particularmente malas de tal forma que puedan ser rediseñadas independientemente.

Cómo Usar el Control del Código Fuente

Los sistemas de control de código fuente te permiten manejar proyectos efectivamente. Ellas son muy útiles para una persona y esenciales para un grupo. Registran todos los cambios en versiones diferentes de manera que nunca se pierde ningún código y puede asignársele significado a los cambios. Uno puede crear y depurar código desechable con confianza usando un sistema de control de código, puesto que el código que modificas se mantiene cuidadosamente separado del código oficial comprometido que será compartido con el equipo o liberado.

Tardé en apreciar los beneficios de los sistemas de control de código pero ahora no viviría sin uno aún en proyectos personales. Generalmente son necesarios cuando tienes equipos trabajando sobre el mismo código base. Sin embargo, tienen otra gran ventaja: fomentan el pensar acerca del código como un sistema orgánico en crecimiento. Puesto que cada cambio se etiqueta como una nueva revisión con un nuevo nombre o número, uno empieza a ver el software como series de mejoras visiblemente progresivas. Pienso que esto es especialmente útil para los principiantes.

Una buena técnica para usar un sistema de control de código es permanecer a pocos días de estar actualizado todo el tiempo. El código que no puede ser finalizado en unos cuantos días se Chequea, pero de una forma que queda inactivo y no será oficialmente nombrado, y por lo tanto no creará problemas para nadie más. Cometer un error que desacelere a tus compañeros de equipo es un serio error; es a menudo un tabú.

Cómo Probar Unidades

La prueba de unidad, la prueba de una pieza individual de funcionalidad codificada por el equipo que lo escribió, es una parte de la codificación, no algo diferente de ella. Parte del diseño del código es diseñar cómo será probado. Deberías poner por escrito

un plan de prueba, incluso si solamente es una oración. A veces la prueba será simple: "¿Se ve bien este botón?'' Algunas veces será complejo: "¿Retornó este algoritmo de hermanamiento precisamente las parejas correctas?''

Usa chequeo de afirmaciones y prueba los manejadores cada vez que sea posible. Esto no solamente atrapa los bugs anticipadamente, sino que es muy útil después sobre la marcha y te permite eliminar misterios de los que de otra forma tendrías que preocuparte.

Los desarrolladores de la Programación Extrema han escrito extensivamente sobre probar unidades efectivamente; no puedo hacer nada mejor que recomendar sus escritos.

Toma Descansos Cuando estés Confundido

Cuando estés confundido, toma un descanso. Algunas veces medito por 15 minutos cuando estoy confundido y el problema mágicamente se descifra cuando regreso a él. El sueño de una noche a veces hace lo mismo a una escala mayor. Es posible que el cambiar temporalmente a cualquier otra actividad pueda funcionar.

Cómo Reconocer Cuándo Ir a Casa

La programación de computadoras es una actividad que es también una cultura. El hecho desafortunado es que no es una cultura que valora mucho la salud mental o física. Tanto por razones histórico/culturales (la necesidad de trabajar por la noche en computadoras sin mucha carga de trabajo, por ejemplo) y debido a la abrumadora presión de tiempo de mercadeo y la escasez de programadores, los programadores de computadoras son tradicionalmente sobretrabajados. No creo que puedas fiarte de todas las historias que escuches, pero pienso que 60 horas a la semana es común, y 50 es un mínimo muy común. Esto significa que a menudo se requiere mucho más que eso. Este es un serio problema para un buen programador, el cual es responsable no solamente por él mismo sino también por sus compañeros de equipo. Tienes que reconocer cuándo ir a casa, y a veces cuándo sugerir que otras personas vayan a casa. No puede haber ninguna regla fija para resolver este problema, más de lo que puede haberla para alzar un niño en brazos, por la misma razón---cada ser humano es diferente.

Más allá de 60 horas a la semana es un extraordinario esfuerzo para mí, el cual puedo aplicar por cortos periodos de tiempo (cerca de una semana), y eso se espera de mí algunas veces. No sé si es legal esperar 60 horas de trabajo de una persona; incluso no sé si 40 es legal. Estoy seguro, sin embargo, que es estúpido trabajar tanto que te excedas de esas horas extras que trabajas. Personalmente para mí, eso es más de las 60 horas a la semana. Personalmente pienso que un programador debería ejercer su noble obligación y apoyar una carga pesada. Sin embargo, no es el deber de un programador ser un patsy. El hecho triste es que a los programadores a menudo se les pide ser patsies es a fin de poner en escena a alguien, por ejemplo a un administrador tratando de impresionar a un ejecutivo. Los programadores a menudo sucumben a esto debido a que ellos son más propensos a agradar y no muy buenos para decir no. Hay cuatro defensas contra esto:

Comunícate tanto como sea posible con todos en la compañía de tal forma que nadie pueda extraviar a los ejecutivos acerca de lo que está pasando,

Aprende a estimar y calendariza defensiva y explícitamente y darle a todos la visibilidad de en qué consiste el calendario y dónde se encuentra,

Aprende a decir no, y di no como equipo cuando sea necesario, y Renuncia si tienes que hacerlo.

La mayoría de los programadores son buenos programadores, y los buenos programadores quieren lograr hacer un montón de cosas. Para hacer eso, ellos tienen que administrar su tiempo efectivamente. Hay una cierta cantidad de inercia mental asociada con el entusiasmarse con un problema e involucrarse profundamente con él. Muchos programadores encuentran que trabajan mejor cuando tienen largos e ininterrumpidos bloques de tiempo en los cuales entusiasmarse y concentrarse. Sin embargo, la gente debe dormir y realizar otros deberes. Cada persona necesita encontrar una forma de satisfacer tanto su ritmo humano como su ritmo de trabajo. Cada programador necesita hacer lo que sea para procurar periodos de trabajo eficiente, tales como reservar ciertos días en los cuales atienda solamente las juntas más críticas.

Puesto que tengo niños, trato a veces de pasar las tardes con ellos. El ritmo que funciona mejor para mí es trabajar un muy largo día, dormir en la oficina o cerca de ella (hago un largo viaje de mi casa al trabajo) luego voy a casa lo suficientemente temprano al día siguiente para pasar tiempo con mis niños antes de que se vayan a la cama. No estoy cómodo con esto, pero es el mejor compromiso que he sido capaz de hacer. Ve a casa si tienes una enfermedad contagiosa. Deberías ir a casa si estás teniendo pensamientos suicidas. Deberías tomar un descanso o ir a casa si tienes pensamientos homicidas por más de unos pocos segundos. Deberías enviar a alguien a casa si ellos muestran mal funcionamiento mental o signos de una enfermedad mental más allá de una leve depresión. Si estás tentado a ser deshonesto o defraudante en una forma que normalmente no eres debido a la fatiga, deberías tomarte un descanso. No uses cocaína o anfetaminas para combatir la fatiga. No abuses de la cafeína.

Cómo Lidiar con Gente Difícil

Probablemente tienes que lidiar con gente difícil. Tú mismo incluso puedes ser una persona difícil. Si eres el tipo de persona que tiene muchos conflictos con los compañeros de trabajo y figuras de autoridad, deberías apreciar la independencia que eso implica, pero trabaja en tus habilidades interpersonales sin sacrificar tu inteligencia o principios.

Esto puede ser muy molesto para algunos programadores que no tienen experiencia en este tipo de cosas y cuya experiencia de vida precia les ha enseñado patrones de comportamiento que no son muy útiles en el lugar de trabajo. La personas difíciles están a menudo habituadas al desacuerdo y son menos afectadas por la presión social para comprometerse que otras. La clave es respetarlos apropiadamente, lo cual es más de lo que tu querrás hacer pero no es tanto como lo que ellos podrían querer.

Los programadores tienen que trabajar juntos como un equipo. Cuando surgen los desacuerdos, deben ser resueltos de algún modo, no pueden ser esquivados por mucho tiempo. Las personas difíciles son a menudo extremadamente inteligentes y tienen algo muy útil que decir. Es crítico que escuches y entiendas a la persona difícil sin prejuicios causados por ella. Un falla de comunicación es a menudo la base del desacuerdo pero a veces puede ser eliminada con gran paciencia. Intenta mantener esta comunicación fresca y cordial, y no aceptes ninguna provocación para agrandar el conflicto que pueda ofrecerse. Después de un razonable periodo para intentar comprender, toma una decisión.

No permitas que la intimidación te fuerce a hacer algo con lo que no estás de acuerdo. Si eres el líder, haz lo que piensas que es mejor. No tomes una decisión por razones personales, y está preparado para explicar las razones de tu decisión. Si eres compañero de equipo con una persona difícil, no permitas que la decisión del líder tenga ningún impacto personal. Si no es a tu modo, hazlo de la otra forma de todo corazón.

La gente difícil cambia y mejora. Lo he visto con mis propios ojos, pero es muy raro. Sin embargo, todos tienen altibajos transitorios.

Uno de los desafíos que cada programador y especialmente los líderes enfrentan es mantener a la persona difícil completamente comprometida. Ellos son mucho más propensos a evadir trabajo y resistir pasivamente que otros.

Capítulo 3. Intermedio

Tabla de ContenidoHabilidades Personales

Cómo Permanecer MotivadoCómo ser Ampliamente ConfiableCómo Negociar Tiempo vs. EspacioCómo Hacer Pruebas de EstrésCómo Balancear la Brevedad y la AbstracciónCómo Aprender Nuevas HabilidadesAprende a TeclearCómo Hacer Pruebas de IntegraciónLenguajes de ComunicaciónHerramientas PesadasCómo Analizar Datos

Habilidades de EquipoCómo Administrar el Tiempo de DesarrolloCómo Manejar Riesgos de Software de Terceras PartesCómo Manejar ConsultoresCómo Comunicar la Cantidad AdecuadaCómo Disentir Honestamente y Sobrellevarlo

JuicioCómo Negociar Calidad Frente a Tiempo de DesarrolloCómo Manejar la Dependencia del Sistema de SoftwareCómo Decidir si el Software es Muy InmaduroCómo Hacer una Decisión de Compra vs. ConstrucciónCómo Crecer ProfesionalmenteCómo Evaluar EntrevistadosCómo Saber Cuándo Aplicar Ciencia Computacional FantasiosaCómo Hablar con No Ingenieros

Habilidades Personales

Cómo Permanecer Motivado

Es un hecho maravilloso y sorprendente que los programadores son altamente motivados por el deseo de crear artefactos que sean bellos, útiles, o nifty. Este deseo no es único para los programadores ni universal pero es tan fuerte y común entre los programadores que los separa de otros en otros roles.

Esto tiene consecuencias prácticas e importantes. Si a los programadores se les pide hacer algo que no sea bello, útil, o nifty, tendrán la moral baja. Hay un montón de dinero que ganar haciendo material feo, estúpido y aburrido; pero al final, la diversión hará la mayor cantidad de dinero para la compañía.

Obviamente, existen industrias completas organizadas alrededor de técnicas motivacionales algunas de las cuales se aplican aquí. Las cosas que son específicas a la programación que puedo identificar son:

Usa el mejor lenguaje para el trabajo. Busca oportunidades para aplicar nuevas técnicas, lenguajes, y tecnologías. Intenta aprender o enseñar algo, aunque sea algo pequeño, en cada proyecto.

Finalmente, si es posible, mide el impacto de tu trabajo en términos de algo que será personalmente motivador. Por ejemplo, al corregir bugs, contar el número de bugs que he corregido no es del todo motivacional para mí, debido a que es independiente del número que puedan aún existir, y también afecta el valor total que estoy agregando a los clientes de mi compañía de la más pequeña forma posible. Relacionar cada bug con un cliente feliz, sin embargo, es personalmente motivador para mí.

Cómo ser Ampliamente Confiable

Para ser confiable debes ser confiable. Debes también ser visible. Si nadie sabe acerca de ti, no se invertirá ninguna confianza en ti. Con quienes están cerca de ti, tales como tus compañeros de equipo, esto no debería ser un problema. Tú estableces confianza siendo responsable e informativo para aquellos fuera de tu departamento o equipo. Ocasionalmente alguien abusará de esta confianza, y pedirá favores no razonables. No temas a esto, sólo explica a lo que tendrías que renunciar al hacer el favor.

No pretendas saber algo que no sabes. Con la gente que no son compañeros de equipo, puede que tengas que hacer una clara distinción entre "no conocer bien el límite de mis capacidades'' y "no ser capaz de hacerlo, nunca.''

Cómo Negociar Tiempo vs. Espacio

Puedes ser un buen programador sin ir a la universidad, pero no puedes ser un buen programador intermedio sin conocer la teoría de la complejidad computacional básica. No necesitas conocer la notación de la "gran O'', pero personalmente pienso que deberías ser capaz de comprender la diferencia entre "constantes de tiempo'', "n logaritmo de n'' y "n al cuadrado''. Podrías ser capaz de intuir cómo negociar tiempo frente a espacio sin ese conocimiento, pero en su ausencia no tendrás una base firme para comunicarte con tus colegas.

Al diseñar o comprender de un algoritmo, la cantidad de tiempo que toma para ejecutarse es a veces una función del tamaño de la entrada. Cuando eso es cierto, podemos decir que el peor, el mejor y el caso esperado de tiempo de ejecución de un algoritmo es "n log n'' si es proporcional al tamaño ($n$) veces el logaritmo del tamaño. La notación y forma de hablar puede ser también aplicada al espacio tomado por una estructura de datos.

Para mí, la teoría de la complejidad computacional es bella y tan profunda como la física---¡y con poquito margen continúan juntas por un largo trecho!

El tiempo (los ciclos del procesador) y el espacio (la memoria) pueden ser negociados entre sí. La ingeniería trata acerca de compromisos, y este es un buen ejemplo. No siempre es sistemática. En general, sin embargo, uno puede ahorrar espacio al codificar las cosas más fuertemente, al costo de más tiempo de computación cuando tienes que decodificarlas. Puedes ahorrar tiempo mediante el cacheo, o sea, al invertir espacio para almacenar una copia local de algo, al costo de tener que mantener la consistencia del caché. Puedes a veces ahorrar tiempo manteniendo más información en una estructura de datos. Esto usualmente cuesta una pequeña cantidad de espacio pero puede complicar el algoritmo.

Mejorar el intercambio espacio/tiempo puede a menudo cambiar a uno o al otro dramáticamente. Sin embargo, antes de que trabajes en esto deberías preguntarte a ti mismo si lo que estás mejorando es realmente lo que necesita la mejoría. Es divertido trabajar en un algoritmo, pero no puedes permitir que te ciegue hasta el frío y duro hecho de que el mejorar algo que no es un problema no hará ninguna notable diferencia y que sólo creará una carga de prueba.

La memoria en las modernas computadoras parece barata, debido a que a diferencia del tiempo de procesador, no puedes verla en uso hasta que golpeas la pared; pero entonces la falla es catastrófica. Hay también otros costos ocultos al usar la memoria, tales como su efecto en otros programas que deben ser residentes, y el tiempo para asignarla y desasignarla. Considera esto cuidadosamente antes de que sacrifiques espacio para ganar velocidad.

Cómo Hacer Pruebas de Estrés

Las pruebas de estrés son divertidas. Al principio parece que el propósito de las pruebas de estrés es determinar si el sistema trabaja bajo una carga. En realidad, es común que el sistema no funcione bajo una carga pero falla de alguna manera cuando la carga es lo suficientemente pesada. Llamo a esto Igolpear la pared o bonking[1]. Pueden haber algunas excepciones, pero casi siempre hay una 'pared'. El propósito de las pruebas de estrés es determinar dónde está la pared, y luego se deduzca cómo moverla un poco más allá.

Un plan para las pruebas de estrés debería desarrollarse en la etapas tempranas del proyecto, debido a que a menudo ayuda a clarificar exactamente lo que se espera. ¿Son dos segundos para una solicitud de página web una falla miserable o un éxito aplastante? ¿Son suficientes 500 usuarios concurrentes? Eso, por supuesto, depende, pero uno debe saber la respuesta cuando se diseña el sistema que conteste la pregunta. La prueba de estrés necesita modelar la realidad lo suficientemente bien como para ser útil. No es realmente posible simular muy fácilmente 500 erráticos e impredecibles humanos usando un sistema concurrentemente, pero uno puede al menos crear 500 simulaciones e intentar modelar alguna parte de lo que ellos podrían hacer.

En las pruebas de estrés, empieza con una ligera carga y carga el sistema a lo largo de alguna dimensión---tal como el tipo o el tamaño de la entrada---hasta que golpees la pared. Si la pared está demasiado cerca para satisfacer tus necesidades, resuelve cuál recurso es el cuello de botella (usualmente hay uno que predomina.) ¿Es la memoria, el procesador, la E/S, el ancho de banda, o la contención de datos? Luego determina cómo puedes mover la pared. Nota que mover la pared, es decir, incrementar la carga máxima que el sistema puede manejar, podría no ayudar o de hecho afectar el desempeño de sistema ligeramente cargado. Usualmente el desempeño bajo carga pesada es más importante que el desempeño bajo una carga ligera.

Puede que tengas que obtener visibilidad desde varias dimensiones diferentes para construir un modelo mental de él; ninguna técnica por sí sola es suficiente. Por ejemplo, hacer un registro de sucesos a menudo da una buena idea del tiempo del reloj de pared entre dos eventos en el sistema, pero a menos que sea cuidadosamente construido, no proporciona visibilidad de la utilización de la memoria e incluso del tamaño de la estructura de datos. De manera similar, en un sistema moderno, pueden estar cooperando un número de computadoras y muchos sistemas de software. Particularmente cuando estás golpeando la pared (o sea, el desempeño es no lineal en el tamaño de la entrada) esos otros sistemas de software pueden ser un cuello de botella. La visibilidad en esos sistemas, aún si solamente mides la carga del procesador en todas las máquinas participantes, puede ser muy útil.

Saber dónde está la pared es esencial no solamente para moverla, sino también para proporcionar previsibilidad de tal manera que el negocio pueda ser administrado efectivamente.

Cómo Balancear la Brevedad y la Abstracción

La abstracción es clave para la programación. Deberías elegir cuidadosamente qué tan abstracto necesitas ser. Los programadores principiantes en su entusiasmo a menudo crean más abstracción de la que es realmente útil. Una señal de ello es si creas clases que realmente no contienen ningún código y realmente no hagan algo excepto servir para abstraer algo. La atracción de esto es comprensible pero el valor de la brevedad del código puede ser medida frente al valor de la abstracción. Ocasionalmente, uno observa un error hecho por idealistas entusiastas: al inicio del proyecto se definen un montón de clases que parecen maravillosamente abstractas y uno puede especular que ellas manejarán cada eventualidad que pueda surgir. A medida que el proyecto progresa y la fatiga empieza a sentirse, el código mismo se vuelve desordenado. El cuerpo de las funciones se vuelve más largo de lo que deberían ser. Las clases vacías son una carga al documentar que es ignorada cuando se está bajo presión. El resultado final habría sido mejor si la energía gastada en la abstracción hubiese sido invertida en mantener las cosas pequeñas y simples. Esta es una forma de programación especulativa. Recomiendo fuertemente el artículo "Succinctness is Power'' (La Concisión es Poder) de Paul Graham [PGSite].

Hay un cierto dogma asociado con técnicas útiles tales como el ocultamiento de la información y laprogramación orientada a objetos que a veces se llevan demasiado lejos. Esas técnicas le permiten a uno codificar abstractamente y anticipar cambios. Personalmente pienso, sin embargo, que no deberías producir mucho código especulativo. Por ejemplo, es un estilo aceptado ocultar una variable entera en un objeto tras mutators y accesorios, de tal manera que la variable misma no esté expuesta, solamente la pequeña interface a ella. Esto permite que la implementación de esa variable sea cambiada sin afectar al código de llamada, y es quizá apropiado para un escritor de bibliotecas que debe publicar una API (Application Program Interface, Interfaz de Programa de aplicación) muy estable. Pero no creo que el beneficio de esto supere el costo de la palabrería de ello cuando mi equipo posee el código llamador y por lo tanto puede recodificar al llamador tan fácilmente como al llamado. Cuatro o cinco líneas extra de código es un pesado precio a pagar por este beneficio especulativo.

La portabilidad posee un problema similar. ¿Debería el código ser portable a una computadora, compilador, sistema de software o plataforma diferente, o simplemente ser fácilmente portado? Pienso que una pieza de código no portable, pequeña y fácilmente portada es mejor que una ampliamente portable. Es relativamente fácil y

ciertamente una buena idea confinar el código no portable a áreas no designadas, tales como una clase que hace consultas a una base de datos que son específicos para un DBMS (Data Base Management System) dado.

Cómo Aprender Nuevas Habilidades

Aprender nuevas habilidades, especialmente las no técnicas, es la diversión más grande de todas. La mayoría de las compañías tendrían una mejor moral si comprendieran cuánto motiva esto a los programadores.

Los humanos aprenden haciendo. La lectura de libros y la toma de cursos son útiles. Pero ¿podrías tener algún respeto por un programador que nunca ha escrito un programa? Para aprender cualquier habilidad, tienes que ponerte a ti mismo en una posición dispensadora donde puedas ejercitar esa habilidad. Cuando aprendas un nuevo lenguaje de programación, trata de hacer un pequeño proyecto en él antes de que tengas que hacer un proyecto grande. Cuando estés aprendiendo a manejar un proyecto de software, trata de manejar primero uno pequeño.

Un buen mentor no es reemplazo para hacer cosas por ti mismo, pero es mucho mejor que un libro. ¿Qué puedes ofrecer a un mentor potencial a cambio de su conocimiento? Como mínimo, deberías ofrecer estudiar duro de tal manera que su tiempo no será desperdiciado.

Intenta conseguir que tu jefe te permita tener entrenamiento formal, pero comprende que ello a menudo no es mucho mejor que la misma cantidad de tiempo invertida simplemente en jugar con la nueva habilidad que deseas aprender. Es, sin embargo, más fácil solicitar entrenamiento que tiempo para jugar en nuestro mundo imperfecto, aunque es sabido que una gran parte del entrenamiento formal consiste solamente en dormir a través de las conferencias esperando la fiesta de la cena.

Si diriges personas, entiende cómo ellos aprenden y apóyalos asignándoles proyectos que sean del tamaño adecuado y que ejerciten habilidades en las que están interesados. No olvides que las habilidades más importantes para un programador no son las técnicas. Dale a tu gente una oportunidad para jugar y practicar coraje, honestidad, y comunicación.

Aprende a Teclear

Aprende a teclear bien. Esta es una habilidad intermedia debido a que escribir código es tan difícil que la velocidad a la cual puedas teclear es irrelevante y no puedes hacer mucho durante el tiempo que toma escribir código, no importa qué tan bueno eres. Sin embargo, mientras seas un programador intermedio probablemente pasarás mucho tiempo escribiendo lenguaje natural para tus colegas y otros. Esta es una divertida prueba de tu compromiso; requiere tiempo dedicado que no es muy divertido aprender algo como eso. La leyenda dice que cuando Michael Tiemann [2] estaba en el MCC la gente se quedaba fuera detrás de su puerta para escuchar el zumbido generado por sus golpes de tecla los cuales eran tan rápidos como indistinguibles.

Cómo Hacer Pruebas de Integración

La prueba de integración es la prueba de la integración de varios componentes que han sido probados como unidades independientes. La integración es costosa y el costo

proviene de la prueba. Debes incluir tiempo para esto en tus estimados y tu cronograma.

Idealmente deberías organizar un proyecto de tal forma que no sea una fase al final donde la integración debe explícitamente tomar lugar. Es mucho mejor integrar gradualmente las cosas a medida que se completan en el curso del proyecto. Si es inevitable estímalo cuidadosamente.

Lenguajes de Comunicación

Hay algunos lenguajes, es decir, sistemas sintácticos formalmente definidos, que no son lenguajes de programación sino lenguajes de comunicación---son diseñados específicamente para facilitar la comunicación a través de la estandarización. En el 2003 los más importantes fueron el UML, el XML, y el SQL. Deberías tener alguna familiaridad con todos ellos de manera que puedas comunicarte bien y decidir cuándo usarlos.

El UML es un rico sistema formal para hacer diagramas que describen diseños. Su belleza descansa en que es tanto visual como formal, capaz de transmitir una gran cantidad de información si tanto el autor como la audiencia conocen el UML. Necesitas saber sobre él debido a que los diseños están algunas veces comunicados en él. Hay muchas herramientas útiles para hacer diagramas UML que lucen muy profesionales. En muchos casos el UML es demasiado formal, y me descubro a mí mismo usando un estilo más simple de cajas y flechas para diseñar diagramas. Pero estoy muy seguro que el UML es al menos tan bueno para ti como el estudiar Latín.

El XML es un estándar para diseñar nuevos estándares. No es una solución para problemas de intercambio de datos, aunque algunas veces lo veas presentado como si lo fuera. Más bien, es una bienvenida automatización de las más aburridas partes del intercambio de datos, como es, el estructurar la representación en una secuencia lineal y analizar la estructura. Provee un agradable chequeo de tipos -y de correctitud-, aunque de nuevo es solamente una fracción de lo que probablemente vas a necesitar en la práctica.

El SQL es un muy poderoso y rico lenguaje de manipulación de datos que no es propiamente un lenguaje de programación. Tiene muchas variantes, típicamente muy dependientes del producto, las cuales son menos importantes que el núcleo estandarizado. El SQL es la lingua franca de las bases de datos relacionales. Puede que trabajes o no en cualquier campo que pueda beneficiarse de una comprensión de las bases de datos relacionales, pero deberías tener una comprensión básica de ellas y de la sintaxis y significado del SQL.

Herramientas Pesadas

A medida que nuestra cultura tecnológica progresa, la tecnología del software se mueve de lo inconcebible, a la investigación, a nuevos productos, a productos estandarizados, a productos ampliamente disponibles y baratos. Esas herramientas pesadas pueden sobrellevar grandes cargas, pero pueden ser intimidantes y requieren una gran inversión en su comprensión. El programador intermedio tiene que saber cómo manejarlas y cuándo deberían ser usadas o consideradas.

A mi entender algunas de las mejores herramientas son:

Bases de Datos Relacionales, Motores de Búsqueda de Texto Completo, Bibliotecas Matemáticas, OpenGL, parsers XML, y Hojas de Cálculo.

Cómo Analizar Datos

El análisis de datos es un proceso en las primeras etapas del desarrollo de software, cuando examinas una actividad de negocio y encuentras los requerimientos para convertirlo en una aplicación de software. Esta es una definición formal, la cual puede conducir a pensar el análisis de datos es una acción que deberías dejar mejor a los analistas de sistemas, mientras tú, el programador, deberías enfocarte en codificar lo que alguien más ha diseñado. Si seguimos estrictamente el paradigma de la ingeniería de software, ello podría ser correcto. Los programadores experimentados se vuelven diseñadores y los más agudos diseñadores se convierten en analistas de negocios, siendo así intitulados a pensar en todos los requerimientos de datos y a darte tareas bien definidas para hacer. Esto no es completamente exacto, debido a que los datos son el núcleo de cada actividad de la programación. Lo que sea que hagas en tus programas, estás moviéndote alrededor de o modificando los datos. El analista de negocios está analizando las necesidades a una mayor escala, y el diseñador de software está exprimiendo más dicha escala de tal forma que, cuando el problema aterriza en tu escritorio, parece que todo lo que necesitas hacer es aplicar algoritmos inteligentes y comenzar a mover los datos existentes.

No es así.

No importa en cuál etapa empieces a verlo, los datos son el principal interés de una aplicación bien diseñada. Si miras de cerca cómo un analista de negocios obtiene los requirimientos de la solicitud del cliente, te darás cuenta de que los datos juegan un papel fundamental. El analista crea los llamados Diagramas de Flujo de Datos, donde todos las fuentes de datos están identificadas y el flujo de la información es modelada. Habiendo definido claramente cuáles datos deberían formar parte del sistema, el diseñador modela las fuentes de datos, en términos de relaciones de bases de datos, protocolos de intercambio de datos, y formatos de archivos, de tal manera que la tarea está lista para ser pasada al programador. Sin embargo, el proceso no termina todavía, porque tú "el programador" aún después de este completo proceso de refinamiento de datos, se te pide analizar los datos para llevar a cabo la tarea de la mejor forma posible. La línea final de tu tarea es el mensaje central de Niklaus Wirth, el padre de varios lenguajes. "Algoritmos + Estructuras de Datos = Programas" Nunca ha habido un algoritmo que permanezca solo, haciendo algo para él mismo. Cada algoritmo está supuesto a hacer algo para al menos una pieza de datos.

Por lo tanto, puesto que los algoritmos no atan sus ruedas al vacío, necesitas analizar tanto los datos que alguien más ha identificado para ti como los datos que son necesarios para escribir tu código. Un ejemplo trivial hará la cuestión más clara. Estás implementando una rutina de búsqueda para una biblioteca. De acuerdo a tus especificaciones, el usuario puede seleccionar libros mediante la combinación de género, autor, título, editor, año de impresión, y número de páginas. La meta última de tu rutina es producir una sentencia SQL legal para buscar la base de datos subyacente. Basado en esos requerimientos, tienes varias opciones: chequear cada control por turnos, usar una sentencia "switch", o varios "ifs"; hacer un arreglo de controles de datos, chequear cada elemento para ver si está establecido; crear (o usar) un objeto de

control abstracto desde el cual heredar todos tus controles específicos, y conectarlos a un motor conducido por eventos. Si tus requerimientos incluyen también optimizar el desempeño de la consulta, asegurándote que los ítems sean Chequeados en un orden específico, puedes considerar el uso de un árbol de componentes para construir tu sentencia SQL. Como puedes ver, la elección del algoritmo depende de los datos que decidas usar, o crear. Tales decisiones pueden hacer toda la diferencia entre un algoritmo eficiente y uno desastroso. Sin embargo, la eficiencia no es la única preocupación. Puedes usar una docena de variables en tu código y hacerlo tan eficiente como podría serlo. Pero tal pieza de código podría no ser fácilmente mantenible. Quizá el elegir un contenedor apropiado para tus variables podría mantener la misma velocidad y adicionalmente permitir a tus colegas comprender mejor el código cuando lo vean el próximo año. Además, el escoger una estructura de datos bien definida puede permitirles extender la funcionalidad de tu código sin reescribirlo. A la larga, tus escogencias de datos determinan qué tanto sobrevivirá tu código después de que lo finalices. Permíteme darte otro ejemplo, solamente algo más en lo que pensar. Supongamos que tu tarea es encontrar todas las palabras en un diccionario con más de tres anagramas, donde un anagrama debe ser otra palabra del mismo diccionario. Si piensas en ello como una tarea computacional, terminarás con un esfuerzo sin fin, intentando trabajar todas las combinaciones de cada palabra y luego comparándola a las otras de la lista. Sin embargo, si analizas los datos a mano, te darás cuenta de que cada palabra puede ser representada por un registro conteniendo la palabra en él mismo y un arreglo ordenado de sus letras como ID. Armado con tal conocimiento, encontrar anagramas significa tan solo ordenar la lista sobre el campo adicional y seleccionar las que comparten el mismo ID. El algoritmo de fuerza bruta puede tomar varios días para ejecutarse, mientras que el inteligente solo es cuestión de unos pocos segundos. Recuerda este ejemplo la próxima vez que estés encarando un problema intratable.

Habilidades de Equipo

Cómo Administrar el Tiempo de Desarrollo

Al administrar el tiempo de desarrollo, mantén un plan del proyecto conciso y actualizado. Un plan del proyecto es un estimado, un calendario, un conjunto de hitos (marcas que reflejen avances) para marcar el progreso, y una asignación del tiempo de tu equipo o de tu propio tiempo para cada tarea en el estimado. Debería incluir también las cosas que tengas que recordar hacer, tales como reunirte con la gente de aseguramiento de la calidad, preparar la documentación, u ordenar hardware. Si estás en un equipo, el plan del proyecto debería ser un acuerdo consensual, tanto al inicio como mientras avanzas.

El plan del proyecto existe para ayudar a hacer decisiones, no para mostrar qué tan organizado eres. Si el plan del proyecto es demasiado largo o no está actualizado, será inútil para hacer decisiones. En realidad, esas decisiones son sobre personas individuales. El plan y tu juicio te permiten decidir si deberías transferir tareas de una persona a otra. Los hitos marcan tu progreso. Si usas una herramienta fantástica de planeación de proyecto, no te dejes seducir para crear un Gran Diseño Desde el Frente (GDDF) para el proyecto, pero úsala para mantener la concisión y la actualidad.

Si fallas un hito, deberías tomar una acción inmediata tal como informar a tu jefe que la finalización programada de ese proyecto se ha corrido por esa cantidad. El estimado y el cronograma nunca podrían haber sido perfectos para comenzar; esto crea la ilusión de que podrías ser capaz de reponer los días que perdiste en la última parte del proyecto. Podrías. Pero es tan probable que hayas subestimado esa parte como que la

hayas sobrestimado. Por lo tanto la finalización programada del proyecto ya se ha corrido, te guste o no.

Asegúrate que tu plan incluye tiempo para: reuniones internas de equipo, demos, documentación, actividades periódicas programadas, pruebas de integración, lidiar con foráneos, enfermedades, vacaciones, mantenimiento de productos existentes, y mantenimiento del ambiente de desarrollo. El plan del proyecto puede servir como una vía para de dar a los foráneos o a tu jefe una visión a lo interno de lo que tú o tu equipo están haciendo. Por esa razón debería ser corto y actualizado.

Cómo Manejar Riesgos de Software de Terceras Partes

Un proyecto a menudo depende del software producido por organizaciones que él no controla. Hay grandes riesgos asociados con software de terceras partes que deberían ser reconocidos por todos los involucrados.

Nunca, nunca, deposites ninguna esperanza en el vaporware. El vaporware es cualquier software alegado que ha sido prometido pero que no está disponible aún. Esta es la forma más segura de salir de los negocios. No es sabio estar solamente escéptico de la promesa de una compañía de software para liberar un cierto producto con una cierta funcionalidad en una cierta fecha; es mucho más sabio ignorarlo completamente y olvidar que alguna vez lo escuchaste. Nunca permitas que se incluya en ningún documento usado por tu compañía.

Si el software de terceros no es vaporware, aún es riesgoso, pero al menos es un riesgo que puede ser abordado. Si estás considerando usar software de terceros, deberías dedicar energía inicialmente a evaluarlo. A la gente podría no gustarle el escuchar que tomará dos semanas o dos meses evaluar cada uno de los tres productos por la conveniencia, pero tiene que hacerse tan pronto como sea posible. El costo de integrar no puede ser exactamente estimado sin una apropiada evaluación.

Comprender la conveniencia de software de terceras partes para un propósito particular es conocimiento muy tribal. Es muy subjetivo y generalmente radica en los expertos. Puede ahorrarte mucho tiempo si puedes hallar esos expertos. A menudo muchas veces un proyecto dependerá de un sistema de software de una tercera parte de una forma tan completa que si la integración falla el proyecto fallará. Expresa los riesgos como ése claramente al incluirlos en el cronograma. Trata de tener un plan de contingencia, tal como otro sistema que pueda ser usado o la capacidad de escribir la funcionalidad tú mismo si el riesgo no puede ser removido antes. Nunca dejes que un cronograma dependa del vaporware.

Cómo Manejar Consultores

Usa consultores, pero no confíes en ellos. Son gente maravillosa y merecen una gran cantidad de respeto. Puesto que tienen que ver muchos proyectos diferentes, a menudo saben más sobre tecnologías específicas e incluso de técnicas de programación de lo que tu sabrás. La mejor manera de usarlos es como educadores a domicilio que puedan enseñar mediante el ejemplo.

Sin embargo, usualmente no pueden volverse parte del equipo en el mismo sentido que lo son los empleados regulares, aunque sea solo porque no puedes tener el tiempo suficiente como para conocer sus fortalezas y sus debilidades. Su compromiso financiero es mucho menor. Pueden moverse más fácilmente. Pueden tener menos que ganar si la compañía lo hace bien. Algunos serán buenos, algunos promedio, y algunos

serán malos, pero es de esperar tu selección de consultores no será tan cuidadosa como tu selección de empleados, de tal forma que obtendrás más malos.

Si lo consultores van a escribir código, debes revisarlo cuidadosamente a medida que avanzas. No puedes llegar al final de un proyecto con el riesgo de un gran bloque de código que no ha sido revisado. Esto es cierto para todos los miembros del equipo, en realidad, pero usualmente tendrás más conocimiento de los miembros del equipo más cercanos a ti.

Cómo Comunicar la Cantidad Adecuada

Considera cuidadosamente el costo de una junta; cuesta su duración multiplicada por el número de participantes. Las juntas son algunas veces necesarias, pero las más pequeñas son usualmente las mejores. La calidad de la comunicación en pequeñas juntas es mejor, y el total de tiempo desperdiciado es menor. Si alguna persona está aburrida en la junta toma eso como una señal, que la junta debería ser más pequeña.

Debería hacerse todo lo posible para fomentar la comunicación informal. El trabajo más útil se realiza durante los almuerzos con colegas que durante cualquier otro tiempo. Es una lástima que la mayoría de las compañías no reconozcan ni apoyen este hecho.

Cómo Disentir Honestamente y Sobrellevarlo

El desacuerdo es una gran oportunidad para hacer una buena decisión, pero debería ser manejada con delicadeza. Con mucha esperanza sientes que has expresado tu opinión adecuadamente y han sido escuchadas antes de que la decisión sea hecha. En ese caso no hay nada más que decir, y deberías decidir si aceptarás la decisión aunque no concuerdes con ella. Si puedes apoya esta decisión aunque no concuerdes con ella, dilo así. Eso demuestra cuán valioso eres porque eres independiente y no eres un hombre "sí señor", sino respetuoso de la decisión y un jugador de equipo.

A veces una decisión con la que no concuerdas será hecha cuando los tomadores de decisión no tuvieron el total beneficio de tu opinión. Deberías entonces evaluar si debes replantear el asunto sobre las bases del beneficio para la compañía o para la tribu. Si en tu opinión es un pequeño error, podría no valer la pena reconsiderar. Si en tu opinión es una gran error, entonces por supuesto debes presentar un argumento.

Usualmente, esto no es un problema. En algunas circunstancias estresantes con algunos tipos de personalidad esto puede conducir a que las cosas sean tomadas personalmente. Por ejemplo, algunos muy buenos programadores carecen de la confianza necesaria para desafiar una decisión aún cuando tienen buenas razones para creer que es errada. En la peor de las circunstancias el tomador de decisiones está inseguro y lo toma como un desafío personal a su autoridad. Es mejor recordar que en tales circunstancias la gente reacciona con la parte reptílea de sus cerebros. Deberías presentar tu argumento en privado, e intentar mostrar cómo el nuevo conocimiento cambia las bases sobre las cuales se tomó la decisión.

Sin importar si la decisión se revierta o no, debes recordar que tu nunca deberás decir '¡Te lo dije!' puesto que la decisión alternativa fue completamente explorada.

Juicio

Cómo Negociar Calidad Frente a Tiempo de Desarrollo

El desarrollo de software es siempre un compromiso entre lo que el proyecto hace y conseguir el proyecto hecho. Pero puede que se te pida bajar el nivel de calidad a fin de acelerar la implantación de un proyecto en una forma que ofenda tu sensibilidades ingenieriles o de negocios. Por ejemplo, puede que se te pida hacer algo que sea una práctica pobre de ingeniería de software y que conducirá a un montón de problemas de mantenimiento.

Si esto sucede tu primer responsabilidad es informar a tu equipo y claramente explicar el costo de la disminución de la calidad. Después de todo, tu comprensión de ello debería ser mucho mejor que la comprensión de tu jefe. Aclara lo que se está perdiendo y lo que se está ganando, y a qué costo el terreno perdido será recobrado en el próximo ciclo. En esto, la visibilidad proporcionada por un buen plan de proyecto debería ser útil. Si el trueque de la calidad por otra cosa afecta el esfuerzo de aseguramiento de la calidad, señala eso (tanto a tu jefe como a la gente de aseguramiento de la calidad). Si el trueque de calidad conducirá a que se reporten más bugs después del periodo de aseguramiento de la calidad, señala eso también.

Si él o ella insiste deberías intentar aislar la mala calidad en componentes individuales que puedas planear reescribir o mejorar en el próximo ciclo. Explica esto a tu equipo para que así puedan planearlo.

NinjaProgrammer en Slashdot envió esta gema:

Recuerda que un buen diseño será flexible frente a implementaciones de código pobre. Si existen buenas interfaces y abstracciones a través del código, entonces las reescrituras eventuales serán mucho menos dolorosas. Si es difícil escribir código claro que sea difícil de corregir, considera lo que está errado con el núcleo del diseño que está causando esto.

Cómo Manejar la Dependencia del Sistema de Software

Los sistemas modernos de software tienden a depender de un gran número de componentes que pueden no estar directamente bajo tu control. Esto incrementa la productividad a través de la sinergía y la reutilización. Sin embargo, cada componente trae consigo algunos problemas:

¿Cómo corregirás los bugs en el componente? ¿Te restringe el componente a sistemas de hardware o software particulares? ¿Qué harás si el componente falla completamente?

Siempre es mejor encapsular el componente de alguna manera de tal forma que esté aislado y de tal manera que pueda ser reemplazado. Si el componente prueba ser completamente inoperable, puede que tengas que conseguir uno diferente, pero puede que tengas que escribir el tuyo propio. La encapsulación no es portabilidad, pero la hace más fácil, lo cual es casi tan bueno.

Tener el código fuente de un componente decrementa el riesgo por un factor de cuatro. Con el código fuente, puedes evaluarlo más fácilmente, depurarlo más fácilmente, hallar formas de corregir los problemas más fácilmente, y hacer correcciones más fácilmente. Si haces correcciones , deberías dárselas al propietario del componente y obtener las correcciones incorporadas en una versión oficial; de otro modo tendrás que mantener incómodamente una versión no oficial.

Cómo Decidir si el Software es Muy Inmaduro

Usar el software que otra persona escribió es uno de las más efectivas formas de construir rápidamente un sistema sólido. Debería no ser desalentado, pero los riesgos asociados con ello deben ser examinados. Uno de los más grandes riesgos es el periodo de bugginess y la cercana inoperabilidad que a menudo está asociada con el software antes de que madure, a través del uso, en un producto utilizable. Antes de que consideres integrar con un sistema de software, sin importar si se creó en casa o por una tercera parte, es muy importante considerar si en realidad es lo suficientemente maduro para ser usado. Aquí están diez preguntas que deberías hacerte a ti mismo al respecto:

1. ¿Es vaporware? (Las promesas son muy inmaduras).2. ¿Hay un cuerpo de ciencia accesible acerca del software?3. ¿Eres el primer usuario?4. ¿Hay un fuerte incentivo para su continuación?5. ¿Ha tenido un esfuerzo de mantenimiento?6. ¿Sobrevirá la deserción de los actuales mantenedores?7. ¿Hay una alternativa madura al menos la mitad de buena?8. ¿Es conocido para tu tribu o compañía?9. ¿Es deseable para tu tribu o compañía?10. ¿Puedes contratar gente para trabajar en él aún si es malo?

Un poco de consideración sobre esos criterios demuestran el gran valor del software libre bien establecido y del software de fuente abierta al reducir riesgos para el emprendedor.

Cómo Hacer una Decisión de Compra vs. Construcción

Una compañía emprendedora o proyecto emprendedor que está intentando hacer algo con software tiene que hacer constantemente las llamadas decisiones de compra vs. construcción. Este juego de palabras es desafortunado por dos cosas: parece ignorar el software de fuente abierta y el software libre el cual no es necesariamente comprado. Aún más importante, debería quizá ser llamado una decisión deobtener e integrar vs. construir aquí e integrar debido a que el costo de la integración debe ser considerado. Esto requiere una gran combinación de negocios, administración, y engineering savvy.

¿Qué tan bien satisface las necesidades para las cuales fue diseñado? ¿Qué porción de lo que compres necesitarás? ¿Cuál es el costo de evaluar la integración? ¿Cuál es el costo de la integración? ¿Comprar incrementará o decrementará a largo plazo los costos de

mantenimiento? ¿Construirlo te pondrá en una posición de negocios en la que no quieres estar?

Deberías pensar dos veces antes de construir algo que sea lo suficientemente grande como para servir de base para otro negocio completo. Tales ideas son a menudo propuestas por gente brillante y optimista que tendrá mucho que contribuir a tu equipo. Si su idea es obligatoria, puede que desees cambiar tu plan de negocios; pero no investigues una solución más grande que tu propio negocio sin un análisis consciente.

Después de considerar esas preguntas, deberías quizá preparar dos borradores de planes de proyecto, uno para construir y otro para comprar. Eso te forzará a considerar los costos de integración. Deberías también considerar los costos de mantenimiento a largo plazo de ambas soluciones. Para estimar los costos de integración, tendrás que hacer una evaluación completa del software antes de que lo compres. Si no puedes evaluarlo, asumirás un riesgo irrazonable al comprarlo y deberías decidir contra comprar ese producto particular. Si hay varias decisiones de compra bajo consideración, tendrá que invertirse alguna energía en evaluar cada una de ellas.

Cómo Crecer Profesionalmente

Asume responsabilidad encima de tu autoridad. Juega el rol que deseas. Expresa aprecio por la contribución de la gente para el éxito de la organización, al igual que a las cosas como las que te ayudan personalmente.

Si quieres convertirte en un líder de equipo, instiga la formación de consenso. Si quieres convertirte en un administrador, toma responsabilidad por el cronograma. Usualmente puedes hacer esto cómodamente mientras trabajas con un líder o un administrador, puesto que ello les libera de tomar una responsabilidad más grande. Si eso es demasiado para probar, hazlo un poco a la vez.

Evalúate tu mismo. Si quieres convertirte en un mejor programador, pregúntale a alguien que admiras cómo puedes convertirte en alguien como él. Puedes también preguntarle a tu jefe, quien sabrá menos pero tendrá un impacto más grande sobre tu carrera.

Planea formas de aprender nuevas habilidades, tanto del tipo trivial técnico, como aprender un nuevo sistema de software, y el tipo trivial difícil, como escribir bien, integrándolas en tu trabajo.

Cómo Evaluar Entrevistados

A la evaluación de empleados potenciales no se le da la energía que merece. Una mala contratación, como un mal matrimonio, es terrible. Una porción significativa de la energía de todos debería dedicarse al reclutamiento, aunque esto se hace raramente.

Hay diferentes estilos de entrevista. Algunas son tortuosas, diseñadas para poner al candidato bajo una gran carga de estrés. Esto sirve al muy valioso propósito de revelar posiblemente las fallas de carácter y las debilidades bajo estrés. Los candidatos no son más honestos con los entrevistadores de lo que lo son con ellos mismos, y la capacidad humana para auto decepción es asombrosa.

Deberías, como mínimo, dar al candidato el equivalente de un examen oral sobre las habilidades técnicas por dos horas. Con práctica, serás capaz de cubrir rápidamente lo que ellos saben y rápidamente retractarse de lo que no saben para marcar la frontera. Los entrevistados respetarán esto. He escuchado varias veces a entrevistados que dicen que la calidad del examen fue una de sus motivaciones para escoger una compañía. La gente buena quiere ser contratada por sus habilidades, no por dónde trabajaron por última vez o a qué escuela fueron o algunas características no esenciales.

Al hacer esto, deberías también evaluar su capacidad para aprender, la cual es mucho más importante de lo que ello saben. Deberías también observar las bocanadas de

azufre que da la gente difícil. Puedes ser capaz de reconocerlo al comparar notas después de la entrevista, pero al calor de la entrevista es difícil reconocer. Qué tan bien se comunica la gente y trabaja con la gente es más importante que estar capacitado en el último de los lenguajes de programación.

Un lector ha tenido buena suerte usando una prueba 'para llevar a casa' para los entrevistados. Esto tiene la ventaja de que puede descubrir a los entrevistados que pueden presentarse bien a sí mismos pero que no pueden realmente codificar---y hay mucha gente como esa. Personalmente no he probado esta técnica, pero suena sensible.

Finalmente, entrevistar es también un proceso de venta. Deberías estar vendiendo tu compañía o proyecto al candidato. Sin embargo, estás hablando con un programador, así que no trates de colorear la verdad. Empieza con lo malo, luego finaliza fuerte con lo bueno.

Cómo Saber Cuándo Aplicar Ciencia Computacional Fantasiosa

Hay una base de conocimientos sobre algoritmos, estructuras de datos, matemáticas, y otras carajos tópicos sobre la que la mayoría de los programadores saben pero que raramente usan. En la práctica, este maravilloso material es muy complicado y generalmente innecesario. No hay punto en mejorar un algoritmo cuando la mayoría de tu tiempo se invierte en hacer ineficientes llamadas a bases de datos, por ejemplo. Una cantidad desafortunada de programación consiste en obtener sistemas para hablar a cada uno de los otros y usar estructuras de datos muy simples para construir una interface de usuario agradable.

¿Cuándo es la alta tecnología la tecnología apropiada? ¿Cuándo deberías abrir un libro para obtener algo distinto a un algoritmo de batalla? A veces es útil hacer esto pero debería ser evaluado cuidadosamente.

Las tres consideraciones más importantes para la técnica de la ciencia computacional potencial son:

¿Está bien encapsulado de tal manera que el riesgo para otros sistemas es bajo y el incremento general en complejidad y costo de mantenimiento es bajo?

¿Es el beneficio sorprendente (por ejemplo, un factor de dos en un sistema maduro o un factor de diez en un nuevo sistema)?

¿Serás capaz de probarlo y evaluarlo efectivamente?

Si un algoritmo bien aislado que usa un algoritmo ligeramente fantasioso puede decrementar el costo del hardware o incrementar el desempeño por un factor de dos a través de un sistema completo, entonces sería criminal no considerarlo. Una de las claves para argumentar por tal aproximación es mostrar que el riesgo es realmente muy bajo, puesto que la tecnología propuesta ha sido probablemente bien estudiada, el único punto importante es el riesgo de la integración. Aquí la experiencia y el juicio de un programador pueden verdaderamente sinergizarse con la tecnología fantasiosa para hacer la integración fácil.

Cómo Hablar con No Ingenieros

Los ingenieros y los programadores en particular son generalmente reconocidos por la cultura popular por ser diferentes de las otras personas. Esto implica que las otras

personas son diferentes de nosotros. Vale la pena tener esto en mente cuando te comuniques con no ingenieros; deberías siempre comprender a la audiencia.

Los no ingenieros son inteligentes, pero no son tan aterrizados en crear cosas técnicas como nosotros. Nosotros hacemos cosas. Ellos venden cosas y manejan cosas y cuentan cosas y administran cosas, pero no son expertos en hacer cosas. Ello no son tan buenos en el trabajo en equipos como los son los ingenieros (sin duda hay excepciones.)[3] Sus habilidades sociales son generalmente tan buenas o mejores que la de los ingenieros en ambientes donde no hay equipos, pero su trabajo no siempre demanda que practiquen el tipo de intimidad, comunicación precisa y las cuidadosas subdivisiones de tareas que nosotros hacemos.

Los no ingenieros pueden ser demasiado dados a agradar y pueden ser intimidados por ti. Al igual que nosotros, ellos pueden decir 'si' sin realmente querer decirlo a fin de agradarte o porque están un poco asustados por tu causa, y luego no respaldar su palabra.

Los no programadores pueden comprender cosas técnicas pero no tienen lo que incluso es difícil para nosotros ---el juicio técnico. Ellos comprenden cómo funciona la tecnología, pero no pueden entender por qué cierto acercamiento tomaría tres meses y otro tres días. (Después de todo, los programadores son también anecdóticamente horribles en este tipo de estimación.) Esto representa una gran oportunidad para sinergizarse con ellos.

Cuando le hablas a tu equipo usarás, sin pensarlo, una suerte de taquigrafía, un lenguaje abreviado que es efectivo debido a que tendrás mucha experiencia compartida sobre la tecnología en general y tu producto en particular. Requiere algo de esfuerzo no usar este vocabulario con los que no tienen esa experiencia compartida, especialmente cuando los miembros de tu equipo están presentes. Este vocabulario crea una pared entre tú y los que no la comparten, y, peor aún, desperdicia su tiempo.

Con tu equipo, las suposiciones básicas y metas no necesitan ser restablecidas a menudo, y la mayoría de la conversación se enfoca en los detalles. Con los foráneos, debe ser del otro modo. Ellos pueden no comprender cosas que das por entendidas. Puesto que las das por entendidas y no las repites, puedes dejar una conversación con un foráneo pensando que comprendiste a los demás cuando realmente hay una gran incomprensión. Deberías asumir que te comunicarás mal y vigilar cuidadosamente para encontrar esta mala comunicación. Intenta resumirlas o parafrasear lo que estás diciendo para asegurarte de que comprenden. Si tienes la oportunidad de reunirte con ellos a menudo, invierte un poco de tiempo preguntando si te estás comunicando efectivamente, y cómo puedes hacerlo mejor. Si hay un problema en la comunicación, busca alterar tus propias prácticas antes de frustrarte con las suyas.

Adoro trabajar con no ingenieros. Proporciona grandes oportunidades para aprender y enseñar. A menudo puedes guiar mediante el ejemplo, en términos de la claridad de tu comunicación. Los ingenieros están entrenados para poner orden al caos, para traer claridad a la confusión, y a los no ingenieros les agrada eso de nosotros. Debido a que tenemos juicio técnico y usualmente podemos comprender tópicos de negocios, a menudo podemos encontrar una solución simple a un problema.

A menudo los no ingenieros proponen soluciones que piensan nos facilitarán las cosas sin bondades y por un deseo de hacer lo correcto, cuando de hecho existe una solución general mucho mejor la cual solamente puede verse sinergizando las visiones de los foráneos con tu juicio técnico. Personalmente me gusta la Programación Extrema

porque resuelve esta ineficiencia; casando la estimación rápidamente a la idea, hace más fácil hallar la idea que sea la mejor combinación de costo y beneficio.

[1] “to hit”

Capítulo 4. Avanzado

Tabla de Contenido

Juicio TecnológicoCómo Diferenciar lo Difícil de lo ImposibleCómo Utilizar Lenguajes EmbebidosEscogiendo Lenguajes

Comprometiéndote SabiamenteCómo Combatir Presión de CalendarioCómo Comprender al UsuarioCómo Obtener una Promoción

Sirviendo a Tu EquipoCómo Desarrollar TalentoCómo Elegir Sobre Qué TrabajarCómo Obtener lo Máximo de Tus Compañeros de EquipoCómo Dividir ProblemasCómo Manejar las Tareas AburridasCómo Conseguir Apoyo para un ProyectoCómo Hacer Crecer un SistemaCómo Comunicar BienCómo Decirle a la Gente Cosas que No Desean EscucharCómo Lidiar con Mitos AdministrativosCómo Lidiar con el Caos Organizacional

Juicio Tecnológico

Cómo Diferenciar lo Difícil de lo Imposible

Es nuestro trabajo hacer lo difícil y discernir lo imposible. Desde el punto de vista de la mayoría de los programadores activos, algo es imposible si no puede ser desarrollado a partir de un sistema simple o no puede ser estimado. Mediante esta definición lo que se denomina investigación es imposible. Un gran volumen de mero trabajo es difícil, pero no necesariamente imposible.

La distinción no es jocosa debido a que se te puede pedir muy bien hacer lo que es prácticamente imposible, ya sea desde un punto de vista científico o desde un punto de vista de la ingeniería de software. Luego se vuelve tu trabajo ayudar al emprendedor a encontrar una solución razonable la cual es meramente difícil y que sea más de lo que querían. Una solución es meramente difícil cuando puede ser confidencialmente calendarizada y son comprendidos los riesgos.

Si es imposible satisfacer un requerimiento vago, tal como 'Construye un sistema que computará el más atractivo estilo y color de cabello para cualquier persona.' Si el requerimiento puede hacerse más expresivo, se volverá a menudo meramente difícil, tal como 'Construye un sistema para computar un estilo y color atractivo de cabello para una persona, permitiéndoles previsualizarlo y hacer cambios, y tener la

satisfacción del cliente basado en que el estilo original sea tan grandioso que hagamos mucho dinero.' Si no hay una definición expresiva, no tendrás éxito.

Cómo Utilizar Lenguajes Embebidos

incrustar un lenguaje de programación dentro de un sistema tiene una fascinación casi erótica para un programador. Es uno de los más creativos actos que pueden ser realizados. Hace al sistema tremendamente poderoso. Te permite ejercitar tus habilidades más creativas y prometeas. Convierte al sistema en tu amigo.

Todos los mejores editores de texto del mundo tienen lenguajes embebidos. Este puede ser usado hasta el punto que la audiencia pretendida pueda dominar el lenguaje. Por supuesto, el uso del lenguaje puede ser opcional, como lo es en los editores de texto, de tal manera que los iniciados puedan usarlo y nadie más tenga que hacerlo.

Yo y muchos otros programadores hemos caído en la trampa de crear lenguajes embebidos de propósito general. Caí en ello dos veces. Ya existen muchos lenguajes diseñados específicamente para ser lenguajes embebidos. Deberías pensarlo dos veces antes de crear uno nuevo.

La verdadera pregunta que uno debe hacerse a sí mismo antes de incrustar un lenguaje es: ¿Funciona esto con o en contra de la cultura de mi audiencia? Si tu audiencia pretendida es exclusivamente no programadores, ¿cómo ayudará? Si tu audiencia pretendida es exclusivamente programadores, ¿preferirían ellos una interface de programación de aplicaciones (API)? ¿Y qué lenguaje será? Los programadores no desean aprender un nuevo lenguaje que sea estrechamente usado; pero si encaja con su cultura no tendrán que invertir mucho tiempo en aprenderlo. Es una broma crear un nuevo lenguaje. Pero no deberíamos permitir que nos cieguen las necesidades del usuario. A menos que tengas algunas necesidades e ideas verdaderamente originales, ¿por qué no usar un lenguaje existente de tal manera que puedas aprovechar la familiaridad que los usuarios ya tienen con él?

Escogiendo Lenguajes

El programador solitario que ama su trabajo (un hacker) puede elegir el mejor lenguaje para la tarea. La mayoría de los programadores activos tienen muy poco control del lenguaje que usarán. Generalmente, este punto es dictado por jefes encopetados quienes están haciendo una decisión política, en lugar de una decisión tecnológica, y carecen del coraje para promover una herramienta no convencional aún cuando saben, a menudo con conocimiento de primera mano, que la herramienta menos aceptada es la mejor. En otros casos el verdadero beneficio de la unidad entre el equipo, y en alguna extensión con una comunidad más grande, excluye la elección por parte del individuo. A menudo los administradores se conducen por la necesidad de ser capaces de contratar programadores con experiencia en un lenguaje dado. Sin duda están sirviendo a lo que ellos perciben como el mejor interés del proyecto o la compañía, y deben ser respetados por eso. Sin embargo, personalmente creo que esto es el mayor desperdicio y la práctica errónea más común con la que probablemente te encuentres.

Pero por supuesto, las cosas no son nunca unidimensionales. Incluso si se ordena usar un lenguaje central y está más allá de tu control, a menudo es el caso que las herramientas y otros programas pueden y deberían ser escritos en un lenguaje diferente. Si un lenguaje debe ser incrustado (¡y deberías siempre considerarlo!) la escogencia del lenguaje dependerá mucho de la cultura de los usuarios. Uno debería

tomar ventaja de esto para servir a tu compañía o proyecto mediante el uso del mejor lenguaje para el trabajo, y al hacerlo así haces el trabajo más interesante.

Los lenguajes de programación deberían ser llamados en realidad notaciones en el sentido que aprender uno no es del todo tan difícil como aprender un lenguaje natural. Para los principiantes y para algunos foráneos "aprender un nuevo lenguaje'' parece una tarea dantesca; pero después de que tienes tres bajo tu faja es realmente sólo cuestión de familiarizarse con las bibliotecas disponibles. Uno tiende a pensar de un gran sistema que tiene componentes en tres o cuatro lenguajes como una mezcolanza desordenada; pero yo argumento que tal sistema es en muchos casos más fuerte que un sistema hecho en un único lenguaje de varias formas:

Hay necesariamente un débil acoplamiento entre los componentes que están escritos en diferentes notaciones (aunque quizá sin interfaces limpias),

Puedes evolucionar a un nuevo lenguaje o plataforma fácilmente al reescribir cada componente de manera individual,

Es posible que alguno de los módulos esté realmente actualizado.

Algunos de esos efectos pueden ser solamente sicológicos; pero la sicología importa. Al final los costos de la tiranía del lenguaje sobrepasan cualquier ventaja que provea.

Comprometiéndote Sabiamente

Cómo Combatir Presión de Calendario

La presión de tiempo de mercadeo es la presión para entregar un buen producto rápidamente. Es bueno debido a que refleja una realidad financiera, y es saludable hasta cierto punto. La presión de tiempo de mercadeo es la presión para entregar algo más rápido de lo que puede ser entregado y es pródigo, insalubre, y muy común.

La presión del cronograma existe por varias razones. La gente que trabaja con programadores no aprecia completamente la fuerte ética de trabajo que tenemos y cuán divertido es ser un programador. Quizá debido a que proyectan su propio comportamiento en nosotros, creen que pidiéndolo más pronto nos hará trabajar más duro para tenerlo ahí más pronto. Esto en realidad sea probablemente cierto, pero el efecto es muy pequeño, y el daño muy grande. Por lo demás, no tienen visibilidad de lo que realmente se requiere para producir software. No son capaces de verlo, y no son capaces de crearlo ellos mismos, la única cosa que pueden hacer es ver la presión de tiempo de mercadeo y molestar a los programadores por ello.

La clave para combatir la presión del calendario es simplemente convertirla en presión de tiempo de mercadeo. La manera de hacer esto es dar visibilidad dentro de la relación entre el trabajo disponible y el producto. Producir un estimado honesto, detallado, y sobre todo, comprensible de todo el trabajo involucrado es la mejor forma de hacer esto. Tiene la ventaja agregada de permitir que las buenas decisiones de administración sean tomadas sobre posibles negociaciones de funcionalidades.

El conocimiento clave que el estimado debe hacer claro es que el trabajo es un fluido casi incomprensible. No puedes empaquetar más en una medida de tiempo más de lo que podrías empaquetar más agua en un contenedor por encima de la capacidad del volumen de ese contenedor. En un sentido, un programador nunca debería decir 'no', sino más bien decir '¿Qué cederás para obtener lo que quieres?' El efecto de producir estimados claros será incrementar el respeto por los programadores. Así es como otros profesionales se comportan. El trabajo duro de los programadores será visible.

Establecer un cronograma no realista será también doloroso para todos. Los programadores no pueden ser burlados. Es irrespetuoso y desmoralizador pedirles que hagan algo poco realista. La Programación Extrema amplifica esto y construye un proceso alrededor de ello; Espero que cada lector será lo suficientemente afortunado para usarlo.

Cómo Comprender al Usuario

Es tu deber comprender al usuario, y ayudar a tu jefe a comprender al usuario. Debido a que el usuario no está tan íntimamente involucrado en la creación de tu producto como lo estás tú, se comportan de manera un poco diferente:

El usuario generalmente hace pronunciamientos cortos. El usuario tiene su propio trabajo; pensarán principalmente en pequeñas

mejoras de tu producto, no en grandes mejoras. El usuario no puede tener una visión que represente a todo el cuerpo completo

de los usuarios de tu producto.

Es tu deber darles lo que realmente quieren y no lo que ellos dicen que quieren. Sin embargo, es mejor proponérselo a ellos y lograr que concuerden en que tu propuesta es lo que realmente quieren antes de que comiences, pero puede que ellos no tengan la visión para hacer esto. Tu confianza en tus propias ideas sobre esto debería variar. Debes cuidarte tanto de la arrogancia como de la falsa modestia en términos de saber lo que realmente quiere el cliente. Los programadores están entrenados para diseñar y crear. Los investigadores de mercado están entrenados para determinar lo que la gente quiere. Esos dos tipos de personas, o dos modos de pensar en la misma persona, trabajando armoniosamente juntos dan la mejor oportunidad para formular la visión correcta.

Entre más tiempo pases con los usuarios estarás en mejor capacidad para comprender lo que en realidad será exitoso. Deberías probar tus ideas frente a ellos tanto como puedas. Deberías comer y beber con ellos si puedes.

Guy Kawasaki [Rules] ha enfatizado la importancia de observar lo que tus usuarios hacen además de escucharlos.

Creo que los contratistas y consultores a menudo tienen tremendos problemas para lograr que sus clientes clarifiquen en sus propias mentes lo que realmente quieren. Si intentas ser un consultor, te sugiero elegir a tus clientes basado en su claridad mental tanto como por sus billeteras.

Cómo Obtener una Promoción

Para ser promovido a un rol, primero interpreta ese rol.

Para ser promovido a un título, determina lo que se espera de ese título y haz eso.

Para obtener un aumento de sueldo, negocia armado de información.

Si sientes como que estás pasado para una promoción, habla con tu jefe acerca de ello. Pregúntale explícitamente qué necesitas hacer para ser promovido, e intenta hacerlo. Esto suena triste, pero muy a menudo tu percepción de lo que necesitas hacer diferirá

considerablemente de la de tu jefe. Esto también prenderá a tu jefe a ti de alguna manera.

La mayoría de los programadores probablemente tienen de alguna forma un exagerado sentido de sus capacidades relativas ---después de todo, ¡no podemos estar todos en el top 10%! Sin embargo, he visto algunas personas que fueron seriamente inapreciadas. Uno no puede esperar que la evaluación de todos coincida perfectamente con la realidad todas las veces, pero pienso que las personas son en general moderadamente justas, con una advertencia: no puedes ser apreciado sin visibilidad en tu trabajo. A veces, hacer to happenstance o por hábitos personales, alguien no será notado mucho. Trabajar mucho en casa o estando geográficamente separado de tu equipo y de tu jefe hace esto especialmente difícil.

Sirviendo a Tu Equipo

Cómo Desarrollar Talento

Nietschze exageró cuando dijo [Stronger]:

Lo que no me destruye, me hace más fuerte.

Tu más grande responsabilidad es hacia tu equipo. Deberías conocer bien a cada uno de ellos. Deberías esforzar a tu equipo, pero no sobrecargarlos. Usualmente deberías hablar con ellos sobre la forma en que están siendo esforzados. Si ellos han comprado la idea, estarán bien motivados. En cada proyecto, o en cada otro proyecto, trata de esforzarlos tanto de una forma que ellos sugieran como de una que pienses que será buena para ellos. Esfuérzalos no dándoles más trabajo, sino dándoles una nueva habilidad o mejor aún un nuevo rol que jugar dentro del equipo.

Deberías permitir que la gente (incluyéndote a ti mismo) falle ocasionalmente y deberías planear alguna falla en tu calendario. Si no hay ninguna falla, no puede haber sentido de la aventura. Si no hay fallas ocasionales, no estás intentándolo lo suficiente. Cuando alguien falla, deberías ser tan gentil como puedas con ellos aunque cuida de no tratarlos como si hubieses tenido éxito.

Intenta conseguir que cada miembro del equipo compre la idea y esté bien motivado. Pregúntale a cada uno de ellos explícitamente lo que necesitan para estar bien motivados si no lo están. Puede que tengas que dejarlos insatisfechos, pero deberías saber qué desean todos.

No puedes rendirte con alguien que no está llevando intencionalmente su parte de la carga debido a una baja moral o insatisfacción y sólo dejarlos que sean negligentes o estén inactivos o flojos. Debes intentar tenerlos a todos bien motivados y productivos. Mientras tengas la paciencia, mantén esto. Cuando tu paciencia se agote, despídelos. No puedes permitir que alguien que está intencionalmente trabajando por debajo de su nivel permanezca en el equipo, puesto que no es justo para el equipo.

Haz claro a los miembros fuertes de tu equipo que piensas que ellos son fuertes diciéndolo en público. Las alabanzas deberían ser públicas y las críticas en privado.

Los miembros fuertes del equipo tendrán naturalmente tareas más difíciles que los miembros débiles del equipo. Esto es perfectamente natural y nadie estará molesto por ello mientras todos trabajen duro.

Es un hecho real que no se refleja en los salarios que un buen programador es más productivo que 10 malos programadores. Esto crea una extraña situación. A menudo será cierto que podrías moverte más rápido si tus programadores débiles se apartaran del camino. Si hicieras eso harías de hecho más progreso a corto plazo. Sin embargo, tu tribu perdería algunos beneficios importantes, por ejemplo el entrenamiento de los miembros débiles, la diseminación del conocimiento tribal, y la capacidad para recuperarte de la pérdida de miembros fuertes. El fuerte debe ser gentil en este aspecto y considerar el punto desde todos los ángulos.

A menudo puedes dar a los miembros más fuertes del equipo tareas desafiantes, pero cuidadosamente delineadas.

Cómo Elegir Sobre Qué Trabajar

Tú balanceas tus necesidades personales frente a las necesidades del equipo al escoger sobre cuál aspecto de un proyecto trabajar. Deberías hacerlo en lo que eres mejor, pero trata de encontrar una forma de esforzarte a ti mismo no por tomar más trabajo sino mediante el ejercicio de una nueva habilidad. Las habilidades de liderazgo y comunicación son más importantes que las habilidades técnicas. Si eres muy fuerte, toma las tareas más difíciles o riesgosas, y hazlas tan pronto como sea posible en el proyecto para decrementar el riesgo.

Cómo Obtener lo Máximo de Tus Compañeros de Equipo

Para obtener lo mejor de tus compañeros de equipo, desarrolla un buen espíritu de equipo y trata de mantener a cada individuo tanto personalmente desafiado como personalmente comprometido.

Para desarrollar espíritu de equipo, el dar a granel cosas como las ropas con logotipos y las fiestas son buenas, pero no tan buenas como el respeto personal. Si todos respetamos a todos los demás, nadie querrá dejar a nadie bajo de ánimo. El espíritu de equipo se crea cuando la gente hace sacrificios por el equipo y piensa en términos del bienestar del equipo antes del propio bienestar personal. Como un líder, no puedes pedir más de lo que tú mismo puedes dar al respecto.

Una de las claves para el liderazgo de equipo es facilitar el consenso de manera tal que todos han comprado la idea. Esto ocasionalmente significa permitir a tus compañeros de equipo estar equivocados. O sea, si ello no daña demasiado al proyecto, debes permitir a parte de tu equipo hacer cosas a su propio modo, basado en el consenso, incluso si crees con gran confianza que es equivocado hacerlo. Cuando esto suceda, no estés en desacuerdo, simplemente disiente abiertamente y acepta el consenso. No suenes como si estuvieras herido, o como que estás siendo forzado a ello, simplemente establece que disientes pero que piensas que el consenso del equipo es más importante. Esto hará que a menudo se echen atrás. No insistas en que sigan con su plan inicial si se echan atrás.

Si hay un individuo que no consienta después de que has discutido los puntos desde todos los ángulos apropiados, simplemente afirma que tienes que tomar una decisión y cuál es tu decisión. Si hay una manera de juzgar si tu decisión estará equivocada o si luego demostrará estar equivocada, cambia tan rápidamente como puedas y reconoce a las personas que estuvieron en lo correcto.

Pregunta a tu equipo, tanto como grupo como de forma individual, qué piensan que crearía un espíritu de equipo y en qué consiste un equipo efectivo.

Elogia frecuentemente en lugar de hacerlo profusamente. Especialmente elogia a esos que disienten contigo cuando se lo merecen. El elogio en público y la crítica en privado; con una excepción: a veces la exaltación o la corrección de una falla no puede hacerse sin dirigir la atención a la embarazosa falla original, así que la exaltación debería ser elogiada en privado.

Cómo Dividir Problemas

Es divertido tomar un proyecto de software y dividirlo en tareas que serán llevadas a cabo por individuos. Esto debería hacerse en etapas tempranas. A los administradores a veces les gusta pensar que un estimado puede hacerse sin consideración hacia los individuos que realizarán el trabajo. Esto es imposible puesto que la productividad de los individuos varía muy ampliamente. El que tiene el conocimiento sobre un componente también cambia constantemente y puede tener un efecto de un orden de magnitud sobre el desempeño.

Al igual que un compositor considera el timbre del instrumento que tocará una nota musical o el coach de un equipo atlético considera la fortaleza de cada jugador, el líder de equipo experimentado usualmente no será capaz de separar la división del proyecto en tareas de los miembros del equipo a las cuales serán asignadas. Esta es parte de la razón por la que un equipo de alta ejecución no debería ser dividido.

Hay un cierto peligro en ello dado que la gente se aburrirá a medida que construyen sus fortalezas y nunca mejoran sus debilidades o aprenden otras nuevas. Sin embargo, la especialización es una muy útil herramienta de productividad cuando no es sobreutilizada.

Cómo Manejar las Tareas Aburridas

A veces no es posible evitar las tareas aburridas que son críticas para el éxito de la compañía o el proyecto. Esas tareas pueden en realidad dañar la moral de quienes tienen que hacerlas. La mejor técnica para lidiar con esto es invocar o promover la virtud de la Pereza del programador Larry Wall. Intenta hallar alguna forma de hacer que la computadora haga la tarea por ti o ayuda a tus compañeros de equipo a hacer esto. Trabajar una semana en un programa para hacer una tarea que tomará una semana hacerlo a mano tiene la gran ventaja de ser más educacional y a veces más repetible.

Si todo lo demás falla, pide disculpas a quienes tienen que hacer la tarea aburrida, pero bajo ninguna circunstancia les permitas hacerla solos. Como mínimo asigna un equipo de dos para hacer el trabajo y promueve el trabajo en equipo saludable para lograr tener la tarea hecha.

Cómo Conseguir Apoyo para un Proyecto

Para conseguir apoyo para un proyecto, crea y comunica una visión que demuestre el valor real a la organización como un todo. Intenta dejar que otros compartan la creación de tu visión. Esto les da una razón para apoyarte y te da el beneficio de sus ideas. Individualmente recluta personal de apoyo clave para tu proyecto. Siempre que sea posible, muestra, no cuentes. Si es posible, construye un prototipo o una maqueta para demostrar tus ideas. Un prototipo es siempre poderoso pero en software es muy superior a cualquier descripción escrita.

Cómo Hacer Crecer un Sistema

La semilla de un árbol contiene la idea del adulto pero no comunica completamente la forma y la potencia del adulto. El embrión crece. Se vuelve más grande. Se parece más al adulto y tiene la mayoría de las características. Eventualmente produce frutos. Más tarde, muere y su cuerpo alimenta a otros organismos.

Tenemos la lujuria de tratar igual al software. Un puente no es así; nunca hay un bebé puente, sino meramente un puente no finalizado. Los puentes son mucho más simples que el software.

Es bueno pensar en el software como algo en crecimiento, debido a que nos permite hacer un progreso útil antes de que tengamos una imagen mental perfecta. Podemos obtener retroalimentación de los usuarios y usar eso para corregir el crecimiento. Podar las hojas débiles es saludable.

El programador debe diseñar un sistema finalizado que pueda ser entregado y usado. Pero el programador avanzado debe hacer más. Debes diseñar una ruta de crecimiento que concluya en el sistema finalizado. Es tu trabajo tomar el germen de una idea y construir una ruta que la convierta tan suavemente como sea posible en un artefacto útil.

Para hacer esto, debes visualizar el resultado final y comunicarlo de una forma que el equipo de ingenieros pueda emocionarse. Pero también debes comunicarles una ruta que vaya de dondequiera que estén ahora hacia donde quieren estar sin grandes saltos. El árbol debe permanecer vivo todo el tiempo; no puede estar muerto en un punto y resucitar más tarde.

Este acercamiento es capturado en un desarrollo en espiral. Los hitos que nunca están demasiado alejados son usados para marcar el progreso a lo largo del camino. En el ambiente ultracompetitivo de los negocios, es mejor si los hitos pueden ser liberados y hacer dinero tan pronto como sea posible, incluso si están demasiado lejos de un punto final bien diseñado. Uno de los trabajos del programador es balancear el pago inmediato frente al futuro mediante la sabia elección de un camino de crecimiento expresado en hitos.

El programador avanzado tiene la triple responsabilidad de hacer crecer el software, los equipos, y a las personas.

Un lector, Rob Hafernik, envió este comentario sobre esta sección que no puedo menos que citarlo completo:

Pienso que subenfatizas la importancia aquí. No son sólo sistemas, sino algoritmos, interfaces de usuario, modelos de datos, y cosas así. Es absolutamente vital a medida que trabajas en un gran sistema tener progreso medible hacia metas intermedias. Nada es tan malo como el horror especial de llegar al final y descubrir que toda la cosa simplemente no va a funcionar (mira la reciente debacle del Sistema Voter News). Yo iría más allá y lo afirmaría como una ley de la naturaleza: ningún sistema grande y complejo puede ser implementado de la nada, puede solamente evolucionar de un sistema simple a uno complejo en una serie de pasos intencionales.A lo cual uno puede solamente replicar ¡Fiat lux!

Cómo Comunicar Bien

Para comunicarte bien, tienes que reconocer cuán difícil es. Es una habilidad en sí misma. Se hace más difícil por el hecho de que las personas con quien tienes que comunicarte son inperfectas. Ellas no trabajan duro en comprenderte. Hablan y escriben pobremente. Están a menudo sobretrabajadas o aburridas, y, como mínimo, algo enfocadas en su propio trabajo más que en los tópicos más grandes que puedes estar comentando. Una de las ventajas de tomar clases y practicar la escritura, el hablar en público, y escuchar es que si te vuelves bueno en ello puedes más fácilmente ver donde yacen los problemas y cómo corregirlos.

El programador es un animal social cuya sobrevivencia depende de la comunicación con su equipo. El programador avanzado es un animal social cuya satisfacción depende de la comunicación con gente fuera de su equipo.

El programador trae orden al caos. Una forma interesante de hacer esto es iniciar una propuesta de algún tipo fuera del equipo. Esto puede ser hecho en un formato strawman o en formato white-paper o sólo verbalmente. Este liderazgo tiene la tremenda ventaja de fijar los términos del debate. También te expone a críticas, y peor, al rechazo y al descuido. El programador avanzado debe estar preparado para aceptar esto, debido a que tiene un poder único y por lo tanto una responsabilidad única. Los emprendedores que no son programadores necesitan que los programadores aporten liderazgo de algunas maneras. Los programadores son la parte del puente entre las ideas y la realidad que descansa en la realidad.

No he dominado bien la comunicación, pero lo que estoy intentando actualmente es un método de cuatro pasos: Después de que tengo mis ideas en orden y estoy completamente preparado, trato de hablar verbalmente, doy a las personas un papel en blanco (sobre papel real, al igual que electrónicamente), les muestro un demo, y luego pacientemente repito este proceso. Pienso que muchas veces no somos lo suficientemente pacientes en este tipo de comunicación difícil. No deberías descorazonarte si tus ideas no son inmediatamente aceptadas. Si has invertido energía en su preparación, nadie pensará pobremente de ti por ello.

Cómo Decirle a la Gente Cosas que No Desean Escuchar

A menudo tendrás que decirle a la gente cosas que los hará sentir incómodos. Recuerda que estás haciendo esto por una razón. Aún si no puede hacerse nada por el problema, estás diciéndoles tan pronto como es posible de tal manera que estarán bien informados.

La mejor manera de decirle a alguien sobre un problema es ofrecerles a la vez una solución. La segunda mejor manera es apelar a ellos para que ayuden con el problema. Si existe el peligro de que no serás creído, deberías conseguir algún soporte para tu afirmación.

Una de las cosas más comunes e implacenteras que tendrás que decir es, 'El calendario tendrá que correrse.' El programador consciente odia decir eso, pero debe decirlo tan pronto como sea posible. No hay nada peor que posponer la acción cuando se corre un hito, incluso si la única acción es informar a todos. Al hacer esto, es mejor hacerlo como equipo, al menos en espíritu, si no puedes físicamente. Desearás la opinión de tu equipo tanto acerca de dónde están como sobre qué puede hacerse al respecto, y el equipo tendrá que enfrentar las consecuencias contigo.

Cómo Lidiar con Mitos Administrativos

La palabra mito algunas veces significa ficción. Pero tiene una connotación más profunda. También significa una historia de religiosa significancia que explica el universo y la relación de la humanidad con él. Los administradores tienden a olvidar lo que ellos aprendieron como programadores y creen en ciertos mitos. Sería tan rudo como exitoso tratar de convencerlos de que esos mitos son falsos como el tratar de desilusionar a una persona devotamente religiosa de sus creencias. Por esa razón, deberías reconocer estas creencias como mitos:

Más documentación es siempre mejor. (Ellos la requieren, pero no quieren que gastes tiempo en ella.)

Los programadores pueden ser equiparados. (Los programadores varían por un orden de magnitud.)

Los recursos pueden ser agregados a un proyecto retrasado para acelerarlo. (El costo de la comunicación con las nuevas personas es casi siempre más penalizador que útil.)

Es posible estimar la confiabilidad del desarrollo del software. (No es posible ni siquiera teóricamente.)

La productividad de los programadores puede ser medida en términos de alguna métrica simple, como las líneas de código. (Si la concisión es poder, las líneas de código son malas, no buenas.)

Si tienes oportunidad, puedes intentar explicar esas cosas, pero no te sientas mal si no tienes éxito y no dañes tu reputación confrontando esos mitos beligerantemente. Cada uno de esos mitos refuerza la idea del administrador de que tienen un control real sobre lo que está pasando. La verdad es que los administradores lo facilitan si son buenos, y lo impiden si son malos.

Cómo Lidiar con el Caos Organizacional

A menudo hay breves periodos de gran caos organizacional, tales como despidos, compras, IPOs, despidos, nuevas contrataciones, y cosas así. Son trastornantes para todos, pero quizá un poco menos para el programador cuya autoestima personal está basada en la capacidad más que en la posición. El caos organizacional es una gran oportunidad para que los programadores ejerciten su poder mágico. He guardado esto para el final porque es un profundo secreto tribal. Si no eres un programador, por favor deja de leer ahora.

Los ingenieros tienen el poder de crear y sostener.

Los no ingenieros pueden ordenar a la gente a su alrededor pero, en una compañía típica de software, no pueden crear ni sostener nada sin los ingenieros, al igual que los ingenieros típicamente no pueden vender un producto o administrar un negocio efectivamente. Este poder es a prueba de casi todos los problemas asociados con la mutilación organizacional temporal. Cuando lo tienes deberías ignorar el caos completamente y continuar como si nada estuviera pasando. Puedes, por supuesto, ser despedido, pero si eso pasa probablemente puedes conseguir un nuevo trabajo debido al poder mágico. Muy comúnmente, alguna persona estresada que no tiene el poder mágico vendrá a tu cubículo y te dirá algo estúpido. Si estás realmente seguro de que es estúpido, es mejor sonreír y asentir hasta que se vaya y luego continuar haciendo lo que sabes es lo mejor para la compañía.

Si eres un líder, dile a tu gente que haga lo mismo y diles que ignoren lo que los demás les digan. Este curso de acción es lo mejor para ti en lo personal, y es lo mejor para tu compañía o proyecto.

Glosario

Este es un glosario de términos usados en este ensayo. No tiene necesariamente un significado estandarizado para otras personas. Eric S. Raymond ha compilado un glosario masivo e informativo [HackerDict] que más que sorprendente puede ser placenteramente leído de tapa a tapa una vez que puedas apreciar una fracción de él.

unk-unk

Argot para unknown-unknown. Los problemas que en la actualidad no pueden ni siquiera ser conceptualizados que robarán tiempo del proyecto y destrozarán el calendario.

jefe

La persona o entidad que te da tareas. En algunos casos este puede ser a la larga el público. La persona que establece tus tareas. En algunos casos, el usuario es el jefe.

printlining

La inserción de sentencias en un programa en una base estrictamente temporal que arroje información acerca de la ejecución del programa para el propósito de la depuración.

logging

La práctica de escribir un programa de tal manera que pueda producir una bitácora de salida configurable describiendo su ejecución.

divide y vencerás

Una técnica de diseño top-down y, aún más importante, de depuración que consiste en la subdivisión de un problema o un misterio en problemas o misterios progresivamente más pequeños.

vaporware

Promesas de software ilusorias y a menudo decepcionantes que no están todavía a la venta y, tan a menudo como no, nunca se materializarán en algo sólido.

tribu

La gente con la que compartes tu lealtad hacia una meta común. Un grupo de personas con la que compartes afinidad cultural y lealtad.

frutas de cuelgue bajo

Grandes mejoras que cuestan poco.

Emprendedor

El iniciador de proyectos.

basura

Objetos que no se necesitan más que se mantienen en memoria. Memoria asignada que ya no tiene un significado útil.

negocio

Un grupo de personas organizadas para hacer dinero.

compañía

Un grupo de personas organizadas para hacer dinero.

ceguera de desplazamiento

El efecto de ser incapaz de encontrar la información que necesitas debido a que está sepultada en muchísima información menos interesante.

reloj de pared

El tiempo real como es medido por un reloj de pared, opuesto al tiempo de CPU.

cuello de botella

La más importante limitación en el desempeño de un sistema. Una constricción que limita el desempeño.

maestro

Una pieza única de información desde la cual se derivan todas las copias cacheadas que sirve como la definición oficial de esos datos.

heap asignado

Memoria de la que puede decirse que está asignada en el heap cuando el mecanismo para liberarla es complicado.

recolector de basura

Un sistema para reciclar basura.

fuga de memoria

La indeseada colección de referencias a objetos que evita la recolección de basura (¡o un error en el recolector de basura o en el sistema de administración de memoria!) que causa que el programa incremente gradualmente sus demandas de memoria en el tiempo.

Programación Extrema

Un estilo de programación que enfatiza la comunicación con el cliente y las pruebas automatizadas.

golpear la pared

Quedarse sin un recurso específico ocasionando que se degrade el desempeño abruptamente en lugar de hacerlo gradualmente.

programación especulativa

Producir una funcionalidad antes de que realmente se sepa si esa funcionalidad será útil.

ocultamiento de información

Un principio de diseño que busca mantener las cosas independientes y desacopladas mediante el uso de interfaces que exponen tan poca información como sea posible.

programación orientada a objetos

Un estilo de programación que enfatiza la administración del estado dentro de los objetos.

lenguajes de comunicación

Un lenguaje diseñado primariamente para la estandarización más que para la ejecución.

cajas y flechas

Un estilo flojo e informal de hacer diagramas que consiste de cajas y flechas dibujadas entre esas cajas para mostrar las relaciones. Esto contrasta con las metodologías formales de diagramación, tales como la del UML.

lingua franca

Un lenguaje tan popular como para el estándar de facto para su campo, tal como el francés lo fue una vez para la diplomacia internacional.

comprar vs. construir

Un adjetivo que describe una elección entre gastar dinero al comprar software o escribirlo tú mismo.

mero trabajo

Trabajo que requiere poca creatividad y vincula poco riesgo. El mero trabajo puede ser fácilmente estimado.

notación de programación

Un sinónimo para los lenguajes de programación que enfatiza la naturaleza matemática del lenguaje de programación y su relativa simplicidad comparada con los lenguajes naturales.

strawman

Un documento destinado a ser el punto de inicio de una discusión técnica. Un strawman puede conducir a un stickman, a un tinman, a un woodman, a un ironman, etc.

white-paper

Un documento informativo que a menudo es destinado para explicar o vender una idea o producto a una audiencia diferente a la de los programadores de esos productos o ideas.

Tabla de Contenido

Bibliography/Websiteography

Bibliografía/Websiteografía

Books

[Rules00] Guy Kawasaki, Michelle Moreno, y Gary Kawasaki. 2000. HarperBusiness. Rules for Revolutionaries: The Capitalist Manifesto for Creating y Marketing New Products y Services.

[RDev96] Steve McConnell. 1996. Microsoft Press. Redmond, Wash. Rapid Development:Taming Wild Software Schedules.

[CodeC93] Steve McConnell. 1993. Microsoft Press. Redmond, Wash. Code Complete.

[XP99] Kent Beck. 1999. 0201616416. Addison-Wesley. Extreme Programming Explained: Embrace Change.

[PlanXP00] Kent Beck y Martin Fowler. 2000. 0201710919. Addison-Wesley. Planning Extreme Programming.

[Prag99] Andrew Hunt, David Thomas, y Ward Cunningham. 1999. 020161622X. Addison-Wesley. The Pragmatic Programador: From Journeyman to Master.

[Stronger] Friedrich Nietzsche. 1889. Twilight of the Idols, "Maxims y Arrows", sección 8..

Web Sites

[PGSite] Paul Graham. 2002. Articles on his website: http://www.paulgraham.com/articles.html. All of them, but especialmente "Beating the Averages".

[Hacker] Eric S. Raymond. 2003. Cómo to Become a Hacker. http://www.catb.org/~esr/faqs/hacker-Cómoto.html.

[HackDict] Eric S. Raymond. 2003. The New Hacker Dictionary. http://catb.org/esr/jargon/jargon.html.

[ExpCS] Edsger W. Dijkstra. 1986. How Experimental is Computing Science?.http://www.cs.utexas.edu/usuarios/EWD/ewd09xx/EWD988a.PDF.

[Knife] Edsger W. Dijkstra. 1984. On a Cultural Gap.http://www.cs.utexas.edu/usuarios/EWD/ewd09xx/EWD913.PDF .

Appendix B. History (As Of February, 2003)

Solicitud de Retroalimentación o Extensión

Por favor envíenme cualesquier comentarios que puedas tener sobre este ensayo. Yo considero todas las sugerencias, muchas de las cuales ya han mejorado este ensayo.

He puesto este ensayo bajo la Licencia de Documentación Libre de la GNU. Esta licencia no está específicamente diseñada para ensayos. Los ensayos are usualmente intended para ser argumentos coherentes y convincentes que son escritos desde un único punto de vista en una única voz. Espero que este ensayo sea una lectura corta y placentera.

Espero también que sea instructivo. Aunque no es un libro de texto, está dividido en muchas secciones pequeñas a las cuales puedes ser libremente añadidas nuevas secciones. Si estás inclinado a ello, you are encouraged a expandir este ensayo as you see fit, sujeto a las provisiones de la Licencia.

Puede ser arrogancia imaginar que vale la pena extender este documento; pero espero eternas primaveras. Estaría gozoso si fuera extendido de las siguientes formas:

La adición de una lista de lecturas comprensivas a cada sección, La adición de más y mejores secciones, La traducción a otros lenguajes, aún si es solamente en una base de

subsecctión por subsección, y/o Críticas o comentarios incluidos dentro del texto. La capacidad de convertirlo a diferentes formatos, tales como formatos palm y

un mejor formato HTML.

Si me informas de tu trabajo, Lo consideraré y puedo incluirlo en versiones subsecuentes que produzca, sujeto a las provisiones de la Licencia. Puedes por supuesto producir tus propias versiones de este documento sin mi conocimiento, como se explica en la Licencia.

Gracias.

Robert L. Read

Versión Original

La versión original de este documento fue comenzada por Robert L. Read en el año 2000 y publicada primero electrónicamente en Samizdat Press (http://Samizdat.mines.edu) en el 2002. Está dedicada a los programadores de Hire.com.

Después de que este artículo fue mencionado en Slashdot en el 2003, cerca de 75 personas me enviaron emails con sugerencias y erratas. Los aprecio a todos. Hubo mucha duplicación, pero las siguientes personas hicieron sugerencias mayores o fueron las primeras en encontrar un error que ya corregí: Morgan McGuire, David Mason, Tom Moertel, Ninja Programador (145252) at Slashdot, Ben Vierck, Rob Hafernik, Mark Cómoe, Pieter Pareit, Brian Grayson, Zed A. Shaw, Steve Benz, Maksim Iofe, Andrew Wu, David Jeschke, y Tom Corcoran.

Finalmente me gustaría agradecer a Christina Vallery, cuya edición y lectura profesional mejoró grandemente el segundo borrador, y a Wayne Allen, quien me alentó a iniciar esto.

Biografía del Autor Original

Robert L. Read vive en Austin, Texas, con su esposa y sus dos hijos. Es actualmente un Ingeniero Principal en Hire.com, donde ha trabajado por cuatro años. Previo a eso fundó 4R Technology, la cual hizo una herramienta de control de calidad para el análisis de imágenes basadas en escáner para la industria periodiodística (o del papel?).

Rob recibió un PhD de la Universidad de Texas en Austin en 1995 en Ciencias de la Computación relacionado a la teoría de bases de datos. En 1987 recibió un BA en Ciencias de la Computación de la Universidad Rice. Ha sido un programador pagado desde la edad de 16 años.

Apéndice C. Licencia de Documentación Libre de la GNU

Versión 1.2, Noviembre del 2002

Tabla de Contenido

PREAMBULOAPLICABILIDAD Y DEFINICIONESCOPIAR AL PIE DE LA LETRACOPIAR EN CANTIDADMODIFICACIONESCOMBINANDO DOCUMENTOSCOLECCIONES DE DOCUMENTOSAGGREGATION CON TRABAJOS INDEPENDIENTESTRADUCCIONTERMINACIONFUTURAS REVISIONES DE ESTA LICENCIAADENDUM: cómo usar esta Licencia para tus documentosCopyright (C) 2000,2001,2002 Fundación del Software Libre, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Se permite a todos copiar y distribuir copias al pie de la letra de este documento de licencia, pero no está permitido cambiarla.

PREAMBULO

El propósito de esta Licencia es hacer un manual, libro de texto, u otro documento funcional y útil "libre" en el sentido de libertad: para asegurar a todos la efectiva libertad de copiarlo y redistribuirlo, con o sin modificaciones, ya sea comercial o no comercialmente. En segundo lugar, esta Licencia preserva para el autor como para el editor una forma de obtener crédito por su trabajo, aunque no sea considerado responsable por las modificaciones hecha por otros.

Esta Licencia es un tipo de "copyleft", lo cual significa que los trabajos derivados del documento deben ser ellos mismos ser libres en el mismo sentido. Complementa la Licencia de Documentación Libre de la GNU, la cual es una licencia copyleft diseñada para software libre.

Hemos diseñado esta Licencia a fin de de usarla para manuales de software libre, debido a que el software libre necesita documentación libre: un programa libre debería venir con manuales que provean las mismas libertades que provee el software. Pero esta Licencia no está limitada a manuales de software; puede ser usada para cualquier trabajo textual, sin importar el tema de la materia o si es published como un libro impreso. Recomendamosesta Licencia principalmente para trabajos cuyo propósito es instrucción o referencia.

APLICABILIDAD Y DEFINICIONES

Esta Licencia se aplica a cualquier manual u otro trabajo, en cualquier medio, que contenga una nota colocada por el poseedor del copyright que diga que puede ser distribuida bajo los términos de esta Licencia. Tal nota concede una licencia mundial y libre de regalías, ilimitada en duración, para usar ese trabajo bajo las condiciones establecidas aquí. El "Documento", en lo sucesivo, se refiere a cualquier manual o trabajo de ese tipo. Cualquier miembro del públic es un licenciado, y es addressed como "tu". Aceptas la licencia si copias, modificas o distribuyes el trabajo de una forma que requiera permiso bajo la ley del copyright.

A "Una Versión Modificada" del Documento significa cualquier trabajo que contenga el Documento o una porción de él, ya sea copiado fielmente, o con modificaciones y/o traducido a otro lenguaje.

A "La Sección Secundaria" es un ap éndice nombrado o una sección front-matter del Documento que trata exclusivamente con la relación de los editores o autores del Documento al tema general del Documento (o a los temas relacionados) y no contiene nada que pudiera caer directamente dentro de ese tema general. (Así, si el Documento es una parte de un libro de texto de matemáticas, una Sección Secundaria puede no explicar ninguna matemática.) La relación podría ser una cuestión de conexión histórica con el tema o con temas relacionados, o de posiciones legales, comerciales, filosóficas, éticas o políticas relacionadas a ellos.

Las "Secciones Invariantes" son ciertas Secciones Secundarias cuyos títulos están designados, como para ser Secciones Invariantes, en la nota que dice que el Documento es liberado bajo esta Licencia. Si una sección no llena la definición anterior de Secundaria entonces no está permitido que sea designada como Invariante. El Documento puede contener cero Secciones Invariantes. Si el Documento no identifica ninguna Sección Invariante entonces no hay ninguna.

El "Texto de la Portada" son ciertos pasajes cortos de texto que son listados, como los Textos de la Cubierta Frontal o los Textos de la Cubierta Posterior, en la nota que dice que el Documento es liberado bajo esta Licencia. Un Texto de Cubierta Frontal puede

ser al menos de 5 palabras, y un Texto de Cubierta Posterior puede ser de al menos 25 palabras.

Una copia "Transparente" del Documento significa una copia legible por una máquina, representado en un format cuya especificación está disponible al público general, que es suitable para revisar el documento straightforwardly con editores de texto genéricos o (en el caso de imágenes compuestas de pixeles) programas de pintura genéricos o (en el caso de dibujos) algunos editores de dibujo ampliamente disponibles, y que es suitable como entrada para formateadores de texto o para traducción automática a una variedad de formatos suitable como entrada para formateadores de texto. Una copia hecha de otro formato de archivo Transparente cuya markup, o ausencia de markup, ha sido arreglado para thwart o discourage las modificaciones subsecuentes por los lectores no es Transparente. Un formato de imagen no es Transparente si es usado para cualquier cantidad sustancial de texto. Una copia que no es "Transparente" es llamada "Opaca".

Ejemplos de formatos suitable para copias Transparentes incluyen ASCII plano sin markup, formato de entrada Texinfo, formato de entrada LaTeX, SGML o XML que usen una DTD públicamente disponible, y los que conformen simples estándares HTML, PostScript o PDF diseñados para modificación humana. Ejemplos de formatos de imagen transparente incluyen PNG, XCF y JPG. Los formatos opacos incluyen formatos proprietarios que puedan ser leídos y editados solamente por procesadores de palabras proprietarios, SGML o XML para los que las DTD y/o las herramientas de proesamiento no están generalmente dispnibles, y el HTML, PostScript o PDF generado a máquina producido por algunos procesadores de palabras para propósitos de salida solamente.

La "Página de Título" significa, para un libro impreso, la página de título misma, más las páginas siguientes que sean necesarias para mantener, legiblemente, el material que esta Licencia requiere para aparecer en la página de título. Para trabajos en formatos que no tengan ningún página de título como tal, "Página de Título" significa el texto cercano a la más prominente aparició de del título del trabajo, precedeciendo el comienzo del cuerpo del texto.

Una sección "Titulada XYZ" significa una subunidad denominada del Documento cuyo título es precisamente XYZ o contiene XYZ en paréntesis siguiendo al texto que traduce XYZ en otro lenguaje. (Aquí XYZ stands for un nombre de sección específica mencionada en lo sucesivo, tal como "Reconocimientos", "Dedicatorias", "Respaldos", o "Historia".) Para "Preservar el Título" de tal sección cuando modifiques el Documento significa que se mantiene una sección "Titulada XYZ" de acuerdo a esta definición.

El Documento puede incluir Abstenciones de Garantía próximas a la nota que establece que esta Licencia se aplica al Documento. Esas Abstenciones de Garantía son consideradas para ser incluidas por referencia en la Licencia, pero solamente as regards de rechazo de garantías: cualquier otra implicación que esas Abstenciones de Garantía puedan tener es evitada y no tiene efecto en el significado de esta Licencia.

COPIAR AL PIE DE LA LETRA

Puedes copiar y distribuir el Documento en cualquier medio, comercial o no comercialmente, siempre que esta Licencia, las notas de copyright, y la nota de la licencia que dicen que esta Licencia se aplica al Documento sean reproducidas en todas las copias, y que no añades ninguna otra condición whatsoever a esas de la Licencia. Puedes no usar medidas técnicas para obstruir o controlar la lectura o copias subsiguientes de las copias que hagas o distribuyas. Sin embargo, puedes aceptar

compensación a cambio de las copias. Si distribuyes una gran cantidad de copias debes también seguir las condiciones de la sección 3.

Puedes también lend copias, bajo las mismas condiciones establecidas arriba, y puedes públicamente exhibir copias.

COPIAR EN CANTIDAD

Si publicas copias impresas (o copias en medios que comúnmente tienen cubiertas impresas) del Documento, en cantidades mayores a 100, y la nota de licencia del Documento requiere Textos de Cubierta, debes enclose las copias en cubiertas que porten, clara y legiblemente, todos esos Textos de Cubierta: Textos de Cubierta Frontal en la cubierta frontal, y Textos de la Cubierta Posterior en la cubierta posterior. Ambas cubiertas deben también identificarte clara y legiblemente como el editor de esas copias. La cubierta frontal debe presentar el texto completo con todas las palabras del título igualmente prominente y visible. Puedes añadir adicionalmente otro material en las cubiertas. Copiar con cambios limitados a las cubiertas, mientras preserven el título del Documento y satisfaga esas condiciones, puede ser tratado como copias al pie de la letra en otros respectos.

Si los textos requeridos para cualquier cubierta son muy voluminosos para caber legiblemente, deberías poner las primeras listadas (tantas como quepan razonablemente) sobre la cubierta actual, y continuar el resto en páginas adyacentes.

Si publicas o distribuyes copias Opacas del Documento en cantidades mayores de 100, debes incluir una copia Transparente legible por máquinas junto con cada copia Opaca, o state in o con cada copia Opaca en una ubicación de red de computadora desde la cual el público que usa la red general tenga acceso a descargarla usando protocolos de red públicos estándares una copia completa Transparente del Documento, libre de material agregado. Si usas la última opción, debes tomar pasos razonablemente prudentes cuando comiences la distribución de copias Opacas en cantidad, para asegurar que esa copia Transparente permanecerá así accesible en la ubicación establecida hasta al menos un año después de la última vez que distribuyas una copia Opaca (directamente o a través de tus agentes o retailers) de esa edición al público.

It is requested, pero no requerido, que contactes a los autores del Documento con suficiente antelación antes de redistribuir cualquier número grande de copias, para darles la oportunidad de proporcionarte una versión actualizada del Documento.

MODIFICACIONES

Puedes copiar y distribuir una Versión Modificada del Documento bajo las condiciones de las secciones 2 y 3 anteriores, provided que tú liberas las Versión Modificada precisamente bajo esta Licencia, con la Versión Modificada filling el rol del Document, licenciando así la distribución y modificación de la Versión Modificada a quien posea una copia de ella. Adicionalmente, debes hacer estas cosas en la Versión Modificada:

A. Usar en la Página de Título (y en las cubiertas, si las tiene) un título distinto al del Documento, y a los de las versiones previas (los cuales deberían, si hubiese alguna, estar listado en la sección de Historia del Documento). Puedes usar el mismo título de una versión previa si el editor original de esa versión da el permiso.

B. Listar en la Página del Título, como autores, una o más personas o entidades responsables pr la autoría de las modificaciones en la Versión Modificada, junto

con al menos cinco de los principales autores del Documento (todos sus autores, si tiene menos de cinco), a menos que ellos te libera de este requirimiento.

C. Coloca en la página de Título el nombre del editor de la Versión Modificada, al igual que el del editor.

D. Preserva todos las notas de copyright del Documento.E. Añade una nota de copyright apropriada para tus modificacions adyacente a las

otras notas de copyright.F. Incluye, inmediatamente despu és de las notas de copyright, una nota de

licencia dando al público permiso para usar la Versión Modificada bajo los términos de esta Licencia, en la forma mostrada en el Addendum siguiente.

G. Preserva en esa nota de licencia la lista completa de las Secciones Invariantes y los Textos de las Cubiertas dados en la nota de licencia del Documento.

H. Incluye una copia inalterada de este Licencia.I. Preserva la sección Titulada "Historia", Preserva su Título, y agrega a ella un

ítem estableciendo al menos el título, año, nuevos autores, y el editor de la Versión Modificada como en la Página de Título. Si no hay una sección Titulada "Historia" en el Documento, crea una estableciendo el títilo, año, autores, y el editor del Documento igual que en su Página de Título, luego añade un ítem describiendo la Versión Modificada como se estableció en la oración previa.

J. Preserva la ubicación de red, si existe alguna, dada en el Documento para acceso público a una copia Transparente del Documento, y likewise las ubicaciones de red dadas en el Documento de versiones previas en las que estaba basada. Esas pueden ser colocadas en la sección "History". Puedes omitir una ubicación de red para un trabajo que fue publicado al menos cuatro años antes que el Documento mismo, o si el editor original de la versión a la que se refiere da permiso.

K. Para cualquier sección Titulada "Reconocimientos" o "Dedicatorias", Preserva el Título de la sección, y preserva en la sección toda la sustancia y tono de cada uno de los reconocimientos de contribuyentes y/o dedicatorias dadas ahí.

L. Preserva todas las Secciones Invariantes del Documento, inalteradas en su texto y en sus títulos. Los números de Sección o el equivalente no son considerados parte de los títulos de la sección.

M. Elimina cualquier sección Titulada "Endorsements". Tales secciones pueden no ser incluidas en la Versión Modificada.

N. No retitules ninguna sección existente Titulada "Endorsements" o para conflictuar en título con alguna Sección Invariante.

O. Preserva cualesquiera Abstenciones de Garantía.

Si la Versión Modificada incluye nuevas secciones front-matter o apéndices que califiquen como Secciones Secundarias y no contengan ningún material copiado del Documento, puedes a tu criterio designar alguna o todas esas secciones como invariantes. Para hacer esto, añade sus títulos a la lista de Secciones Invariantes en la nota de licencia de la Versión Modificada. Esos títulos deben ser distintos de los de cualquier otra sección.

Puedes añadir una sección Titulada "Endorsements", procurando que no contenga otra cosa excepto endorsements de tu Versión Modificada by varias partes--por ejemplo, statements de revisiones personales o que el texto ha sido aprovado por una organización como la definición authoritative de un estándar.

Puedes añadir un pasaje de hasta cinco palabras como un Texto de Cubierta Frontal, y un pasaje de hasta 25 palabras como un Texto de Cubierta Posterior, al final de la lista de Textos de CubiertasTen la Versión Modificada. Solamente un pasaje de Texto de Cubierta Frontal y uno de Texto de Cubierta Posterior pueden ser añadidos por (o por

medio de arreglos) cualquier entidad única. Si el Documento ya incluye un texto de cubierta para la misma cubierta, previamente añadida pr ti o por medio de un arreglo hecho por la misma entidad estás actuando on behalf of, puedes no agregar otra; pero puedes reemplazar la antigua, con el permiso explícito del editor previo que la ha agregado.

El (los) autor(es) y el (los) editor(es) del Documento no conceden mediante esta Licencia permiso para usar sus nombres para publicidad o to assert o implicar endorsement of cualquier Versión Modificada.

COMBINANDO DOCUMENTOS

Puedes combinar el Documento con otros documentos liberados bajo esta Licencia, bajo los términos definidos en la sección 4 anterior para versiones modificadas, provided que incluyes en la combinación todas las Secciones Invariantes de todos los documentos original, no modificados y listadas todas como Secciones Invariantes de tu trabajo combinado en su nota de licencia, y que preservas todas sus Abstenciones de Garantía.

El trabajo combinado necesita solamente contener una copia de esta Licencia, y Secciones Invariantes idénticas múltiples pueden ser reemplazadas con una única copia. Si hay múltiples Secciones Invariantes con el mismo nombre pero diferente contenido, haz el título de cada una de dichas secciones único al añadir al final de él, entre paréntesis, el nombre del autor original o editor de esa sección si es conocido, o de otro modo un número único. Haz el mismo ajuste a los títulos de la sección en la lista de Secciones Invariantes Sections en la nota de licencia del trabajo combinado.

En la combinación, debes combinar cualesquiera secciones Tituladas "Historia" en los diversos documentos originales, formando una sección Titulada "Historia"; de igual modo combina cualesquiera secciones Tituladas "Reconocimientos", y cualesquiera secciones Tituladas "Dedicatorias". Debes eliminar todas las secciones Tituladas "Endorsements".

COLECCIONES DE DOCUMENTOS

Puedes hacer una colección consistente del Document y otros documentos liberados bajo esta Licencia, y reeplazar las copias individuales de esta Licencia en los documentos varios con una única copia que es incluida en la colección, procuranado seguir las reglas de esta Licencia para las copias al pie de la letra de cada uno de los documentos en todos los otros aspectos.

Puedes extraer un único documento de tal colección, y distribirlo individualmente bajo esta Licencia, procurando que insertes una copia de esta Licencia en el documento extraído, y siguiendo esta Licencia en todos los otros aspectos relacionados con copias al pie de la letra de ese documento.

AGGREGATION CON TRABAJOS INDEPENDIENTES

Una compilación del Documento o sus derivados con otros documentos o trabajos separados e independentes, en o sobre un volumen de almacenamiento o medio de distribución, es llamado un "agregado" si el copyright que resulta de la compilación no es usado para limitar los derechos legales de los usuarios de la compilación más allá de los que los trabajos individuales permiten. Cuando el Document es incluido en un

agregado, esta Licencia no se aplica a los otros trabajos en el agregado los cuales no son ellos mismos trabajos derivados del Documento.

Si el requiremento del Texto de la Cubierta de la sección 3 es aplicable a esas copias del Documento, entonces si el Documento es menos de la mitad del agregado completo, el Texto de la Cubierta del Document puede ser colocado en las cubiertas que bracket el Documento con el agregado, o el equivalente electrónico de las cubiertas si el Documento es en forma electrónica. De otro modo ellos deben aparecer en las cubiertas impresas que bracket todo el agregado.

TRADUCCION

La Traducción es considerada un tipo de modificación, de tal manera que puedes distribuir traducciones del Documento bajo los términos de la sección 4. El reemplazo de las Secciones Invariantes con traducciones requiere permiso especial de sus poseedores del copyright, pero puedes incluir traducciones de alguna o todas las Secciones Invariantes adicionalmente a las versiones originales de esas Secciones Invariantes. Puedes incluir una traducción de esta Licencia, y todas las notas de licencia en el Documento, y cualesquieras Abstencipnes de Garantía , siempre que también incluyas la versión Inglés original de esta Licencia y las versiones originales de esas notas y abstenciones. En caso de un desacuerdo entre la traducción y la versión original de esta Licencia o una nota o abstención, la versión original prevalecerá.

Si una sección en el Documento es Titulada "Reconocimientos", "Dedicatorias", o "Historia", el requerimiento (sección 4) para Preservar su Título (sección 1) requerirá típicamente el cambio del título actual.

TERMINACION

Puedes no copiar, modificar, sublicenciar, o no distribuir el Document excepto como expresamente se proveyó bajo esta Licencia. Cualquier otro intento de copiar, modificar, sublicenciar, o distribuir el Documento es evitada, y finalizará automáticamente tus derechos bajo esta Licencia. Sin embargo, las partes que han recibido copias, o derechos, de ti bajo esta Licencia no tendrán sus licencias terminadas mientras tales partes se mantengan en completo cumplimiento.

FUTURAS REVISIONES DE ESTA LICENCIA

The Fundación del Software Libre puede publicar versiones nuevas o revisadas de la Licencia de Documentación Libre de la GNU de vez en cuando. Tales versiones nuevas serán similares en espíritu a la presente versión, pero pueden diferir en detalles para resolver nuevos problemas o preocupaciones. Véase http://www.gnu.org/copyleft/.

A cada versión de la Licencia se le da un número de versión que la distingue. Si el Documento especifica que una versión particular numerada de esta Licencia "o cualquier versión posterior" se aplica a ella, tienes la opción de seguir los términos y condiciones de esa versión especificada o de cualquier versión posterior que haya sido publicada (no como un borrador) por la Fundación del Software Libre. Si el Documento no especifica un número de versión de esta Licencia, puedes elegir cualquier versión que haya sido publicada (no como un borrador) por la Fundación del Software Libre.

ADENDUM: cómo usar esta Licencia para tus documentos

Para usar esta Licencia en un documento que has escrito, incluye una copia de la Licencia en el documento y pon el siguiente copyright y notas de licencia justo después de la página de título:

Copyright (c) AÑO TU NOMBRE. Se concede permiso para copiar, distribuir y/o modificar este documento bajo los términos de la Licencia de Documentación Libre de la GNU, Versión 1.2 o cualquier versión posterior publicada por la Fundación del Software Libre; sin Secciones Invariantes, sin Textos de Cubierta Frontal, y sin Textos de Cubierta Posterior. Una copia de la licencia se incluye en la sección titulada "Licencia de Documentación Libre de la GNU".

Si tienes Secciones Invariantes, Textos de Portada Frontal y Textos de Cubieta Posterior, reemplaza la línea "con...Textos." con esto:

con las Secciones Invariantes siendo LISTA SUS TITULOS, con los Textos de la Cubierta Frontal siendo LISTA, y con los Textos de la Cubierta Posterior siendo LISTA.

Si tienes Secciones Invariantes sin Textos de Portada, o alguna otra combinación de los tres, combina esas dos alternativas para acomodar la situación.

Si tu documento contiene ejemplo no triviales de código de programa, recomendamos liberar esos ejemplos en paralelo bajo tu elección de licencia de software libre, tal como la Licencia Pública General de la GNU, para permitir su uso en el software libre.

Colofón

Este trabajo es licenciado bajo la Licencia de Documentación Libre de la GNU. Fue originalmente escrito en LaTeX, luego portado a DocBook. Está disponible en copia transparente en el formato DocBook/XML. Un sistema de construcción e instrucciones especiales sobre el procesamiento son parte del paquete de la copia transparente, aunque la contrucción desde la fuente es dependiente del sistema. La fuente puede ser construida tanto en formato HTML como PDF, y la extensión a otros formatos debe ser posible y es alentada.

La versión original de este documento fue escrita por Robert L. Read sin renumeración y dedicada a los programadores de Hire.com.-