Refactoring – Move switch to Table

Esta es quizás una de las técnicas más antiguas de programación pero como no lo he visto en el catalogo de refactoring me he decidido a ponerlo aquí. Esta técnica es llamada Table Driven Method en el libro de Steve McConnell (Code Complete) pero como ya dije, la técnica es mucho más antigua que el libro.

La idea es reemplazar código como este: 

image

Por algo como lo que sigue:

image

Nota: es cierto que el comportamiento de ambos métodos es distinto pero es solo para mostrar la idea.

¿Por qué tanto miedo al movimiento software craftsmanship? Mi visión.

Hace ya más de 10 años se redactó el “Manifesto for Agile Software Development” con sus 4 valores y 12 principios, un hito importantísimo dentro de la historia de nuestra profesión pero de ningún modo el comienzo del movimiento ágil porque para cuando los próceres se reunieron ya existía cierto consenso, al menos entre ellos, sobre la manera en que se debía desarrollar software. Como miembros respetados de la comunidad y la industria, todo el mundo técnico se sintió representado por los 17, sobre todo porque no eran un grupo de MBAs ni de auditores de calidad ni miembros de algún que otro instituto de normalización o estándares sino personas reconocidas por, entre otras cosas, sus conocimientos técnicos. Y sí, mis “ídolos” Martin Fowler, Kent Beck y  Uncle Bob están allí y son tipos técnicamente fuertes.

El Manifesto no podía esperar más, los procesos de desarrollos eran pesadísimos y todos lo sabíamos y por esto, salvo aquellos que vivían de la ineficiencia (auditores, certificadores, documentadores, analistas de causas, consultores CMMI y recolectores de métricas entre otros), odiábamos el sinsentido. Lo que era evidente que no funcionaba parecía solo ser evidente por los técnicos que despotricábamos todo el tiempo por el estado de las cosas porque la inmensa mayoría de los gerentes de proyecto, y de ahí para arriba, estaban fascinados con la visión “Ingenieril”, pensaban que si lo hacían lo suficientemente bien podrían al fin deshacerse del problema de los desarrolladores y en su lugar reclutar a ejércitos de amas de casa deprimidas por el sobrepeso y obtener los mismo resultados.

Aunque el Manifesto dio un gran empuje, la revolución no iba a esperar por él, si no lo hacían estos 17, lo hubieran hecho otros porque XP ya estaba en boca de todos cambiando las mentes desde abajo de la pirámide. Y es que aunque muchos piensan que esto debemos agradecerlo a los 17, y a las primeras empresas importantes que lo comenzaron a intentar, la verdad es que en toda empresa que yo haya conocido existía al menos uno, y bien respetado técnico, que machacaba, transmitía (“evangelizaba”),  discutía y peleaba por que las cosas cambiaran. Desde las bases, como una guerra de guerrillas. Y al fin, uno por uno, hasta el más escéptico, terminó recitando los principios  del Manifesto mientras se daban golpes en el pecho. (Si hasta el SEI se camufló de ágil, algo similar a ponerle el traje de Spiderman a una anciana de 200 kilos)

Eso es lo que queríamos, cambiar para mejorar. Ese es y ha sido siempre el pensamiento de quienes hacemos de esto nuestras vidas, cambiar para mejorar! Y la cosa mejoró sin dudas, ahora ya tenemos iteraciones, ya aceptamos mejor los cambios, ya nos concentramos más en aquello que da valor pero… ¿qué hay del software?  ¿qué hay de eso de la “excelencia técnica”?. Si si si, hoy estamos mejor pero también es cierto que los técnicos seguimos viendo lo evidente: tenemos un problema muy grave con “la excelencia técnica” que impide que todo esto funcione como debería, como sabemos que debe funcionar. Mientras que hoy la capa de management, mayoritariamente Scrum, está ampliamente difundida, las prácticas de ingeniería por su parte, mucho más antiguas que el mismo scrum, no se implementan (quizás si estás leyendo esto es porque formás parte del 5% de desarrolladores que leen blogs y que implementa alguna de ellas), pair programming casi no existe, TDD muy pero muy poco (muchos se llenan la boca pero el porcentaje de software escrito con TDD es ínfimo), Integración contínua aún cuando es una de las más sencillas todavía está lejos de ser la norma, refactoring hoy se le llama a cualquier cambio suicida (sin tests, sin metodología) y así podemos seguir. Ni hablemos de la formación de los desarrolladores.

El código sigue apestando, esto significa que los diseños apestan, que la calidad sigue lejos de lo que debería ser, esto mismo también significa que los costos siguen altos y que quien invierte en esto puede hacerse de la ventaja competitiva. Pero de todo el movimiento ágil parece que lo que se ha llevado todo es Scrum (y ahora Lean). Pero entre tanta gestión nos estamos olvidando de algo importante: el software y como este se diseña, se programa y se prueba. ¿O acaso está por volver la idea de los monos programadores? ¿Será posible formar equipos de alto rendimiento con maestras jardineras reconvertidas a programadoras?

La verdad es que hoy como ayer, quienes pensamos en cambiar para mejorar, estamos dando una nueva batalla, la de profesionalizar la profesión, la de reforzar las prácticas, la de recrear la carrera técnica (porque el “paraíso” del management (y sus salarios) sigue llevándose a los mejores de entre nosotros), la de formar realmente a los aspirantes para que puedan hacer frente a la complejidad de los desarrollos actuales y futuros, en fin… la batalla sigue siendo por lo mismo: por mejorar la manera en que desarrollamos software. ¿Alguien ve algo malo en esto?

Increiblemente, aunque no veo cómo esto pueda perjudicar a la industria, a la profesión, a los clientes o a la sociedad, hay gente preocupada por el movimiento, personas importantes como Martin Fowler aquí. ¿En qué modo puede un intento por mejorar la profesión, de mejorar y difundir aún más las practicas de ingeniería ser peligroso? El miedo es que se le preste “demasiada” atención a la disciplina y se deje de lado al cliente, el miedo es a que nos perdamos en discusiones ñoñas sobre arquitectura, frameworks, patrones y sesiones de refactoring. Este miedo se basa en la creencia de que podemos volvernos aún mucho más idiotas!. Martin Fowler, quien ha escrito los libros más técnicos que yo haya leído en mi vida parece tener cierto grado de preocupación.

Y sí, yo sé que existe un pequeño grupo de fanáticos que de alguna forma se han sentido traicionados por el rumbo que tomó el movimiento ágil, gente que acompañó al movimiento y que pensó que el camino iba a ser diferente. Después de todo yo también me sentí algo defraudado, pero eso no significa que no aprecie lo que hemos logrado de la mano del movimiento ágil. No obstante, tenemos un problema entre manos, un problema que muchos creyeron que iba a ser resuelto por el movimiento ágil pero que aún persiste y se sigue cargando costos y sigue perjudicando a los clientes.

Autodisciplina al hacer check in

Cuando el build se rompe con demasiada frecuencia o permanece en ese estado por mucho tiempo, el equipo se ve impedido de avanzar cómodamente. Pero la razón principal por la que se rompen es sin dudas el descuido: no compilar antes de subir, no correr las pruebas antes de subir y no prestar la suficiente atención al mergear entre otras cosas. Esto es porque existe un exceso de confianza en los miembros del equipo.

Para ayudar a mitigar esto, en mi equipo anterior creé este premio semanal con el que nos hemos divertido mucho y la verdad es que me ha dado un resultado enorme hasta el punto que debí quitarlo cuando lo empecé a ganar yo!

image

Nota: usábamos CC.Net y SVN por lo que más que descansar en la herramienta, lo que logramos fue autodisciplica.

Arquitectos e intelectuales

Ser llamado arquitecto es similar a ser llamado “un intelectual”, es un título que un grupo te otorga debido a tu actividad en la comunidad o en la industria pero que entiendo que nunca debería autoasignarse. Del mismo modo en que es de mal gusto que una persona se presente a si mismo como “un intelectual”, lo mismo sucede con aquellos desarrolladores que se presentan como “arquitectos”. No obstante, aunque nunca he escuchado a nadie presentarse como “un intelectual” (quizás porque queda algo ridículo decir: “Hola, me llamo Pedro y soy un intelectual”), sí lo veo a diario en desarrolladores que se presentan a si mismos como arquitectos.

Hoy por hoy, arquitecto es muchas veces una “categoría” que muchas empresas utilizan a la hora de categorizar (valga la redundancia) a sus desarrolladores más capaces y en ese contexto puede que presentarse ante los demás como arquitecto de tal o cual compañía sea correcto.

Por otro lado, conozco a algunos desarrolladores de esos que son invisibles a Google, que no mantienen un blog, que no dan charlas, que no participan en los foros y que no twitean pero que son auténticos cracks, tipos a los que aún cuando todos en su entorno los reconocen como arquitectos, no se sienten cómodos con el título, al igual que le sucede a muchos auténticos intelectuales.

Así que por favor, no te autodenomines arquitecto! Si eres uno, tus compañeros, la empresa en la que trabajas, la comunidad y quizás el mundo entero te reconocerá como tal aún cuando no te guste o creas que el título te queda grande. No depende de tí.

Difícil demostrar con números las ventajas de Pair Programming

ElBruno ha escrito un interesante artículo en su blog titulado “[#ALM] DEMOSTRANDO CON NÚMEROS PORQUÉ ES CONVENIENTE REALIZAR PAIR PROGRAMMING” en el que, mediante lo que considero un ejercicio de razonamiento, intenta demostrar el incremento que esta práctica puede generar en la productividad de un equipo con una configuración ficticia, aunque bastante común, de 2 Devs. Srs. y 4 Devs. Jrs.  Recomiendo su lectura (y además, es condición necesaria para entender de que se habla en esta entrada).

En primer lugar debo aclarar que todo intento por ayudar a difundir, y animar a implementar, esta y otras prácticas es de agradecer e imitar. Además, y solo para dejar explícita mi posición acerca de esta práctica (Pair Programming), debo decir que estoy absolutamente de acuerdo con ella, incrementa la calidad, los diseños, la comunicación y el conocimiento del equipo como pocas prácticas lo hacen. Y además es más sociable y divertido mientras que eleva el compromiso.

Ahora, una vez aclarado esto, debo decir que a mi humilde entender ElBruno no ha acertado en su enfoque. ¿Por qué? Veamos, para demostrar la hipótesis, utiliza el siguiente ejemplo:

image

El problema con la argumentación es que todo el modelo cierra cuando existe una cantidad de desarrolladores juniors los cuales no pueden completar su trabajo sin quitarles tiempo a los desarrolladores seniors, de esta forma y en este contexto parece que la propuesta es una buena idea para maximizar la productividad. Lo curioso es que según el ejemplo, la mejor solución sería eliminar esos 4 factores de anti-capacity llamados juniors y así, con solo una fracción del costo, los 2 desarrolladores seniors podrían completar sus 2 unidades de trabajo diarias con lo que a la semana tendríamos 20 unidades de trabajo completas. Entonces, es la existencia de esos juniors la condición necesaria para que esto cierre.

No obstante creo que aquí se cumple una gran verdad: poner más desarrolladores, poco experimentados, no incrementa la velocidad del equipo; y como este modelo concuerda con las experiencias de la vida misma, podemos pensar que no está muy lejos de ser correcto.

Ahora, este mismo razonamiento no arroja los mismos resultados si el equipo tuviese otra configuración como por ejemplo si fuesen solamente 6 Devs. Srs. En este caso, si aplicamos el mismo razonamiento utilizado en el ejemplo, el resultado será que como nadie requiere ayuda de otro para terminar (o al menos idealmente), entonces tener a 2 Devs. Srs. en una misma máquina resultaría en una pérdida de la productividad.

Como Pair Programming es exactamente para, entre otras muchas cosas, incrementar la calidad y con esto reducir los costos, creo que esta argumentación podría habilitar a aquellos quienes desconocen la práctica, detractores por ignorancia, a jugar con modelos similares concentrándose en la economía evidente (para ver “si les conviene” o “no les conviene”) ignorando la disminución del costo a largo plazo que esta logra. Quizás, como todo el ejemplo cierra gracias a estos 4 devs. juniors alguien podría argumentar que su equipo no necesita de esta práctica ya que el mismo se compone solo de devs. seniors. Así las cosas, este argumento es de doble filo!

Otro motivo por el que este ejemplo no me parece el mejor es porque, en mi experiencia, Pair Programming funciona mucho mejor cuando ambos desarrolladores tienen conocimientos “equivalentes” y no tan bien cuando la diferencia de conocimientos es grande como entre un junior y un senior. En este último caso, el juniors casi siempre se limita a mirar (y en el mejor de los casos a aprender, que no es poco) pero difícilmente pueda darse la dinámica de cambiar con cierta frecuencia el teclado y los roles.

Por desgracia esta práctica es quizás la menos utilizada y esto se debe entre otras cosas a que es difícil de demostrar de manera “teórica” lo que la hace no muy evidente. Otro problema es que en varios papers de señores científicos que publican en la IEEE y la ACM se menciona que esta incrementa el time to market en entre un 15-20% y por eso es también que se hace mucho más difícil de justificar. En el tiempo de los resultados rápidos pocos quieren invertir a largo plazo.

Refactoring–Extract Method para separar validaciones de operaciones

Existen casos en los que es conveniente extraer un bloque de código en un nuevo método por razones de validaciones de entrada. Es decir, queremos sepaar el código de validaciones de entradas del código que realiza propiamente las operaciones con estas. En algunos casos esto además puede traernos algunos beneficios de performance. Esto es más claro en los métodos recursivos. Para ilustrar esto pongamos como ejemplo al clásico método que calcula el Factorial de N de manera recursiva:

image

Aquí el problema está en que el parámetro ‘n’ se valida en cada llamada pero la realidad es que esto no debería ser así ya que si ‘n’ es válido en la primera llamada este va a serlo también en todas las sucesivas invocaciones que se hacen de manera recursiva. Por este motivo es conveniente separar las validaciones y extraer el cálculo del factorial para llevarlo a otro método como sigue:

image

No es la performance lo que interesa aquí sino la separación conceptual de las validaciones y las operaciones, el incremento de la performance es solo un producto derivado de haber hecho esto.

Cambiando a modo Autoritario – Una historia real

La Misión

La misión era formar un equipo para un proyecto de esos grandes, realmente muy grandes, así que la empresa se puso a la búsqueda de desarrolladores para que eligiera de entre ellos a los que considerase más apropiados. La búsqueda se comenzó tanto de manera interna como externa en un esfuerzo contra reloj por conseguir profesionales que cumpliesen con los requisitos que yo había solicitado; nada del otro mundo a mi entender.

Buscando profesionales

Está claro que uno debe privilegiar la incorporación de aquellos profesionales que ya forman parte de la empresa por sobre aquellos es necesario reclutar puesto que el recruiting es un proceso largo, así que comencé por donde debía aunque paralelamente evaluaba los perfiles de las candidatos que el equipo de recruiting me enviaba (haciendo una tarea excepcional) y los entrevistaba en horas extra laborales ya que la gente que trabaja difícilmente puede “escaparse” de sus lugares de trabajo para ser entrevistados.

Como en las empresas los desarrolladores no vagan por los pasillos a la espera de una asignación sino que en su inmensa mayoría están asignado a proyectos, luego de evaluar a un par (los disponibles), y a falta de opciones (quería evitar a toda costa formar un equipo distribuido) me focalicé en entrevistar candidatos externos. Candidato tras candidato fallaban miserablemente en temas técnicos los cuales yo consideraba sumamente esenciales y me hacían replantearme mis niveles de exigencia, los cuales me vi forzado a relajar hasta niveles mínimos; y luego los debí relajar un tanto más. La verdad es que encontrar verdaderos profesionales es una tarea titánica que puede asombrar a muchos pero el punto es que luego de 2 semanas no había podido encontrar ni a uno solo. Los candidatos, en un gran número, provenían de entidades bancarias, empresas constructoras u otras no dedicadas directamente a la industria del desarrollo de software (nota: no había límite alguno en la propuesta salarial ni en los beneficios ofrecidos por lo que si se hubiese presentado un arquitecto seguramente se lo hubiese tentado, doy fe. En realidad, para ser honesto, se presentó un arquitecto pero este era un título que se había autoasignado de manera descarada, pero ese es otro tema)

Sin demasiadas opciones y repleto de presiones desde varios frentes, porque básicamente tenía que formar un equipo y el tiempo se agotaba, me decidí por aquellos que tenía más experiencia y respondían con mayor coherencia en las sucesivas entrevistas. Y no solo eso sino aquellos con mayor predisposición y que pensaba que trabajarían mejor como equipo, nada fácil. Luego, cuando el tiempo se agotó definitivamente, el management más alto se encargó de sugerirme los restantes, tres juniors.

Características del equipo

Ninguno de los miembros del recientemente formado equipo había escrito nunca una prueba unitaria y tampoco sabían nada al respecto, tampoco habían trabajado con integración continua a excepción de uno de ellos, y muchos no habían usado nunca una herramienta de gestión de versiones. Aunque no es necesario continuar con esta lista, quien lee puede inferir el resto de los tópicos faltantes.

No obstante a esto que menciono, es de tener en cuenta que de entre los descartados había quienes conocían estos temas aunque fallaban en tareas como ordenar un vector de 10 números enteros, algo que quedará para otra entrada porque me ha llamado poderosamente la atención.

Comienza el proyecto

Comienza el proyecto y caigo en el primer error. Yo creía que luego de explicar las prácticas básicas (UT, CI, PR y SCA), estas iban a ser reconocidas como beneficiosas a la primera; error! La resistencia fue grande, recuerdo solo algunas pocas opiniones por su repetición:

  • ¿Para qué UT? Yo nunca los necesité!
  • ¡Qué importa si el build está roto! No entiendo por qué no puedo subir mis cambios
  • ¿¡Como %#&!* querés que suba código si todavía no lo he terminado!?, mañana lo termino y lo subo
  • En eso de revisar el código se pierde mucho tiempo
  • No pongo los comentarios en los checkins porque me olvido, además nunca los va a leer nadie

Lo peor es que obtener estos y otros conocimientos (o hábitos) es algo que lleva mucho tiempo. No solo eso sino que además estos fueron problemas a nivel técnico pero también los hubo a nivel organización: el equipo no era capaz de auto organizarse, requerían dirección, requerían asignaciones, requerían control y seguimiento y requerían…. órdenes.

Cambiando a modo autoritario

Antes de continuar debo decir que cambiar a modo autoritario es en extremo sencillo, casi que me animo a decir que es natural, y es quizás por eso que es tan común en el mundo. Pero aunque va en contra de todo lo que crees, de lo que sabes, de lo que has aprendido, de lo que has estudiado, de lo que has pensado y reflexionado, la autoridad es una facultad (y una responsabilidad) con la que, en parte,  te enviste embiste la compañía y, que en parte, tenés por tus conocimientos. Y en ese momento entendí que debía utilizarse por el bien de todos.

Comencé por imponer la prácticas de manera muy rigurosa, a controlar su cumplimiento y a alertar a los infractores. Solo como ejemplo las siguientes fueron las primeras reglas inquebrantables y me aseguraba que se cumplieran:

  • Nadie sube nada con el build roto
  • Todo el mundo sube código al menos una vez al día
  • Nadie deja el build roto por ninguna causa
  • Si el build se rompe, a arreglarlo inmediatamente (es prioridad número uno)
  • Antes de subir, se pide a un compañero que revise el código y se incluye el nombre del revisor como parte del commit
  • Todo método tiene que tener al menos un UT
  • Los comentarios en los commits deben explicar el motivo y contenido de los cambios

También hacer el seguimiento del avance de manera estricta para forzar a las personas a que siguiesen no solo las prácticas sino que también las tareas de soporte como reportar avance, tiempo consumido en la tarea, etc. Recuero que día tras día siempre debía recitarle a alguien: “si no subiste código ni ayer ni antes de ayer y no reportaste las horas consumidas ¿cómo puedo saber que estás trabajando?”. Obviamente detrás es esta excusa lo único que pretendía era que subieran código periódicamente y que reportasen las horas en una herramienta en la que queríamos tener esas horas, nada más. También sacaba reportes diariamente de las distintas “infracciones” y se las comunicaba.

Todo esto, como habrán de imaginarse no me hizo merecedor del premio al mejor amigo, sobre todo después que la experiencia me diera la razón en repetidas oportunidades. Solo dos ejemplo:

  • Caso 1: Un día uno de los integrantes me dice que se le había roto la PC a lo que yo le pregunto: ¿perdiste algo de trabajo? Sí, lo de hoy y lo que de ayer –me responde. ¡Pero acaso no quedó claro que se hace commit todos los días?!
  • Caso 2: Otro miembro reportaba que había solucionado un conjunto de bugs un día y al siguiente reportó que había solucionado otros tanto pero a todo esto yo veía que no subía código. Subí el código le decía una y otra vez pero luego QC reabrió todos sus bugs porque nunca hizo commit.

Primera buena noticia

Pasado casi tres meses todo el mundo subía código al menos una vez al día, es más, casi todo el equipo subía código varias veces al día. Todo el equipo comentaba sus commits y luego fueron mejorando sus comentarios a medida que necesitaban buscar cosas en SVN, nunca nadie dejó el build roto jamás, ni lo rompían con la frecuencia inicial, incluso hubo semanas en las que con más de 200 commits nunca se rompió el build (mucho código nuevo, pocas pruebas unitarias y mucho cuidado por parte de todos – no usábamos análisis estático de código). Las pruebas unitarias mejoraron algo (no mucho). La calidad del código se incrementó notablemente aun cuando distaba de ser lo esperado.

Luego el equipo siguió creciendo y los nuevos integrantes se adaptaban a las reglas de manera natural ya que el resto se las comunicaba como algo positivo “che, rompiste el build, es un UT ¿querés que te de una mano con eso?”, “fulano, hay que poner comentarios en los commits. Fijate como lo hacemos nosotros!”.

La buena noticia

Por último, con la mejora de la comunicación, la confianza adquirida y la experiencia en el proyecto el equipo fue capaz al fin de auto organizarse, de elegir las tareas, de coordinarse, de reportar proactivamente sin esperar a ser consultados, de evaluar alternativas y sugerir cambios, de trabajar como un verdadero equipo, unido. Recién luego de estos cambios “forzados” el equipo comenzó a dar verdaderos resultados y de disfrutar de la autonomía y la confianza que se habían ganado. Luego de esto abandoné el proyecto con una gran satisfacción y un orgullo inmenso.

Conclusión

Cuando estamos en un equipo bien aceitado, un nuevo miembro experimentado (y técnicamente fuerte) que pertenezca a la industria se adaptará a la manera de trabajo y en poco tiempo habrá asimilado todas la prácticas que ejecuta el equipo sin problemas. Pero, un equipo grande y completamente nuevo formado en parte por profesionales que no pertenecen al la industria, y otros tantos juniors, y no fuertes técnicamente, no será capaz de auto organizarse.

Llegar al nivel de madurez necesario para que sea posible todo esto no ocurrirá mágicamente nunca, antes de esto tendremos lo que al principio: un equipo completamente inmaduro e incapaz de lograr los resultados que se necesita que alcance. Estos equipos requieren que se los dirija, y para ello contamos con la autoridad (no solo la del conocimiento sino también, y en este contexto quizás más importante, aquella que te otorga tu posición en el grupo)

Entonces, el ejercicio firme de la autoridad (o el autoritarismo) es un vehículo que, a falta de mejores opciones, debe en estos casos utilizarse para generar las condiciones necesarias para su total desaparición (El autoritarismo anti-autoritario).

Code Freeze–Explicando esta MALA práctica

Hace un par de días una amigo preguntó por esta práctica en twitter por lo que decidí dar una brevísima explicación en este video.

NOTA: a sugerencia de Rodrigo Corral he cambiado el título para que quede claro de entrada que en la inmensa mayoría de los casos esta es una mala práctica, cosa que entiendo he dejado bien claro en el video; aunque nunca se sabe. Creo además que la malas prácticas también necesitan ser explicadas ya que forman parte del vocabulario común y uno debe conocerlas.