1. Validación de entrada:
* Verificación de tipo de datos: Asegúrese de que las entradas sean del tipo de datos esperado (entero, cadena, flotación, etc.). No confíe en la entrada del usuario o los datos de fuentes externas implícitamente.
* Verificación de rango: Verifique que las entradas numéricas caen dentro de los rangos aceptables. Por ejemplo, una cantidad no puede ser negativa.
* Verificación de longitud: Limite la longitud de las cuerdas para evitar los desbordamientos del amortiguador u otros problemas.
* Comprobación de formato: Confirme que las entradas se ajusten a un formato específico (por ejemplo, dirección de correo electrónico, fecha).
* desinfectación: Eliminar o escapar de los caracteres potencialmente dañinos (por ejemplo, etiquetas HTML, caracteres de inyección SQL) de las entradas del usuario antes de procesarlas.
2. Manejo de errores:
* Manejo de excepciones (bloques Try-Except): Use el manejo de excepciones estructurado para atrapar con gracia y manejar errores anticipados (como el archivo no encontrado, problemas de conexión de red, entrada no válida) que evita los bloqueos del programa.
* Afirmaciones: Use las declaraciones de 'afirmar' para verificar las condiciones que * siempre deberían ser verdaderas. Si una afirmación falla, indica un error de programación. Las afirmaciones son principalmente para la depuración.
* Códigos de retorno/indicadores de error: Las funciones pueden devolver códigos o banderas específicos para indicar éxito o diferentes tipos de falla.
* Registro: Los eventos registrados, incluidos errores y advertencias, a un archivo de registro para análisis y depuración posteriores. Esto es crucial para identificar problemas en los entornos de producción.
3. Predeterminados a prueba de fallas:
* Valores predeterminados: Proporcione valores predeterminados sensibles para variables o parámetros cuando faltan las entradas o no son válidas.
* Mecanismos de retroceso: Implemente estrategias alternativas o mecanismos de respuesta cuando las operaciones primarias fallan (por ejemplo, utilizando un valor en caché si falla una consulta de base de datos).
4. Gestión de recursos:
* Cierre adecuado de recursos: Asegúrese de que los recursos como archivos, conexiones de red y conexiones de bases de datos estén correctamente cerradas incluso si ocurren errores (usando bloques `finalmente` o construcciones similares). Esto evita las fugas de recursos.
* Gestión de memoria: Preste atención a la asignación de memoria y la desacoplación para evitar fugas de memoria y punteros colgantes.
5. Simplicidad y legibilidad del código:
* Diseño modular: Desglose las tareas complejas en módulos más pequeños y bien definidos para facilitar el código de entender, probar y mantener.
* Nombres significativos: Use los nombres de funciones de variable y funciones descriptivas para mejorar la legibilidad del código y facilitar la comprensión de la lógica.
* Comentarios y documentación: Agregue comentarios claros y concisos para explicar partes complejas del código y su propósito.
6. Pruebas:
* Prueba unitaria: Pruebe componentes o funciones individuales del programa de forma aislada.
* Prueba de integración: Pruebe cómo funcionan los diferentes componentes juntos.
* Prueba de regresión: Vuelva a probar el programa después de hacer cambios para garantizar que la funcionalidad existente no se haya roto.
* Análisis de valor límite: Pruebe el programa con entradas en los bordes de los rangos válidos.
* Prueba de estrés: Pruebe el programa con altos volúmenes de datos o condiciones inusuales.
Las técnicas de programación defensiva agregan gastos generales en términos de tiempo de desarrollo y complejidad del código. Sin embargo, la mejor robustez y confiabilidad del software resultante generalmente supera con creces este costo, particularmente en aplicaciones críticas donde las fallas pueden tener graves consecuencias.