language agnostic - ¿Cómo se puede evitar que las soluciones provisionales duren para siempre?
language-agnostic (26)
Digamos que hay dos soluciones posibles para un problema: el primero es rápido pero raro; el segundo es preferible pero tomaría más tiempo implementarlo. Necesita resolver el problema rápidamente, por lo que decide implementar el truco lo más rápido que pueda, planeando comenzar a trabajar en la mejor solución luego. El problema es que, tan pronto como se alivia el problema, se desploma en la lista de tareas pendientes. Todavía está planeando implementar la mejor solución en algún momento, pero es difícil justificar su implementación en este momento. De repente, descubres que has pasado cinco años utilizando la solución menos que perfecta, maldiciéndolo mientras tanto.
¿Suena familiar? Sé que ha sucedido más de una vez donde trabajo. Un colega describe hacer deliberadamente una mala GUI para que no sea adoptada accidentalmente a largo plazo. ¿Tienes una mejor estrategia?
De repente, descubres que has pasado cinco años utilizando la solución menos que perfecta, maldiciéndolo mientras tanto.
Si lo estás maldiciendo, ¿por qué está en la parte inferior de la lista de pendientes?
- Si no te está afectando, ¿por qué lo estás maldiciendo?
- Si te está afectando, entonces es un problema que debe solucionarse AHORA.
Algunas soluciones que he visto en el pasado:
- Marcarlo con un comentario
HACK
en el código (o esquema similar comoXXX
) - Haga que se ejecute un informe automático y se envíe por correo electrónico semanalmente a aquellos que se preocupan, que cuenta cuántas veces aparecen los comentarios de
HACK
- Agregue una nueva entrada en su sistema de seguimiento de errores con el número de línea y la descripción de la solución correcta (para que el conocimiento obtenido de la investigación antes de escribir el truco no se pierda)
- escriba un caso de prueba que demuestre cómo el truco falla (si es posible) y verifíquelo en el conjunto de pruebas apropiado (es decir, para arrojar errores que eventualmente alguien quiera limpiar)
- una vez que el hack está instalado y la presión está desactivada, comience inmediatamente con la solución correcta
Esta es una excelente pregunta. Una cosa que noté fue que obtuve más experiencia: los piratas informáticos le compraban muy poco tiempo y, a menudo, le costaban una cantidad enorme. Estrechamente relacionado está la "solución rápida" que resuelve lo que crees que es el problema, solo para descubrir cuando explota que ese no era el problema en absoluto.
Aquí hay un gran artículo relacionado sobre deuda técnica .
Básicamente, es una analogía de la deuda con todas las decisiones técnicas que toma. Hay una buena deuda y una mala deuda ... y tiene que elegir la deuda que va a lograr los objetivos que desea con el menor costo a largo plazo.
El peor tipo de deuda son los pequeños atajos acumulados que son análogos a la deuda de la tarjeta de crédito ... cada uno no duele, pero muy pronto estás en la casa pobre.
Buena suerte. En mi experiencia esto es casi imposible de lograr.
Una vez que bajes la pendiente resbaladiza de implementar un hack porque estás bajo presión, entonces también podrías acostumbrarte a vivir con él todo el tiempo. Casi NUNCA hay tiempo suficiente para volver a trabajar algo que ya funciona, no importa cuán mal se implemente internamente. ¿Qué te hace pensar que mágicamente tendrás más tiempo "en una fecha posterior" para arreglar el truco?
La única excepción que se me ocurre a esta regla es si el truco le impide completamente implementar otra funcionalidad que necesita un cliente. Entonces no tienes más remedio que volver a trabajar.
Confesión:
He utilizado ''#define private public'' en C ++ para leer datos de otra capa de código. Fue un truco pero funciona bien y solucionarlo nunca se ha convertido en una prioridad. Ahora es 3 años después ...
Una de las razones principales por las que los hacks no se eliminan es el riesgo de que uno introduzca nuevos errores al arreglar el hack. (Especialmente cuando se trata de bases de código pre-TDD.)
Dejando de lado el debate sobre si debes hacerlo, supongamos que tienes que hacerlo. El truco ahora es hacerlo de una manera que minimice los efectos de largo alcance, se arranca fácilmente más tarde y se convierte en una molestia por lo que recuerda arreglarlo.
La parte molesta es fácil: haga que emita una advertencia cada vez que ejecute el kludge.
La parte arrancada puede ser fácil: me gusta hacer esto poniendo el kludge detrás de un nombre de subrutina. Eso facilita la actualización ya que compartimentaliza el código. Cuando obtienes tu solución permanente, tu subrutina puede implementarla o no hacer nada. A veces, una subclase puede funcionar muy bien para esto también. Sin embargo, no dejes que otras personas dependan de tu solución rápida. Es difícil recomendar cualquier técnica en particular sin ver la situación.
Minimizar los efectos de largo alcance debería ser fácil si el resto del código es agradable. Siempre vaya a través de la interfaz publicada, y así sucesivamente.
Eduque a quien sea que esté a cargo de tomar la decisión final sobre por qué la forma hacky de hacer las cosas es mala a largo plazo.
- Describe el problema en términos con los que se pueden relacionar.
- Incluye un gráfico de costo, productividad e ingresos.
- Enséñeles sobre la deuda técnica .
- Reorganice regularmente si lo empujan hacia adelante.
- Nunca lo llame "refactorización" o "volver atrás y limpiar" frente a personas no técnicas. En su lugar, llámalo "adaptar" el sistema para manejar "nuevas funciones".
Básicamente, las personas que no entienden el software no tienen el concepto de revisar las cosas que ya funcionan. La forma en que lo ven, los desarrolladores son como mecánicos que quieren seguir desmontando y volviendo a ensamblar todo el automóvil cada vez que alguien quiere agregar una característica, lo que les parece una locura.
Ayuda a hacer analogías con las cosas cotidianas. Explíqueles cómo, cuando creó la solución provisional, tomó decisiones que le sirvieron para construirla rápidamente, en lugar de ser estable, mantenible, etc. Es como elegir construir con madera en lugar de acero porque la madera es más fácil de cortar y, por lo tanto, podrías construir la solución provisional más rápido. La madera, sin embargo, simplemente no puede soportar la base de un edificio de 20 pisos.
El precio real de introducir una solución rápida es que cuando alguien más necesita introducir una segunda solución rápida, la presenten según su propia solución rápida. Por lo tanto, cuanto más tiempo se implemente una solución rápida, más arraigado se volverá. Muy a menudo, un truco toma solo un poco más de tiempo que hacer las cosas bien, hasta que te encuentras con un segundo truco que se basa en el primero.
Entonces, obviamente es (o parece ser) a veces necesario introducir una solución rápida.
Una posible solución, suponiendo que el control de tu versión lo respalde, es introducir una bifurcación de la fuente cada vez que hagas un hack. Si se alienta a las personas a evitar la codificación de nuevas características dentro de estas horquillas especiales de "hazlo listo", entonces con el tiempo será más trabajo integrar las nuevas características con el tenedor de lo que será para deshacerte del truco. Sin embargo, es más probable que el tenedor "bueno" sea descartado. Y si estás lo suficientemente lejos de la liberación que hacer una bifurcación de este tipo no será práctico (porque no vale la pena realizar la integración dual mencionada anteriormente), entonces probablemente ni siquiera deberías estar usando un hack.
Un enfoque muy idealista.
Una solución más realista es mantener su programa segmentado en tantos componentes ortogonales como sea posible y ocasionalmente hacer una reescritura completa de algunos de los componentes.
Una mejor pregunta es por qué la solución hacky es mala. Si es malo porque reduce la flexibilidad, ignórelo hasta que necesite flexibilidad. Si es malo porque tiene un impacto en el comportamiento de los programas, ignórelo y eventualmente se convertirá en una corrección de errores y se resolverá. Si es malo porque se ve feo, ignóralo, siempre que el truco esté localizado.
Es una llamada difícil. He hecho hacks personalmente porque a veces TIENES que sacar ese producto de la puerta y ponerlo en manos de los clientes. Sin embargo, la forma en que me ocupo de eso es simplemente hacerlo.
Informe al jefe del proyecto, a su jefe o al cliente: hay algunos puntos que deben limpiarse y codificarse mejor. Necesito una semana para hacerlo, y va a costar menos hacerlo ahora, luego será hacerlo dentro de 6 meses, cuando tengamos que implementar una extensión en el subsistema.
Escribe un caso de prueba que falla el truco.
Si no puede escribir una prueba que falla el truco, entonces o bien no hay nada de malo con el truco, o bien su marco de prueba es inadecuado. Si el primero, huye rápido antes de perder tu vida en la optimización innecesaria. Si es este último, busca otro enfoque (ya sea para marcar hacks, o para probar ...)
Este es un problema importante cuando se trabaja en un plazo determinado. Encuentro que agregar comentarios muy detallados sobre por qué se eligió esta forma y algunos consejos sobre cómo se debe codificar la ayuda. De esta forma, las personas que miran el código lo ven y lo mantienen fresco.
Otra opción que funcionará es agregar un bug.feature en su marco de seguimiento (usted sí tiene uno, ¿verdad?) Que detalla la repetición. De esta manera, es visible y puede forzar el problema en algún momento.
Esto me recuerda la historia de "CTool". Al principio CTool fue presentado por uno de nuestros desarrolladores, lo llamaré Don, como una posible forma de resolver el problema que estábamos teniendo. Siendo un tipo serio y trabajador, Don se desconectó y entregó un prototipo funcional. Ya sabes a dónde voy con esto. De la noche a la mañana, CTool se convirtió en parte del flujo de trabajo de la empresa con un departamento completo que depende de él. Al segundo o tercer día, empezaron a surgir amargas quejas sobre las deficiencias de CTool. Los usuarios cuestionaron la competencia, el compromiso y el coeficiente de inteligencia de Don. Las protestas de Don de que esto nunca se suponía que fuera una aplicación de producción cayeron en oídos sordos. Esto continuó por años . Finalmente, alguien pudo volver a escribir la aplicación, mucho después de que Don se fuera. En este momento, tanto odio se había unido al nombre CTool que nombrarlo CTool versión 2 estaba fuera de discusión. Hubo incluso un funeral formal para CTool, algo que recuerda a la escena de ejecución de la copiadora (¿o era una impresora?) En Office Space .
Algunos podrían decir que Don se merecía las hondas y las flechas por no hacer que vaya bien para reparar CTool. Mi único punto es que decir que nunca deberías hackear una solución es probablemente injustificable en el mundo real. Pero si usted es el que lo hace, pise con cautela.
Estrategia 1 (casi nunca seleccionada): No implemente el kluge. Ni siquiera dejes que la gente sepa que es una posibilidad. Solo hazlo de la manera correcta la primera vez. Como dije, casi nunca se selecciona esta, debido a limitaciones de tiempo.
Estrategia 2 (deshonesto): Lie and Cheat. Dile a la gerencia que hay errores en el truco, y que podrían causar problemas graves más adelante. Desafortunadamente, la mayoría de las veces, los gerentes solo dicen que esperen hasta que los errores se conviertan en un problema, y luego corrigen los errores.
Estrategia 2a: Igual que la estrategia 2, excepto que realmente hay errores. El mismo problema, sin embargo.
Estrategia 3 (y mi favorito personal): Diseña la solución siempre que puedas, y hazlo lo suficientemente bien como para que un interno o mono de código pueda hacerlo. Es más fácil justificar gastar la pequeña cantidad de dinero de código-mono que justificar su propio salario, por lo que podría hacerse.
Estrategia 4: Espere una reescritura. Seguir esperando. Tarde o temprano (probablemente más tarde), alguien tendrá que reescribir la cosa. Bien podría hacerlo en ese momento.
Gran pregunta Esto también me molesta mucho, y la mayoría de las veces soy la única persona responsable de priorizar los problemas en mis propios proyectos (sí, pequeña empresa).
Descubrí que el problema que debe solucionarse suele ser solo un subconjunto del problema. IOW, el cliente que necesita una solución urgente no necesita resolver todo el problema, solo una parte, más pequeña o más grande. A veces, esto me permite crear una solución alternativa que no es la solución al problema completo, sino solo al subconjunto del cliente, y eso me permite dejar el problema más grande abierto en el rastreador de problemas.
Eso, por supuesto, puede no aplicarse en absoluto a su entorno de trabajo :(
Intente que el costo del truco sea claro para la gente de negocios. Entonces pueden tomar una decisión informada de cualquier manera.
Intento construir la solución hacky para que pueda migrar a largo plazo de la forma más indolora posible. Supongamos que tiene un tipo que está creando una base de datos en SQL Server porque es su base de datos más sólida, pero su estándar corporativo es Oracle. Cree la base de datos con tan pocas características no transferibles (como tipos de datos Bit) como sea posible. En este ejemplo, no es difícil evitar los tipos de bits, pero hace que la transición más tarde sea un proceso más fácil.
La única vez que puede justificar arreglar estas cosas (porque no están realmente rotas, solo son feas) es cuando tiene otra característica o corrección de errores que toca la misma sección de código, y también podría volver a escribirla.
Tienes que hacer los cálculos sobre cuánto cuesta el tiempo de un desarrollador. Si se cumplen los requisitos del software, y lo único malo es que el código es embarazoso, no merece la pena solucionarlo.
Empresas enteras pueden ir a la quiebra porque los ingenieros demasiado entusiastas insisten en una nueva arquitectura cada año más o menos cuando se ponen ansiosos.
Si no tiene errores y cumple con los requisitos, ya está hecho. Envíalo. Siga adelante.
[Editar]
Por supuesto, no estoy abogando por que se piratee todo en todo momento. Debe diseñar y escribir el código cuidadosamente en el curso normal del proceso de desarrollo. Pero cuando terminas con hacks que solo deben hacerse rápidamente, tienes que hacer un análisis de costo-beneficio sobre si vale la pena o no para limpiar el código. Si durante la vida útil de la aplicación pasarás más tiempo codificando alrededor de un hack desordenado de lo que lo habrías arreglado, entonces por supuesto, resuélvelo. Pero si no, es demasiado costoso y arriesgado volver a codificar una aplicación que funciona sin errores solo porque mirar la fuente te pone enfermo.
Mi respuesta es un poco diferente a las demás. Mi experiencia es que las siguientes prácticas te ayudan a mantenerte ágil y pasar de las primeras soluciones de iteración / alfa de Hackey a listas beta / producción:
Desarrollo impulsado por prueba
Pequeñas unidades de refactorización
- Integración continua
- Buena gestión de configuración
- Técnicas de bases de datos ágiles / refactorización de bases de datos
Y no hace falta decir que tiene que contar con el apoyo de los interesados para hacer cualquiera de estos correctamente. Pero con estos productos en su lugar, tiene las herramientas y procesos adecuados para cambiar rápidamente un producto de manera importante y con confianza. A veces, su capacidad de cambiar es su capacidad para gestionar el riesgo de los cambios y, desde la perspectiva del desarrollo, estas herramientas / técnicas le brindan una base más segura.
NO HACES SOLUCIONES PROVISIONALES
A veces creo que los programadores solo necesitan que les digan esto.
Lo siento, pero en serio: una solución hacky no tiene ningún valor e incluso en la primera iteración puede llevar más tiempo que una parte de la solución.
Por favor deja de dejarme tu código de mierda para mantener. SIEMPRE CÓDIGALO BIEN. No importa cuánto tiempo tome y quién te grite.
Cuando estás sentado allí jugueteando con tus pulgares después de entregar temprano mientras todos los demás están depurando sus estúpidos hacks, me lo agradecerás.
Incluso si no piensa que es un gran programador, siempre trate de hacer lo mejor que pueda, nunca tome atajos, no le CUALQUIER tiempo hacerlo bien. Puedo justificar esta afirmación si no me crees.
Podrías escribirlo intencionalmente de manera demasiado restrictiva y encaminada y requeriría una nueva escritura para ser modificado.
Por lo general, problemas como este surgen de una mala comunicación con la administración o el cliente. Si la solución funciona para el cliente, entonces no ve razón para pedir que se cambie. Por lo tanto, es necesario que se les informe acerca de las compensaciones que hicieron de antemano para que puedan planificar un tiempo adicional para solucionar los problemas después de que haya implementado la solución rápida.
Cómo resolverlo depende un poco de por qué es una mala solución. Si su solución es mala porque es difícil cambiarla o mantenerla, la primera vez que tiene que hacer mantenimiento y tener un poco más de tiempo, ese es el momento adecuado para actualizar a una solución mejor. En este caso, ayuda si le dice al cliente o a su jefe que tomó un atajo en primer lugar. De esa forma, saben que no pueden esperar una solución rápida la próxima vez. La eliminación de la IU puede ser una buena forma de asegurarse de que el cliente regrese para solucionar el problema.
Si la solución es mala porque es arriesgada o inestable, entonces realmente necesita hablar con la persona que hace la planificación y tener un tiempo planeado para solucionar el problema lo antes posible.
Tuvimos que hacer esto una vez: crear una versión demo a corto plazo que sabíamos que no queríamos mantener. El cliente lo quería en una caja winTel, por lo que desarrollamos el prototipo en SGI / XWindows. (Hablamos con fluidez en ambos, así que no fue un problema).
Usamos Java y Hudson para una integración continua. Las ''soluciones provisionales'' deben comentarse con:
// TODO: Better solution required.
Cada vez que Hudson ejecuta una compilación, proporciona un informe de cada ítem TODO para que tengamos un registro actualizado y altamente visible de cualquier ítem destacado que necesite mejorarse.
Usted archiva un segundo error muy descriptivo contra su propio "arreglo" y pone un comentario por hacer en las áreas afectadas que dice: "Esta área necesita mucho trabajo. Vea el defecto # 555" (use el número correcto de curso) . La gente que dice "no hagas un truco" no parece entender la pregunta. Asuma que tiene un sistema que necesita estar listo para funcionar ahora, su solución no pirateada es 8 días de trabajo, su truco es 38 minutos de trabajo, el truco está ahí para comprarle tiempo para hacer el trabajo y no perder dinero mientras lo estás haciendo.
Ahora todavía tiene que conseguir que su cliente o la gerencia acuerden programar los N * 100 minutos necesarios para realizar la reparación real, además de los N minutos necesarios para solucionarlo. Si debe negarse a implementar el hack hasta que obtenga dicho acuerdo, entonces tal vez eso es lo que tiene que hacer, pero he trabajado con algunas personas comprensivas en ese sentido.
- Me aseguro de expresar la prioridad de la solución a largo plazo ESPECIALMENTE después de que se haya solucionado el problema a corto plazo.
- Detallo los motivos por los que es un truco y no una buena solución a largo plazo y los utilizo para lograr que los interesados (gerentes, clientes, etc.) comprendan por qué es necesario solucionarlo
- Dependiendo del caso, incluso puedo inyectar un poco del peor de los casos de miedo allí. "¡Si esta línea de seguridad se rompe, todo el puente podría colapsar!"
- Asumo la responsabilidad de encontrar una solución a largo plazo y me aseguro de que se implemente
Consíguelo por escrito (un correo electrónico). Entonces, cuando se convierte en un problema, la gerencia no "olvida" que se suponía que era temporal.
Haz que sea visible para los usuarios. Mientras más visible sea, es menos probable que las personas olviden retroceder y hacerlo de la manera correcta cuando termine la crisis.
Negocie antes de que la solución temporal esté lista para un proyecto, recursos y líneas de tiempo para obtener la solución real. El trabajo para la solución real probablemente debería comenzar tan pronto como termine la solución temporal.