“Poner parches” o “apuntalar con muletas” significa crear una solución temporal a un problema que corrige un error o agrega funcionalidad, pero no elimina la causa raíz ni cumple con los estándares arquitectónicos del proyecto. Las muletas son inevitables en cualquier desarrollo: los plazos, la comprensión incompleta del sistema y las limitaciones externas obligan a tomar decisiones de compromiso. Según Refactoring Guru, la diferencia clave entre una muleta pragmática y la deuda técnica está en la conciencia de la decisión y la existencia de un plan para eliminarla. El uso competente de soluciones temporales requiere disciplina y documentación.
Puntos clave
Una muleta (crutch) es una solución de software que funciona pero está hecha “apresuradamente”: soluciona un problema específico pero no elimina su causa, no sigue la arquitectura del proyecto y puede romperse con los más mínimos cambios en el entorno. La metáfora es precisa: como una muleta real, ese código ayuda a “caminar” pero no cura la “pierna.”
Los desarrolladores “apuntalan con muletas” errores, incompatibilidades de versiones, peculiaridades de la plataforma y requisitos urgentes del cliente. Una muleta típica es una muleta condicional: si iOS 15, agrega un margen; si Huawei, oculta el botón. Estas comprobaciones se multiplican y convierten el código en un “pastel de capas” de ramas de plataforma y versión.
Las muletas vienen en diferentes escalas: desde una sola línea con una condición de muleta hasta un módulo envolvente completo que “corrige” el comportamiento de una biblioteca. Es importante entender que una muleta no siempre es mala: en las manos adecuadas, es una herramienta que permite lanzar un producto a tiempo. El problema comienza cuando la muleta permanece en el código para siempre.
La razón principal por la que aparecen las muletas es el conflicto entre la solución ideal y las restricciones reales del proyecto. El desarrollador sabe cómo hacerlo correctamente, pero el tiempo, el dinero o las limitaciones técnicas lo impiden. Como resultado, surge una solución de compromiso que “simplemente funciona.”
Veamos cuatro razones principales por las que los desarrolladores recurren conscientemente a las muletas. Comprender estas razones ayuda a tratar las muletas no como un error sino como una herramienta pragmática que necesita ser gestionada.
La razón más común. El lanzamiento es mañana, el error se reproduce solo en un modelo específico, y corregirlo arquitectónicamente tomaría dos semanas. Una muleta condicional toma una hora y soluciona el problema. Después del lanzamiento, el equipo promete volver y reescribirlo correctamente. “Nada es más permanente que una solución temporal” — eso es exactamente sobre estas muletas.
La biblioteca A requiere Android 12, pero tu aplicación soporta Android 10. La solución es escribir un envoltorio que verifique la versión del SO y seleccione la ruta de ejecución. Esto es una muleta porque cuando se actualice la biblioteca, el envoltorio tendrá que reescribirse. Pero la alternativa — abandonar la biblioteca o el soporte para dispositivos antiguos — podría ser peor.
// Muleta para compatibilidad con API 29
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
useModernApi()
} else {
useLegacyFallback()
}
Una biblioteca de la que depende el proyecto tiene un error, pero actualizarla podría llevar semanas (se necesita PR, revisión de código, publicación). En lugar de esperar, el equipo escribe un envoltorio que parchea el comportamiento de la biblioteca sobre la marcha. Cuando se publique la versión corregida de la biblioteca, se elimina el envoltorio. Si no se elimina, eso ya es un problema arquitectónico.
Un desarrollador nuevo en un proyecto legacy no entiende por qué el código funciona como lo hace. En lugar de averiguarlo, agrega una nueva condición sobre las existentes. Este es el tipo de muleta más peligroso porque el autor no se da cuenta de que es una muleta. El único remedio es la revisión de código y la programación en pareja para los nuevos miembros del equipo.
No toda muleta es mala. En el desarrollo real, la pureza absoluta del código es inalcanzable y a menudo poco práctica. Un enfoque pragmático reconoce que las soluciones temporales son parte del proceso, pero requiere conciencia, documentación y un plan de eliminación. Una muleta está justificada cuando resuelve un problema de negocio más rápido que una solución arquitectónica limpia.
Los criterios para una muleta justificada: soluciona un problema específico, tiene un responsable (alguien encargado de su eliminación) y existe un plan de refactorización. Si falta al menos una de estas tres condiciones, la muleta se convierte en deuda técnica. Herramientas como los comentarios TODO con un ticket en el tracker son el método mínimo de documentación.
Un error crítico en la rama de lanzamiento que debe corregirse antes del despliegue de mañana. La solución limpia requiere refactorización arquitectónica y tomaría dos semanas. La muleta: agregar una comprobación de nil y enviar la corrección como hotfix. Condiciones de justificación: se ha creado un ticket de refactorización en el tracker, se ha asignado un responsable y la muleta está marcada con un comentario. Dos semanas después, el equipo vuelve a la tarea.
// TODO: IT-1234 — eliminar esta muleta después de la refactorización de AuthService
guard let userId = session.user?.id else {
return Result.failure(.notAuthenticated)
}
El límite entre una muleta consciente y un problema arquitectónico (deuda técnica) se define por dos parámetros: la conciencia de la decisión y la existencia de un plan para eliminarla. Una muleta es siempre una solución temporal con una vida útil conocida. La deuda técnica es la consecuencia de muchas muletas dejadas sin atención.
| Parámetro | Muleta consciente | Deuda técnica |
|---|---|---|
| Conciencia | El equipo sabe que es una solución temporal | Nadie recuerda por qué el código es así |
| Documentación | Tiene TODO, un ticket en el tracker | Sin comentarios, referencias ni descripciones |
| Plan de eliminación | Se ha asignado un sprint para la refactorización | “Algún día lo reescribiremos” |
| Impacto | Local, no interfiere con nuevas funcionalidades | Bloquea cambios, ralentiza el desarrollo |
La situación empeora cuando el número de muletas supera una masa crítica. Cada nueva muleta aumenta la “fragilidad” del sistema: un cambio en un lugar rompe otro. Con el tiempo, el desarrollo se ralentiza, los errores se multiplican y un desarrollador nuevo no puede entender el código sin la ayuda del autor. En este punto, las muletas dejan de ser soluciones temporales y se convierten en un problema arquitectónico.
Si el código contiene cinco comprobaciones anidadas de la versión del SO, el fabricante del dispositivo y la presencia de una biblioteca específica — esto no es una muleta, es un problema arquitectónico. Si agregar una corrección causa tres regresiones en módulos relacionados — las muletas ya no son locales. Si las revisiones de código se rechazan regularmente por “otra muleta más” — es hora de planificar la refactorización.
Refactorizar muletas es el proceso de reemplazar soluciones temporales por otras arquitectónicamente correctas. Esto lleva tiempo, por lo que se necesita una estrategia de priorización: no todas las muletas deben eliminarse de inmediato. Una buena estrategia es evaluar cada muleta según dos parámetros: la frecuencia de cambios en esa área del código y el impacto en los usuarios.
Prioridad alta — muletas en módulos que cambian con frecuencia (lógica de negocio, interfaz de usuario de propósito general) que ralentizan el desarrollo y causan regresiones. Prioridad media — muletas en módulos que rara vez cambian pero con impacto potencial en los usuarios (procesamiento de pagos, autorización). Prioridad baja — muletas en código heredado que funciona de manera estable y no está planificado para modificación.
Paso 1: inventario — encuentra todos los TODO y FIXME relacionados con muletas. Paso 2: evaluación — determina cuáles siguen siendo relevantes. Paso 3: planificación — programa la refactorización de muletas en un sprint, comenzando por las de alta prioridad. Paso 4: reemplazo — implementa la solución limpia, elimina la muleta y su comentario TODO. Paso 5: verificación — asegúrate de que las pruebas pasen y no haya regresiones.
# Encontrar todas las muletas TODO en el proyecto
grep -r "TODO\|FIXME\|HACK\|XXX" --include="*.kt" --include="*.swift" .
La mejor manera de combatir las muletas es no crearlas innecesariamente. Antes de escribir una muleta, hazte tres preguntas: ¿puedo implementar una solución limpia en un tiempo razonable? ¿Hay una alternativa que no sea una muleta? ¿Tendrá el equipo tiempo para volver y reescribir esto? Si la respuesta a al menos una pregunta es “no” — piensa de nuevo antes de “apuntalar” el código.
Preguntas frecuentes
Poner un parche significa escribir una solución temporal que soluciona el problema pero no elimina su causa. El código funciona pero no cumple con la arquitectura del proyecto y puede romperse con los cambios.
Una muleta es una solución temporal consciente con un plan de eliminación. La deuda técnica es la consecuencia de muchas muletas olvidadas. La muleta es local, la deuda es sistémica y bloquea el desarrollo.
Cuando el plazo es crítico, la solución limpia requiere tiempo y la muleta está documentada con un comentario TODO y un ticket en el tracker. La condición: la muleta tiene un plan de eliminación en un futuro previsible.
Agrega un TODO o FIXME con el número del ticket y una breve descripción de la solución correcta. Ejemplo: // TODO: IT-567 — rewrite using Factory pattern. Sin un ticket, la muleta será olvidada.
Realiza un inventario de todos los TODO, prioriza, comienza con los módulos que cambian con frecuencia. Reemplaza la muleta con una solución limpia, elimina el comentario y verifica con pruebas.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también