“Clavar a fuego” y “hardcodear” son términos de argot que significan la fijación rígida de valores directamente en el código del programa, en lugar de moverlos a la configuración. Hardcode es uno de los antipatrones más conocidos en desarrollo porque reduce la flexibilidad y reutilización del código. Según Refactoring Guru, el hardcode complica las pruebas, el mantenimiento y la adaptación de la aplicación a diferentes entornos. El uso consciente de constantes en lugar de hardcode es señal de una arquitectura madura.
Puntos clave
Hardcodear (clavar a fuego) — incrustar un valor específico en el código del programa de modo que para cambiarlo sea necesario editar el código fuente y recompilar la aplicación. La metáfora “clavar a fuego” refleja con precisión la esencia: el valor queda fijado permanentemente y solo se puede separar del código con esfuerzo.
Un ejemplo de hardcode es una URL de servidor escrita como cadena directamente en el cuerpo de una función. Si el servidor se muda a otra dirección, el desarrollador debe encontrar la cadena en el código, cambiarla, recompilar la aplicación y lanzar una nueva versión. En una aplicación con arquitectura adecuada, esa URL estaría en un archivo de configuración, una variable de entorno o un servicio de configuración.
El término “clavar a fuego” tiene una carga más emocional: enfatiza que el valor se inserta de forma permanente sin posibilidad de reemplazo rápido. En el entorno de habla rusa, ambas expresiones se usan como sinónimos completos con connotación negativa. A veces el hardcode se llama irónicamente “una constante extraída en una constante separada de una constante”.
Hardcode es un antipatrón porque viola los principios de mantenibilidad, testabilidad y extensibilidad. En el código donde los valores están “clavados a fuego”, cualquier cambio en el entorno, diseño o lógica requiere búsqueda y reemplazo manual en el código fuente. Esto aumenta el riesgo de errores y ralentiza el desarrollo.
Examinemos las consecuencias específicas del hardcode usando como ejemplo una aplicación móvil típica. Si el margen de todos los botones se define como un número en el código en lugar de a través de un recurso, cambiar el diseño requiere encontrar todas las ocurrencias y reemplazarlas. Si la URL del endpoint está hardcodeada, el cambio entre entornos (dev, stage, prod) es imposible sin recompilar.
| Consecuencia | Descripción | Nivel de criticidad |
|---|---|---|
| Dificultad de mantenimiento | Los cambios requieren buscar en todo el código | Alto |
| Errores de copia | No todas las ocurrencias se encuentran y reemplazan | Alto |
| Imposibilidad de probar | No se pueden sustituir datos de prueba | Medio |
| Problemas de localización | Los textos en código no se traducen | Medio |
| Complejidad en code-review | El revisor debe recordar todos los contextos | Bajo |
Una función que usa números mágicos y cadenas hardcodeadas es un ejemplo clásico de hardcode. Después de un mes, el autor no recordará qué significan 18, 0.07 y 2.5. Después de un año, nadie en el equipo se atreverá a cambiar estos números por miedo a romper la lógica. Extraer valores en constantes con nombre hace que el código sea autodocumentado.
// Bad: magic numbers and strings
fun calculatePrice(base: Double): Double {
val tax = base * 0.07
val tip = base * 0.15
val discount = if (base > 100) 10 else 0
return base + tax + tip - discount
}
Una URL de base de datos hardcodeada no permitirá ejecutar pruebas en una base de datos local in-memory. El desarrollador tendrá que levantar un servidor completo o modificar el código antes de probar. Sacar la configuración del código resuelve el problema: las pruebas usan parámetros de prueba, producción usa los reales y el código no cambia.
Hardcode es un antipatrón, pero existen excepciones legítimas donde un valor hardcodeado no solo es aceptable sino preferible. El límite se define por el eje de modificabilidad: si un valor nunca o casi nunca cambia durante el ciclo de vida de la aplicación, se puede hardcodear. Si pudiera cambiar potencialmente, muévalo a la configuración.
Constantes matemáticas y físicas — Pi, aceleración gravitacional, número de milisegundos en un segundo — son seguras para hardcode. Están definidas por la naturaleza o los estándares y no cambiarán. Tamaños de arrays constantes definidos por especificación también se pueden hardcodear, pero con un comentario sobre el origen del número.
El número de milisegundos en un segundo es una constante estable definida por el estándar de tiempo. No tiene sentido moverlo a un config porque nunca cambiará. Sin embargo, incluso estas constantes es mejor declararlas con un nombre claro para que el código no contenga “números mágicos”: en lugar de 1000, escriba MILLISECONDS_IN_SECOND.
// Justified hardcode: stable constants
private const val MILLIS_IN_SECOND = 1000
private const val LOGIN_TIMEOUT_SECONDS = 30
fun formatDuration(ms: Long): String {
val seconds = ms / MILLIS_IN_SECOND
return "${seconds} sec."
}
Existen varios métodos probados para evitar el hardcode, cada uno adecuado para su tipo de valores. La elección de la alternativa depende de la frecuencia con que cambie el valor y quién lo cambie: el desarrollador, devops o el usuario final.
Para URLs de servidores, claves de API y feature flags, use archivos de configuración en formatos JSON, YAML o TOML. En Android, esto incluye build.gradle con buildConfigField o res/values/config.xml. En iOS, Info.plist o xcconfig. Los configs se empaquetan con la aplicación pero pueden diferir según el esquema de compilación.
Para secretos (tokens, contraseñas) y parámetros de entorno, use variables de entorno. No terminan en el repositorio y pueden diferir en servidores dev, stage y prod. En desarrollo móvil, las variables de entorno a menudo se emulan mediante esquemas de compilación de Xcode o build flavors en Gradle.
Los textos, colores, tamaños e imágenes deben colocarse en archivos de recursos: strings.xml en Android, Localizable.strings en iOS, archivos ARB en Flutter. Esto simplifica la localización, la adaptación a diferentes pantallas y el modo oscuro. Cambiar un texto en los recursos no requiere reescribir código.
<!-- Android: res/values/strings.xml -->
<resources>
<string name="app_name">MyApp</string>
<string name="api_base_url">https://api.example.com</string>
</resources>
Para servicios y proveedores, use Dependency Injection mediante Dagger, Hilt o Koin en Android, Swinject en iOS. Los frameworks DI permiten intercambiar implementaciones sobre la marcha — para pruebas, diferentes entornos o diferentes usuarios. Este es el nivel más alto de abstracción, donde “clavar a fuego” un valor se reemplaza por inyección externa.
Refactorizar hardcode es el proceso de extraer valores hardcodeados en configuración o recursos. Es una de las operaciones de refactorización más seguras si se realiza metódicamente. La secuencia siguiente funciona para cualquier lenguaje y plataforma.
La búsqueda se puede hacer a través del IDE (Search in Project) o con un script. Busca cadenas, URLs, literales numéricos, tamaños y timeouts. Presta especial atención a los valores duplicados: si el mismo número aparece en cinco lugares, es candidato para extraerlo en una constante. Usa grep o la búsqueda integrada de IDEA / Xcode.
Para cada valor encontrado, crea una constante con un nombre significativo. Agrupa las constantes por módulos o clases. El nombre debe explicar qué significa el valor, no cómo se usa: API_TIMEOUT, no TIMEOUT_30. Después del reemplazo, ningún número en el código debe quedar sin explicación.
// Before: magic number 0.4
let cardHeight = screenHeight * 0.4
// After: named constant
private let cardHeightRatio: CGFloat = 0.4
let cardHeight = screenHeight * cardHeightRatio
Si el valor puede cambiar entre compilaciones o entornos, muévelo a un archivo de configuración o recursos de la aplicación. Para textos, usa archivos de localización. Para URLs, usa build config o xcconfig. Para dimensiones, usa archivos de recursos (dimens.xml en Android). Verifica que la aplicación se compile y funcione correctamente después de la extracción.
Después de la refactorización, escribe una prueba que verifique que la configuración se carga correctamente y que los valores coinciden con lo esperado. Si alguien cambia el config en el futuro, la prueba indicará la discrepancia. Una prueba de configuración es una forma rápida y fiable de prevenir regresiones.
Después de mover a config, verifica que todos los lugares que usaban el valor antiguo ahora referencien una fuente única. Elimina el código comentado y las constantes antiguas que ya no se usen. Finaliza la refactorización con un commit cuyo mensaje describa qué valores se movieron y adónde.
Preguntas frecuentes
Hardcodear — escribir un valor de forma rígida en el código fuente en lugar de colocarlo en la configuración o recursos. Esto hace que el código sea menos flexible y más difícil de mantener.
Hardcode complica cambiar el comportamiento de la aplicación, dificulta las pruebas, crea duplicación y aumenta el riesgo de errores de copia. Cambiar un valor hardcodeado requiere recompilar y redistribuir la aplicación.
Aceptable para constantes matemáticas, valores estables que no cambian durante el ciclo de vida de la aplicación y prototipos temporales. En producción, incluso las constantes deben extraerse en variables con nombre.
Encuentra todos los números mágicos mediante búsqueda, reemplázalos con constantes con nombre o muévelos a un archivo de configuración. Escribe una prueba que verifique la carga de la configuración. Elimina duplicados y haz un commit describiendo los cambios.
Una constante es un valor con nombre en el código que se puede cambiar en un solo lugar. Hardcode son valores sin nombre dispersos por el código. Buena práctica: usar siempre constantes con nombre significativo.
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