Jul 03

Se nos va relajando Scrum…. por decirlo suavemente.

 

Hace tiempo empezamos a intentar hacer Scrum un grupo de cuatro para atender seis proyectos, con sprints de una semana. Los sprints tan cortos eran necesarios para poder reorganizar el product backlog mezclado con historias de varios proyectos y poder cambiar de unos proyectos a otros en función de sus prioridades. Pero esos sprints tan cortos nos hacían perder mucho tiempo, ya que organizar todos los viernes una o dos demos, era demasiado para enseñar un pequeño incremento de funcionalidad.

Así que intentamos aproximarnos a algo más como Kanban. Teníamos nuestras historias, nuestras reuniones diarias, nuestras tareas, planificación por poker, pero no haciamos las demos.

Y ya no queda ni eso. Uno de los proyectos ha entrado en sus fases finales, así que estamos los cuatro liados con ese proyecto. Nuestro trabajo día a día consiste en probar, encontrar incidencias y corregirlas. Nuestro product backlog es "probar tal tema y corregir". Planificar eso es complejo, una incidencia nunca se sabe cuánto se puede tardar en corregir y menos una semana antes, cuando todavía no la has encontrado.

Así que nada, consideraremos este periodo como un descanso de Scrum, seguiremos con nuestras reuniones diarias (han gustado a todos los miembros del equipo) y a la vuelta de vacaciones retomaremos el Scrum/Kanban.

Jul 02

Chuletas a mogollón

 

En Cheat Sheet hay un montón de chuletas de temas de informática. Pequeños pdf de una o dos páginas para imprimir en el que se resumen comandos de un montón de temas: subversion, git, vi, ada, ajax, apache, etc, etc.

Ideal para bajarse, imprimir y tener a mano las de las herramientas que más usemos día a día, sobre todo cuando empezamos con ellas.

Jul 01

Ser o no ser héroes

 

Imagínate que caes en un equipo de desarrollo con gente competente, que saben lo que hacen y lo hacen bien. Tienes además la suerte de que el jefe de proyecto para el que trabajas también es un buen jefe de proyecto. Sabe lo que quiere, se lo cuenta al equipo con claridad y trata de resolver todos los problemas que se presenten. ¿Qué pasa en esta situación?. Lo normal. El proyecto va bien, sin problemas graves, llega a tiempo a sus fechas de entrega con unas incidencias razonables y sin fallos graves.

Suponte ahora lo contrario. Un proyecto en el que el jefe de proyecto no tiene claro lo que quiere, no te especifica nada, no te dice como lo quiere, pero sí te dice cuando ya los has hecho que así no lo quería. Además, el grupo de desarrolladores es más bien de la media para abajo, el poco código que sale está lleno de errores y si funciona, es de casualidad. ¿Qué pasa en esta situación? Pues lo normal, que el proyecto va mal, que no llega en fechas, que cuando se pasan las pruebas con cliente todo es un "efecto demo" gigante.

Entre los dos proyectos hay además una consecuencia interesante. En el primer caso, los jefes del jefe de proyecto apenas saben que existe ese proyecto. Es un proyecto que no da pegas, que no gasta más dinero de la cuenta, que no se retrasa y que no recibe quejas del cliente, así que la cosa "no sube" hacia arriba, así que para ellos no es más que una cifra bonita en alguna tabla de Excel.

En el segundo caso, empiezan a dispararse las alarmas, los jefes del jefe empiezan a recibir los problemas de dinero, fechas y quejas del cliente. Empiezan a saber que ese proyecto existe y empiezan a hacerle un seguimiento exhaustivo día a día. Se empieza a hacer presión y los desarrolladores y jefe de proyecto empiezan a echar horas como locos y se olvidan de que tienen casa.

En el primer proyecto, el buen jefe de proyecto y los buenos desarrolladores han hecho estupendamente su trabajo, pero no se les ha notado ni los jefes los van a valorar en lo que merecen. En resumen, "no son héroes".

En el segundo proyecto, si después de echar muchos fines de semana y horas a tope se consigue que el proyecto pase como se pueda, con un listado interminable de incidencias y cosas pendientes, con el cliente descontento, pero pasa, entonces los que han participado en él son la leche, han hecho un esfuerzo sobrehumano y han conseguido sacar adelante un proyecto que era un caos. Gracias a esto, los jefes de proyecto ya conocen las caras de los desarrolladores y del jefe de proyecto. Por supuesto, se han creído todas las excusas que el jefe de proyecto y los desarrolladores les han dado para justificar que el proyecto va mal. En resumen, "Sí son héroes".

Desgraciadamente, es la realidad. Se valora más al desarrollador que echa horas y horas resolviendo problemas en un proyecto caótico, que al desarrollador que no resuelve problemas a horas intempestivas de la noche, símplemente porque no ha generado esos problemas.

Jun 30

JUnit y Log4j

 

Cuando hacemos nuestras clases de test de JUnit, puede ser bastante normal testear clases que usan log4j. Si en nuestros test queemos que se muestre la traza de esas clases, debemos configurar log4j. Lo normal es hacerlo en el método setUp() del test (el que se ejecuta justo antes de cada uno de los test) de una forma similar a esta

public void setUp() {
   BasicConfigurator.configure();
}

Quizás, en vez de en el setUp() lo hagamos en el constructor de la clase de test.

Pero esto tiene una pequeña cosa que debemos saber. Cada vez que llamamos al BasicConfigurator.configure(), se añade un ConsoleAppender al log4j. Por ello, cada vez que se ejecuta setUp() (una vez por cada test), se añade un appender nuevo… y la traza empieza a salir repetida, ya que cada appender creado saca el mensaje por consola. Si lo hacemos en el constructor y tenemos varias clases de test, tenemos el mismo problema.

Para evitar esto, lo mas sencillo es llamar a BasicConfigurator.configure() en el método setUp() (y no en el constructor), pero poner tambien un método tearDown(), que JUnit llama automáticamente al final de cada test, y ahí borrar los appenders añadidos

public void tearDown() {
   LogManager.shutdown();
}

De esta forma, por cada test, primero se añadirá el appender y después se borrará. Cada test tendrá un único appender y la salida de log será única.

Jun 27

Tipos de debugger

 

Cuando queremos depurar nuestro código, hay tres tipos de debugger, que de menos evolucionado a más evolucionado son:

  1. Poner prints, compilar, ejecutar y mirar la traza. Ponemos más prints, volvemos a ejecutar y volvemos a mirar la traza. Así, por aproximaciones sucesivas, vamos aislando el problema hasta que damos con él.
  2. Usar un debugger propiamente dicho, el que venga con el compilador o el de nuestro IDE favorito. Ponemos breakpoints, watches, inspects y similares. Ejecutamos el códido y vamos dándole a "step over", "step into" y demás variantes. De esta forma, llegamos más lentos que en el paso anterior al error, ya que tenemos que aprender a usar el debugger y si apenas sabemos programar, es pedir demasiado.
  3. La opción buena. Cogemos nuestro proyecto y lo metemos un un zip. Hacemos un copy-paste del error/excepción que nos sale y lo subimos todo a varios foros junto con una explicación más o menos elaborada, pero sobre todo misteriosa (estilo "lo tengo todo bien pero no funciona"). Esta es la forma más cómoda, con un poco de suerte, el bug se soluciona solo y además usamos las metodologías más avanzadas (el internet) y compartimos conocimientos (otros pueden aprender de nuestros errores).

Lo siento. A veces me espanto con lo que veo en los foros …

Jun 26

CVS no vale para proyecto grandes

 

Llevamos ya varios días que hemos migrado algunos repositorios de CVS a Subversion y se nota una gran diferencia, sobre todo en los update. Tras usarlo varios días y si nos paramos a pensar un poco, es bastante lógico.

CVS mantiene un número de versión para cada uno de los ficheros en el repositorio y cada fichero es independiente totalmente de los demás. De hecho, puedes entrar directamente en el repositorio, borrar uno de los ficheros con su historia y el repositorio sigue funcionando perfectamente, se olvida por completo que ese fichero ha existido alguna vez.

Subversion no tiene número de versión para cada fichero, sino que tiene un único número de versión para todo el repositorio. Si se toca un solo fichero, el número de versión de todo el repositorio se incrementa en uno.

Esta diferencia, que en cuestión de gustos puede ser mejor una u otra, tiene una importancia importante en la eficacia de los update. Si estoy en CVS y hago un update de todo el proyecto, CVS no tiene más remedio que revisar todos los ficheros uno a uno para ver si en el repositorio hay una versión más moderna de ese fichero y actualizarla. Eso, en un proyecto grande, con varios miles de ficheros, puede tardar un rato.

Sin embargo, con subersion, mi copia local tiene un número de versión que es de la última vez que hice update. Si ahora hago un nuevo update, subversion sólo tiene que comparar la versión de mi copia local y la del repositorio (sólo compara un entero). Si coincide, es que el update no tiene que hacer nada. Si no coincide, el repositorio tiene guardado qué ficheros se tocaron para esa nueva versión (y las anteriores si hay varias versiones de diferencia), así que sólo hay que hacer update de esos ficheros. No es necesario recorrerlos todos uno a uno.

En resumen, un update de un proyecto grande que antes tardaba tres o cuatro minutos, ahora se hace en unos segundos.

Por ello, si tu proyecto va a ser grande, con varios miles de ficheros, CVS no es una buena opción, ya que perderás mucho tiempo haciendo los updates diarios de los fuentes (y si el proyecto es grande, serán muchos días). Es mucho mejor Subversion (o cualquier otro sistema de control de versiones que lleve todo el repositorio con un único número de versión), ya que el update diario es cuestión de segundos.

De la misma forma, crear tags o ramas es muy lento en CVS, porque debe recorrer todos los ficheros y marcar el tag o rama en cada uno de ellos. Mientras que subversion le basta con marcar que la revisión 1234 es un tag o rama. (En subversion no hay tags o ramas, como en CVS, sino que son copias, pero son copias "perezosas", es decir, no se hace realmente la copia hasta que el fichero cambia en la copia).

Por cierto, teníamos varios repositorios de CVSNT y aunque la herramienta de migración cvs2svn comenta que puede haber problemas en la migración a Subversion de CVSNT, no hemos encontrado ninguno (salvo temas de acentos y eñes dentro de los ficheros, en el nombre de los mismos o en el comentario de los commit).

Jun 23

Test Driven Develompment by example, de Kent Beck.

 

Aprovechando mi puente de cuatro días (fiestas locales de la ciudad en la que trabajo), me he leído "Test Driven Development by example", de Kent Beck. El libro se lee rápido, ya que hay poco texto en cada hoja, mucho código de ejemplo, mucha hoja en blanco para que pongas tus anotaciones y, sobre todo, porque al estar en inglés, me he saltado alegremente todo lo que no he entendido ;-)

De todos son conocidos los tres famosos pasos que hay que seguir con TDD

  1. Escribir un test automático de prueba y ejecutarlo para ver que falla.
  2. Hacer el código mínimo necesario para que el test pase.
  3. refactorizar el código.

Sin embargo, es necesaria la lectura de un libro como este (o aprender de alguien con experiencia) para poder entender qué significan exactamente estos pasos y cómo seguirlos de forma eficiente. Paso a continuación a detallar algunas de las conclusiones prácticas a las que te lleva la lectura del libro.

¿Cuánto debemos avanzar cada vez?

Siguiendo los tres pasos anteriores, podemos irnos a dos extremos. Por un lado, podemos hacer un test tonto, que nos lleve un minuto hacerlo. Luego podemos hacer el código para que pase ese test, que nos lleva otros dos minutos, y luego el refactor, en otros dos minutos. Al final del día podemos haber escrito doscientos tests y docientos trozitos de código y apenas haber avanzado en nuestro proyecto. El otro extremo es pasarnos dos días haciendo un test, una semana para el código de ese test y otra semana para hacer el refactor.

Según el libro, ni lo uno ni lo otro, hay que llegar al punto justo. ¿Y cual es ese punto?. Somos nosotros los que debemos decidirlo en función de nuestras "sensaciones" al ir programando. Los test y el código que hagamos no nos deben resultar demasiado triviales de forma que nos de la sensación de estar perdiendo el tiempo. Sin embargo, si deben ser del tamaño justo para que no nos cueste demasiado pensar el código que tenemos que hacer. Debemos ser capaces de hacer con cierta facilidad el código necesario para el test, sin que nos lleve más de, digamos, media hora conseguir que el test pase.

Si el código que hacemos para cada test nos resulta demasiado trivial, podemos hacer test un poco más grandes. Si el código para el test que estamos haciendo nos empieza a dar que pensar, no estamos muy seguros de cómo hacerlo o si va a funcionar a la primera, debemos hacer test más pequeños. Por ejemplo, si hacemos un test para un método suma, podemos implementar fácilmente el método. Si hacemos un test para un método recursivo de factorial, los más experimentados o con mejor cabeza para la programación pueden hacerlo directamente, pero los más novatos quizás necesiten hacer primero un test para el caso trivial e implementarlo, luego un test para otro número e implementarlo, etc.

De alguna forma, el libro da a entender que tenemos que tender más al ensayo y error con los test que pasarnos ratos largos pensando cómo implementar algo. Una buena medida de que debemos empezar a hacer test más pequeños y menos código en cada paso es cuando los test empiezan a sorprendernos con fallos inesperados, es decir, cuando ya no estamos realmente controlando la situación.

Centrarse en un test cada vez y hacer sólo lo necesario para este test

Este es quizás uno de los puntos que más fácilmente nos podemos saltar. Si hacemos un test y nos ponemos a hacer un código, es muy fácil que nos salgan situaciones o código auxiliar que necesitemos y nos pongamos a hacerlo en condiciones.

Por ejemplo, imagina que para pasar un test que requiere buscar un Alumno en una lista, vemos que necesitamos implementar el método equals() en la clase Alumno, que ese método equals() requiere un código algo rebuscado y además deberíamos implementar el método hashCode() que nos aconseja java siempre que implementemos el equals(). Es muy fácil que nos desviemos de nuestro test para hacer ese equals() y ese hashCode() lo más completos posibles y nos olvidemos temporalmente del test que nos ocupa. O quizás, haciendo el código usemos un método ya hecho y descubramos que ese método necesita un arreglo porque hay un caso que no contempla o debería hacer algo más. Es fácil que ahora nos pongamos a arreglar ese método.

Según el libro, no debemos hacer eso. Debemos implementar únicamente un equals() y/o hashCode() mínimo que nos permita pasar el test lo antes posible, incluso aunque devuelva directamente true o false y un hashCode cero, si con eso basta para que pase el test. Una vez que pasa nuestro test, podemos dar la siguiente iteración y hacer un test para el método equals() y entonces hacer una implementación correcta de equals().

Y la mejor forma de hacer esto y que no se nos olvide después y que nos sintamos cómodos haciendo esas "chapuzas" temporales, es tener un papel al lado del teclado en el que apuntemos los test que creemos que debemos  hacer más adelante. Si tenemos que hacer un equals() en condiciones, apuntamos en el papel que tenemos que hacer un test de equals() de la clase Alumno, escribimos ahora un equals() con la implementación mínima necesaria para que funcione el test en el que estamos trabajando, y nos olvidamos del equals() hasta que le toque el turno. Si tenemos que arreglar aquel método que hemos descubierto, pues apuntamos hacer un test para ese método y no lo tocamos ahora, nos centramos en el test que estamos actualmente trabajando.

Dejar que TDD nos vaya llevando al diseño más simple

Según TDD, debemos hacer en cada momento el código más simple posible que haga pasar el test. En el refactor, según el libro, debemos sobre todo trata de eliminar repeticiones (DRY, Dont repeat yourself o "no te repitas", para los amigos) y es precisamente en este paso de refactor, donde debemos "complicar" nuestro diseño sólo lo justo para evitar esas repeticiones. Veamos esto con un ejemplo concreto.

Imagínate que uno de nuestros test dice que al jefe le podemos fijar el sueldo. Hacemos un test que a la clase Jefe le pone un setSueldo() y comprueba que getSueldo() devuelve el sueldo que hemos pasado. (sí, ya sé que es muy tonto y que este tipo de cosas ni siquiera merecen la pena ser testeadas). Bueno, hacemos nuestra clase Jefe y ese par de métodos tontos y el test pasa.

Ahora, el siguiente test nos dice que podemos hacer lo mismo con un currito. Hacemos el test, hacemos la clase Currito y le ponemos los dos métodos de marras. Los test pasan, pero ahora toca refactorizar. ¿Código repetido?. Sí, las dos clases enteras, lo único que cambia es el nombre. Tal cual tenemos ahora, deberíamos hacer una clase Empleado con todo el código de setSueldo() y getSueldo() y BORRAR las clases Jefe y Currito. Sí, borrar, no hacer herencia, ni interface común ni nada parecido. Ahora mismo no hay nada que distinga a Jefe de Currito y el diseño más simple es tener una única clase con el código común (todo el código) para ambos tipos de personajes. No debemos dejarnos llevar en ningún momento por nuestro entusiasmo ni nuestros bastos conocimientos de OO para mantener la clase Jefe y Currito y hacerles una clase padre Empleado. De momento, simplemente no es necesario y por tanto, no lo hacemos.

Supón ahora que un test nos pide que escribamos en pantalla el tipo de personaje que es. Si es jefe o currito. Pues bien, la solución más simple no es volver a hacer las clases Jefe y Currito. La OO nos lo pide a gritos, pero no es la solución más simple para los tres test que tenemos. La solución más simple es hacer un enumerado JEFE, CURRITO y ponerle un atributo a la clase Empleado, que puede rellenarse en el mismo constructor, con el método getTipoEmpleado() correspondiente.

Ahora, otro test hace que alguna cosa, por ejemplo, comprobar si el Empleado tiene derecho a coche de empresa, y cómo no, sólo si es jefe tiene derecho a ello. Pues bien, mientras sólo este este test, la solución más simple es poner un if comprobando en el atributo enumerado si es jefe. El método tieneCocheEmpresa() de empleado simplemente devuelve el restultado del if.

Y finalmente, piensa en otro test que también da un privilegio al jefe, como comprobar si Empleado tiene derecho a un sillón cómodo y nuevamente sólo si es jefe tiene ese derecho. La solución más simple que podemos dar en este momento es añadir otro método tieneSillonComodo() otro if del atributo … pero cuando llega el momento de refactor vemos que hay código repetido. Ese if está en dos sitios distintos. Ahora, y sólo ahora, es el momento donde TDD nos aconseja que empezemos a pensar en la existencia de dos clases separadas, la de Jefe y la de Currito, cuando empezamos a ver que el "si es jefe" empieza a repetirse en varios sitios. Y sólo si las nuevas clases Jefe y Currito tienen código repetido, debemos mantener la clase Empleado y  heredar de ella. Si dejara de existir ese código común, simplemente eliminamos Empleado y no hacemos herencia. O quizás, en este caso concreto, sea más fácil mantener una tabla de booleanos/privilegio dentro de la clase Empleado.

De hecho, uno de los ejemplos del libro es precisamente algo parecido a esto. Comienza haciendo dos clases (Dolar y Franco) y acaba descartándolas para hacer una única clase (Dinero) que tiene un atributo que indica el tipo de moneda.

Descansos frecuentes

Y el consejo que más me ha gustado del libro: Tener siempre una botella de agua a mano, de esta forma, la fisiología te obligará a tomarte descansos frecuentes … para ir al baño.

Jun 19

¿Será que no me explico?

Hoy no es mi día. Envíe dos correos distintos, de temas distintos, a dos personas distintas. Me levanté del sitio y fuí a hacer algo (¿tomar un café?). Cuando volví a mi sitio, tenia dos correos nuevos. Las respuestas a los que había enviado. Una de las respuestas era …

"¿mande?"

La otra era …

"¿Cualo qué?"

En fin, creo que hay días en que uno no se levanta de la cama con la facilidad de hacerse entender.

Jun 17

El difícil compromiso entre KISS y OO

 

KISS es la abreviatura de "Keep it simple, stupid" o traducido, "Manténlo simple, estúpido". La idea es que el código debe hacerse siempre lo más sencillo posible. Esto ayuda a que haya menos errores y a que sea más fácilmente mantenible en un futuro, ya que será más fácil entenderlo por terceras personas y corregir posibles errores que queden.

OO es la orientación a objetos. Un código diseñado con orientación a objetos debe usar cosas como clases, herencias, polimorfismos, encapsulación, etc. Tras muchos años de diseño orientado a objetos, se ha llegado a que hay determinadas formas de combinar clases e interfaces para obtener unos resultados óptimos, los llamados patrones de diseño. Como consecuencia, un buen diseño orientado a objetos normalmente implica el uso de determinados patrones de diseño. También, en un buen diseño orientado a objetos, se usan varias clases cada una de ellas con una responsabilidad concreta muy definida, es decir, suelen ser clases pequeñas y que sólo hacen cosas concretas. El fin último de la orientación a objetos es conseguir que el código sea reutilizable. Podemos llevarnos a otros proyectos sólo aquellas clases que realmente necesitamos y además, están hechas de tal manera, que no es necesario modificarlas, sino que nos sirven tal cual.

Pues bien, KISS y OO, hasta cierto punto son opuestos y veamos un pequeño ejemplo tonto. Imagina que vamos a hacer un programa que pida al usuario por pantalla los coeficientes de una ecuación de segundo grado y nos muestre el resultado por pantalla.

Si llevamos KISS a sus últimas consecuencias y tratamos de hacer el código lo más simple posible, sin preocuparnos en absoluto de posible reusabilidad de lo que hacemos, lo más sencillo es hacer una única clase con un método main(). En ese método pedimos por pantalla los coeficientes (podemos hacer un método estático encargado de pedir un número por pantalla), echamos las cuentas (podemos meterlas en otro método estático) y sacamos los resultados (si acaso en otro método estático). Resultado final: una clase sencilla, que hace lo que tiene que hacer, con quizás tres métodos además del main(), pero que no es en absoluto reusable. Hace lo que hace y nada más. Sólo pide coeficientes por pantalla, echa unas cuentas y saca los resultados por pantalla.

Si pensamos más bien en hacer algo reusable y aplicamos orientación a objetos, posiblemente hagamos una clase EcuacionSegundoGrado a la que le pasemos los coeficientes y nos devuelva los resultados. Haremos otra clase (o dos clases) para pedir y sacar cosas por pantalla. Estas clases, idealmente, deberían implementar interfaces de pideDato() y muestraDato(), de forma que si más adelante en vez de pantalla es una base de datos, nos baste con implementar esas interfaces. Finalmente, posiblemente hagamos otra clase más con un main() encargada de instanciar las anteriores y hacerlas funcionar conjuntamente. El resultado final es que tenemos una serie de clases con responsabilidades separadas y reusables. Podemos coger cualquiera de esas clases y llevarla tal cual a otro proyecto y usarla a nuestro gusto.

Pero…. hemos perdido la sencillez. Ojo, no quiero decir que estas clases no estén bien hechas o que sean dfiíciles de entender si están bien hechas, pero donde antes teníamos una única clase y siguiendo el main() lo veíamos todo, ahora tenemos tres o cuatro clases, dos interfaces y seguir el código nos obliga a navegar de una a otra … y navegar a través de una interface no es sencillo, puesto que no sabemos qué implementación hay detrás (en este ejemplo sí sabemos cual hay detrás, porque sólo hay una). Obviamente, todo esto es peor si nuestro programa no es tan tonto como una ecuación de segundo grado.

¿Cual es entonces la situación ideal?. Las metodologías ágiles, en general, nos dan la solución bien clara. Haz el código lo más simple posible sólo para lo que tienes que hacer ahora (la historia de usuario concreta que estás haciendo ahora, el bug que estás corrigiendo, etc).

Si tenemos una historia de usuario que dice que pedimos los coeficientes por pantalla, resolvemos la ecuación y mostramos por pantalla los resultados, debemos, sin dudarlo, hacer la primera implementación, la del KISS puro y duro, tal cual nos aconsejan las metodologías ágiles. Cualquier metodología ágil nos aconseja también a hacer test automáticos de prueba. de forma que si más adelante tenemos que rehacer, tengamos seguridad de no estropear.

Supongamos ahora una segunda historia de usuario que nos dice que los coeficientes se deben leer de base de datos. Bien, este y no otro es el momento de hacer la interface con el método pideCoeficiente(), hacer dos implementaciones, la de pantalla y la de bd, y cambiar nuestro código para que no vaya directamente contra pantalla, sino contra esta interface cuya implementación alguien le pasará de fuera. Al tener test de la primera parte, tendremos seguridad de no haber estropeado lo que ya funcionaba después de tocar y ya habremos empezado nuestro diseño OO, por necesidad, y no por gusto. Ojo, todavía no hemos extraido la clase EcuacionSegundoGrado ni hemos hecho metodo en la interface de muestraResultado(), porque nadie nos ha pedido mostrarlo en otro sitio que no sea pantalla.

Resumiendo, es muy importante para tener un código lo más claro posible, no lanzarse sin ton ni son a hacer clases, interfaces, aplicar patrones y usar a tope la OO. Hay que ser realista y usar esas características de OO sólo cuando es estrictamente necesario o cuando estamos seguros al 99% de que vamos a necesitarlas. En el ejemplo anterior, si tenemos la lista de historias de usuario en algún sitio y vemos que la segunda está justo detrás de la primera, quizás, y en contra de las metodologías ágiles estrictas, podamos ir haciendo la interface ya en la primera implementación.

Jun 11

¿La programación es una carrera que llena tu vida?

 

Leo en DosIdeas el siguiente post : ¿La programación es una carrera que llena tu vida ?. Precisamente eso es algo en lo que estaba reflexionando en días anteriores y ahí van los porqués.

En el curro me dedico o intento dedicarme a programar. Siempre he huído despavorido de ser jefe de proyecto, de un grupo o de cualquier otra cosa. ¿Por qué?. Por que pienso que todas las relaciones con clientes y en general con gente en ambiente de trabajo siempre acaba llevando a tener roces. Al principio con el cliente todo son buenas palabras, pero cuando los plazos empiezan a echarse encima y log bugs del sistema empiezan a aparecer y ser complejos de resolver, la relación con el cliente puede volverse tensa. Con los compañeros de trabajo, habiendo buen rollo, no suele haber problemas. Pero al llegar a las etapas finales de proyecto, la presión, los bugs y las muchas horas de más pueden llevar también a roces y discusiones. "Mi parte funciona, el bug es tuyo". "Y unas narices". Si ya entre compañeros puede llegar a ser tensa, no te digo entre jefe y curritos. Además, en momentos de presión, un jefe debe ser malo, debe conseguir que la gente se quede a echar horas y terminen a tiempo. Los jefes inútiles lo hacen amenazando, regañando, chillando e imponiéndose. Los jefes astutos (y esos son los peores), lo consiguen sin necesidad siquiera de pedirlo. Todavía recuerdo un Domingo que me quedé hasta las dos de la madrugada para un proyecto que pasaba pruebas el Lunes y lo peor es que la jefa de proyecto… ¡ ni siquiera me pidió que fuera el fin de semana !, consiguió que yo lo hiciera voluntariamente.

Sin embargo, cuando me dedico a programar es cuando realmente estoy en mi salsa. Puedo pasar horas entretenido, sin darme cuenta del tiempo que pasa. Y cuando consigo acabar algo o resuelvo algún bug especialmente complejo, es cuando más satisfecho me voy a casa. De hecho, cuando llego a casa, suelo encender el ordenador y ponerme a hacer/aprender cosas de programación o relacionas. Además de mi trabajo, es también mi hobby.

Sí, entiendo que si quisiese ser jefe de la forma tradicional, cogiera proyectos como jefe de proyecto, me dedicara con mi traje y corbata a aguantar y engañar al cliente y me importara tres pepinos "explotar" a mis compañeros, posiblemente cobraría más y estaría mejor considerado en la empresa, pero… a mi, por lo menos, no me merece la pena. Prefiero tener la conciencia tranquila y dedicarme a algo que realmente me gusta. Irme a mi hora a casa (salvo agún Domingo excepcional), llevarme bien con la gente y aprender cosas nuevas todos los días.