Login Barrapunto
Proyectos de informática: ¡Reacciona antes de estrellarte!
desde el dept. autoayuda
1. Autocrítica y consciencia de la situación.
- El "no hay recursos suficientes" no es excusa: Si produces el 20% que otros con igualdad de recursos, significa que no lo estás haciendo bien.
- El responsable eres tú. No te escudes en la proyección psicológica.
2. Identificar los recursos que dispones
- Identifica en qué eres competente y en qué no.
- Sé realista y honesto contigo mismo: No tapes tus complejos pretendiendo saberlo todo, pues cuando es obvio que no tienes ni idea de algo, genera desconfianza y malestar (por ser una falta de consideración/respeto y un insulto a la inteligencia).
- Busca suplir tu incompetencia con la competencia de otros.
- Busca la excelencia: no actúes por orgullo, miedos, o amiguismo.
- Conoce muy bien a las personas, si no sabes en profundidad cómo trabaja cada uno de los componentes de tu equipo, estás perdido: Para un ignorante dos programadores pueden ser iguales, pero en el mundo real uno puede hundirte la empresa y otro sacarte las castañas del fuego en una fracción del tiempo.
- Identificar a quien perjudica más que aporta, y consciencia de falsas ventajas comparativas: Si alguien tarda en programar algo 2 meses, y luego otro tiene que estar una semana corrigiendo, y este segundo habría hecho esa misma tarea en una semana o en menos, significa que la productividad de la primera persona es 0 -i.e. no hay posibilidad de ventaja comparativa cuando la productividad es menor o igual a 0-. Esto se puede arreglar asignando otras tareas o con "reciclaje" u "orientación" (i.e. programa como X, y si no, no programas, punto).
3. Prevención de problemas
- El proceso de desarrollo tiene que estar definido, ser sencillo, y que no se den "cortijos" (gente que no pide permiso ni sigue regla alguna). Usa gestores de versiones, planifica las releases.
- Si quieres tener el control sobre todo, has de tener el conocimiento sobre todo. Como eso es imposible, tienes que aprender a: delegar. Si no delegas, serás el árbitro universal, tendrás que resolverlo tú todo, hasta para el conflicto más ridículo, e incluso para cosas en las que no tienes ni idea (si hay alguien experto en X, delega en X las decisiones al respecto: recuerda que como responsable tendrás siempre capacidad de veto).
- Las obligaciones y responsabilidades han de estar claras. Las bicefalias/tricefalias/etc., junto con las responsabilidades que están en el aire, producen conflictos y/o desautorizaciones a destiempo (i.e. si alguien es responsable de algo, ha de ser responsable "de verdad", pues si por miedo de delegar el tema se queda a medio gas, acaba siendo un cachondeo).
- Adecuar el talento y formación a las tareas: Dejar hacer algo "grande" a un aprendiz o a alguien sin preparación suficiente puede quebrar a una empresa, por el pifostio que puede montar. Salvo que sea algo experimental y no dependa de ello el negocio, pues es importante dar oportunidades a gente con potencial.
- Asigna lo complejo a quien tenga más talento. Si por criterios arbitrarios asignas cosas a quien no puede con ellas o a quien lo podría hacer mejor, tendrás retrasos, problemas, llegando a perder la salud o tener que cerrar la persiana. Si no hay bastante talento, búscalo, o simplifica el problema hasta que sea abarcable por lo que tengas.
- Hay que buscar hacer lo complicado sencillo: Si alguien hace complicado lo simple, ahí tienes tu aprendiz, ni se te ocurra encargarle tareas de más de 20 horas.
- El "código malo" sale carísimo (sólo interesa a cárnicas y demás parásitos del mantenimiento eterno). Si en tu equipo tienes personas que generan, por el motivo que sea, "código malo" (sean conscientes o no), tenlos identificados, y mucho ojo con lo que se le asigna.
- Si funciona, no lo toques. (i.e. si sólo se trata de que no te gusta a ti)
- Si no funciona, analiza y evalúa antes de reescribir. Hay "reescrituras" que son peores que el/los original/es. El dejar de usar algo sin reemplazo, también es una opción.
- Intenta evitar nueva funcionalidad a una base de código malo: Añade lo nuevo en un contexto "sano", i.e. si tienes componentes defectuosos pero que "funcionan" y no puedes permitirte reprogramarlos, en lugar de añadirles funcionalidades nueva dentro, hazlo en otros componentes nuevos.
- Contabiliza en qué se te va el presupuesto. Esto, es, si reescribes una misma funcionalidad 20 veces, que conste cuánto ha costado, y por qué se ha hecho ese gasto. No puede ser que tras 3 años te des cuenta que has gastado 1500 horas (correcciones, pruebas, soporte técnico) en correcciones a un componente que reescribirlo por completo no habría costado más de 300 horas (desarrollo + pruebas). Tienes que saber dónde se va el tiempo, o el tiempo se escapará un sumidero.
4. Identificación y gestión de los problemas en curso
Partiendo de la base que lo que tenéis en uso/producción es "más o menos usable/vendible", y que lo queréis hacer sobre la marcha (1):
- Paso 1, localización y segmentación de problemas:
- A) Dividir entre lo que afecta (A.1) y lo que no afecta (A.2) a la experiencia del usuario.
B) Diferenciar lo que no funciona o funciona pero no es escalable (B.1; crashes y problemas que ocasionan "consumo" del personal de soporte técnico, querys de 5 minutos, etc.), y lo que es horrible a nivel de código "pero funciona bien como caja negra y no hace crash nunca" (B.2).
C) Diferenciar lo que funciona pero supone gastos fijos (C.1; e.g. cosas sin automatizar que requieren procesos manuales como pueda ser el despliegue de contenido a N nodos remotos, el no usar gestores de versiones adecuados, no tener backups, etc.), de lo que no tiene coste dejándolo como está (C.2).
Tras el primer paso, el problema se reduce a modificar: A.1, B.1, C.1 (si lo queréis es vender un buen producto, reduciendo los fallos y el tiempo dedicado a mantenimiento).
Paso 2: priorización
- Pasada de priorización #1 (sobre A.1,B.1,C.1): Elimina todo lo que veas en A.1, B.1, C.1 que puedas dejar de hacer, por no ser vital para el negocio, de A.1, ya sea simplificando procesos o haciéndolo de otra manera (e.g. cambiar Intranet hecha "a mano" por un CMS, sin tunear a medida, algo austero pero que cumpla lo mínimo que necesitáis). Tras la limpieza, quedaría: A.1', B.1', C.1'
Pasada de priorización #2 (sobre A.1, B.1): Juntad el 80% de los casos más graves de A.1' y B.1', que se puedan resolver en el 30% del tiempo sin generar dependencias en los casos restantes (tuneado de la "Regla de Pareto" pero con un 80-30 en lugar del 80-20). Etiquetad esos casos como "AB.1-rápido", el resto, dividirlos entre "AB.1-fácil-pero-lento" y "AB.1-muy-difícil"
Pasada de priorización #3 (sobre C.1): Determinar los gastos fijos que suponen, separando en dos grupos: C.1-pinchazo (hasta el 5% de los costes fijos de la empresa, i.e. la empresa podría ir boyante, pero las chapuzas se comen los beneficios) y C.1-sangría (riesgo de cerrar la empresa).
Paso 3, ejecución:
- Pre-ejecución: No asignar a nadie una tarea para la que no esté capacitado (la buena voluntad no siempre es suficiente), la pueda hacer en un tiempo razonable, y el resultado sea de calidad. Si esas restricciones no son posibles, volved al paso 1, y simplificar más todavía las tareas hasta que las podáis acometer (si es imposible, y depende del cierre de la empresa, pagad a uno o varios figuras un pastón -e.g. pasta por delante y además, si en 3 años le va bien a la empresa, te llevas un X como bonus-).
Ataque #1: "C.1-sangría"
Ataque #2: "AB.1-rápido"
Ataque #3: "AB.1-fácil-pero-lento"
Ataque #4: Volver al Paso 1, con sólo "AB.1-muy-difícil" y "C.1-pinchazo"
- A) Dividir entre lo que afecta (A.1) y lo que no afecta (A.2) a la experiencia del usuario.
Suponiendo que ya conoces la situación, eres consciente de tus capacidades y la de quienes están a tu cargo, puedes prever/evitar problemas, y has reenfocado/solucionado los problemas del "pasado". ¿Ahora qué? ¿Cómo enfocar el camino?
5.1. Visualiza dónde estás y a dónde te diriges
Si el desarrollo está estancado, y no cambias nada, dentro de dos años, suponiendo que puedas mantener el negocio en funcionamiento, seguirás prácticamente igual. Estando en situación de "detenimiento psicológico", haciendo las cosas a remolque, anclado en el mantenimiento, es equivalente a estar parado: arrancar no será fácil. En mi opinión, lo que más sirve es tener una visión del camino a dónde quieres/puedes ir, e ir haciéndolo más o menos de acuerdo a un programa, susceptible de cambios por los requisitos que puedan llegar de fuera, etc.
Si no tienes ni idea de a dónde quieres ir, ni por donde, ni con quien, lo tienes crudo. Si tienes un plan a largo plazo, aún cuando este no sea el mejor del mundo, es infinitamente mejor que ir a la deriva, que te llevará a estrellarte tarde o temprano, pues los problemas no se solucionarán solos, sino que irán a peor.
5.2. Multiplica la capacidad de programación
En la industria del software, descontando la parte del espectáculo, el hacerse la foto, vender la moto, y demás cuentos, lo que acostumbra a determinar la supervivencia del negocio es el resultado de trabajo enfocado en la parte de desarrollo. Si el desarrollo no funciona adecuadamente, el negocio malvivirá de los éxitos del pasado o cerrará en el largo plazo, salvo que no tenga competencia, claro está. La parte clave en el desarrollo es el programador, quien marca la diferencia. Por mucho que se haya pretendido, principalmente por parte de consultoras plagadas de gestores mediocres, el programador no es ninguna commodity, desde el momento que un programador excelente puede ser de 5 a 20 veces más productivo que uno "normal" (y como normal no incluyo a los que son más perros que un trillo, que como en todas las profesiones, haylos). Hay gente con más y menos talento, más y menos formación, y si bien no puedes convertir a un burro en una eminencia, la mayoría de la gente que programa tiene mucho potencial de mejora. Se me ocurren las siguientes claves de la "reprogramación de programadores" (ejemplos, si alguien tiene más, que lo comente):
- Clave 1: Producir cosas sencillas es menos costoso que cosas complejas. Ejemplo: Si alguien necesita 30 threads para algo trivial que se puede hacer con sólo uno. Esto, por mi experiencia, puede suponer reducir el coste de implementación y mantenimiento a la tercera parte. También hay casos de software que no llega a funcionar bien nunca, pues añadir complejidad sobre algo complejo acaba llevando la situación al esperpento.
- Clave 2: Evitar la "sobreingeniería". En el caso de software orientado a objetos, el montar un "pifostio" con 10 veces más clases de las necesarias, sólo para demostrar que alguien se ha leído el libro de "patrones de diseño de turno" tiene un coste brutal. Para hacer mantenimiento implica una curva de aprendizaje importante, dificultando que las correcciones mantengan el "enfoque" original.
- Clave 3: Buscar de motu proprio la simplificación de las cosas, como actitud. Hay que aprender a que identificar cosas innecesarias es muy productivo, pues hacer algo que no se necesita es tirar el tiempo/dinero.
- Clave 4: No se puede ahorrar en la estabilidad del software. Si algo está mal sincronizado, es un bug crítico y hay que corregirlo, punto. El sacar a producción algo defectuoso puede ocasionar costes brutales de mantenimiento y soporte técnico, sin contar la mala imagen que proyecta.
- Clave 5: Identificación de las limitaciones. En el software, salvo casos excepcionales, los "todologos" (gente que "sabe" y discute de todo) son muy peligrosos. Una solución objetivable e impepinable para este punto son los hechos: opinión tiene todo el mundo, pero opinión respaldada por hechos, no. Una vez se es consciente de las limitaciones, se puede aprender de quien realmente sabe, con humildad y sin aspavientos.
- Clave 6: Planificación y supervisión de los desarrollos por parte de gente de más talento/conocimientos/experiencia. El que sabe menos tiene que aprender del que sabe más, con humildad y disciplina (i.e. que no sea "el coño de la tía Bernarda"). Si se ignora esto, jamás se sale de la mediocridad. Por mi experiencia, los desarrollos sin supervisión adolecen siempre de un problema u otro: calidad, productividad (e.g. retrasos), falta de visión de conjunto que generarán costes a otros componentes en el futuro, etc.
- Clave 7: Seguimiento (subconjunto de la supervisión). No puede ser que para una proyecto estimado en 2 meses, lleguen los dos meses, y te enteres de que es un desastre. Esto, por mi experiencia, mejora notablemente con un análisis de riesgos dentro de la planificación (sea público o no), y acciones a tomar, e.g. comprobaciones en el 30%, 50% y 70% del desarrollo. Ya sea mediante gestión "tradicional" o técnicas "agile" (centradas en un seguimiento exhaustivo y división de tareas al extremo, aún cuando en estos casos también se hace fraude "a lo Enron"), si no hay seguimiento y gestión de impedimentos/imprevistos/contingencias, el tema no marchará.
- Clave 8: Consciencia de que programar bien es difícil, y que no se aprende en 21 días, y que hay gente que necesita 10 años, otros 20, y otros no aprenden a programar bien nunca (si son conscientes, no es un problema, y conociendo sus limitaciones pueden llegar a grandes logros basados en múltiples elementos sencillos).
- Clave 9: Consciencia de que, aunque se pueda intentar dentro de lo posible, no siempre se pueden establecer reglas a gusto de todo el mundo, y que, por ejemplo, pueden tener sentido usar procesos que puedan ser antipáticos para una parte de los desarrolladores (Windows / Linux / OSX dev wars) si supone reducir el coste de desarrollo de manera sustancial.
- Clave 10: No hay solución mágica. Además de buenos hábitos, talento, conocimientos, y experiencia, hay que trabajar duro.
5.3. Usa las mejores técnicas y herramientas
- Obtén el mejor hardware disponible para programar, para todos los miembros del equipo. La productividad que se pierde por usar herramientas no adecuadas es brutal. Además, con hardware adecuado, i.e. mucha CPU y RAM (e.g. 8-16GB de RAM y 4-8 cores), puedes tener múltiples entornos de desarrollo con diferentes sistemas operativos, etc.
- Usa un gestor de versiones que reduzca el tiempo de sincronización entre desarrolladores. Es estúpido usar gestores de versiones poco flexibles o que te hagan tardar media hora para hacer un merge trivial.
- Planifica las releases. Ya sea por ramas, agrupación de componentes, o lo que sea, pero que se adecúe a las capacidades y tenga en cuenta el coste y dependencias.
- Ten scripts que compilen el código, para todas las plataformas soportadas (e.g. para llamar a todos los makefiles y/o proyectos de Visual Studio). Es inaceptable el no enterarse de que algo se ha roto. Si no lo conoces, échale un ojo a herramientas como Jenkins (antes llamado Hudson).
- Añade tests en cada desarrollo, aún cuando no hagáis TDD. Ya sea a nivel de clases, componentes, o lo que consideres oportuno para cada caso. No es un gasto, es inversión: Dedicar un 5-10% del tiempo de desarrollo a cobertura por tests (aún cuando estos sean sencillos y no cubran todas las posibilidades), reducirá de manera notable el coste de mantenimiento.
- Si desarrollas para múltiples plataformas, usa un método sencillo (e.g. Makefiles si se ha de soportar un número limitado de entornos POSIX e.g. Linux y OSX, automake/autoconf para los casos de soportar el máximo número de sistemas POSIX, junto con ficheros de proyecto para Visual Studio). En mi opinión, por ejemplo, para proyectos multiplataforma de C y C++, el mantener proyectos para Eclipse/NetBeans/Xcode es un error, puesto que para muchos proyectos el mantenimiento de estos es brutal (aún usando refritos como CMake, pues es un elemento de ruido más: compatibilidad de versiones determinadas entre diferentes SOs, etc.) Si incluso usando el Make pelado de GNU hay problemas de compatibilidades, usando generadores de "workspaces", es para alucinar en colores, salvo que se traten de pocos proyectos y te lo puedas permitir.
Sintonía de hoy:
« IBM dona el código de Symphony a la Apache Software Foundation | ¿Cómo fomentar entre los universitarios la emprendeduría? »
Historias relacionadas
Merluzo nos cuenta: «En el trabajo me ha tocado encargarme de un proyecto inmantenible e inactualizable con los recursos disponibles, lo que me tiene un poco abrumado. Leyendo esta semana me he encontrado con la mejor metáfora para describirlo: la "deuda técnica", el conjunto de chapuzas y parches cuyos arreglos se van postponiendo. Como desarrollador, te endeudas cada vez que escribes código sin documentarlo, cada semana que dejas que tu fork local se aleje del desarrollo de upstream. La metáfora funciona porque cuanto más tiempo dejas sin arreglar uno de estos apaños, más tiempo te costará pagar la deuda. Es como si los problemas devengaran intereses. En ocasiones hay que reescribirlo todo, lo que en nuestra metáfora es el equivalente de declararse en bancarrota (y que puede llevar a la bancarrota real si no hay tiempo y dinero para asumir el desarrollo necesario). ¿Te has encontrado tú con problemas de endeudamiento técnico? ¿Cómo te arreglaste sin llegar a la ruina?»

Gracias por los consejos pero...
(Puntos:2)( http://noalprestamodepago.org/ | Última bitácora: Sábado, 23 Julio de 2011, 16:18h )
Salvando las diferencias, me recuerda un poco a las actividades de "coaching" que últimamente se han puesto tan de moda. Todo es positivo, hermoso, maravilloso, solucionable... pero parece que los "coach" no han trabajado en una empresa española en su vida.
Caso práctico
(Puntos:1, Interesante)En mi empresa tenemos este ejemplo, y hemos aplicado los mismos arreglos que propones: "otras tareas" y "orientación".
Resultado: el programador en cuestión, de >9 años de experiencia, que ha sido como dices en el artículo "permanentente mediocre" se cree menospreciado y "la puta de la oficina" que va de tarea en tarea y anda buscando un curro para largarse de aquí.
Las buenas ideas y motivaciones de este artículo chocan con la personalidad de la gente en muchos casos...
Muy buen texto
(Puntos:1)( http://barrapunto.com/ | Última bitácora: Viernes, 05 Agosto de 2011, 12:28h )
Has pensado en ponerle un titulo estupido, rellenarlo de paja y venderselo a managers? Tu te harias de oro y quizas entonces nos dejen a los tecnicos hacer nuestro trabajo (aunque si no lo consiguio Fred Brooks con su mythical man-month, dudo que te hagan caso).
Dale fuego a un hombre y estara caliente un dia, prendele fuego y estara caliente el resto de su vida.
dudas
(Puntos:2)( Última bitácora: Martes, 07 Diciembre de 2010, 18:45h )
Mientras iba leyendo he ido identificando mentalmente cada parte con el caso real donde trabajo.
En la metodología para reducir la deuda tecnológica que describes, indicas que hay que diferenciar en el punto B, lo que no funciona bien porque hace "crash" (B1), y lo que es horrible a nivel de código aunque funciona bien como caja negra (B2)
La dudas que tengo son:
duda 1) ¿que se hace luego con las partes detectadas de B2?
duda 2) ¿y si se da el caso llamémosle "B3": "que funciona bien pero no es una caja negra"?
Un ejemplo: tenemos un "monstruo" de aplicación web que data del año 2000 y que no ha evolucionado en cuanto a tecnología. Es horrible a nivel de código: - sin diseño Modelo Vista-Controlador. Toda la lógica de la aplicación esta metida en las páginas jsp, que son gigantescas. Los jsps son un caos en los que va todo: desde la lógica con scriptlets, llamadas a la base de datos con sql, hasta código java que en ultima instancia sirve para pintar los elementos en pantalla
- utiliza librerías no estandar de las que no existe documentación, por ejemplo: en lugar de usar jdbc, toda la aplicación utiliza para el acceso a datos una librería que se coloca por encima del api jdbc. Tambien utiliza una especie de seudolibrería para la presentación que hace la función de pintar elementos html. El no usar tecnología estandar hace que los desarrolladores necesiten formación extra de la que no disponemos.
- No hay código de pruebas
La aplicación funciona "bien", pero adolece de una interfaz de usuario amigable. Además es practicamente imposible meterle mano, por lo que cuando hay que corregir algo o cambian los requisitos, el monstruo crece otro poco.
Mediante la refactorización se podría ir corrigiendo poco a poco, pero cuesta mucho menos hacer la aplicación entera de nuevo.
(Reflexión personal)... posiblemente el llamado "B3" en este caso es intratable. Habría que tratar la aplicación entera como un "B2" y no tocarla. En nuestro caso lo único que podría aprovecharse de la aplicación es el modelo de datos. He pensado que una posiblidad sería plantear una arquitectura-infraestructura MVC con tecnología estandar nueva (JPA, JSF, spring) partiendo de ingeniería inversa, integrarlo en paralelo con el código existente y a partir de ese momento toda modificación-corrección o nueva funcionalidad realizarla en el código bueno.
De acuerdo en un 99%
(Puntos:1, Interesante)liderazgo
(Puntos:1)