Tengo un proyecto que es lo suficientemente grande como para no poder mantener todos los aspectos en mi cabeza. Estoy tratando con una serie de clases y funciones, y estoy pasando datos.
Con el tiempo, noté que seguía recibiendo errores, porque olvidé qué forma precisa deben tener los datos cuando los paso a diferentes funciones ( por ejemplo, una función acepta y genera una matriz de cadenas, otra función, que escribí mucho más tarde, acepta cadenas que se guardan en un diccionario, etc., por lo que tengo que transformar las cadenas con las que estoy trabajando para tenerlas en una matriz y tenerlas en un diccionario ).
Para evitar tener que averiguar siempre qué es lo que se rompió, comencé a tratar cada función y clase como una "entidad aislada" en el sentido de que no puede confiar en que el código externo le dé la entrada correcta y tiene que realizar comprobaciones de entrada por sí mismo (o, en algunos casos, refundir los datos, si los datos se dan en forma incorrecta).
Esto ha reducido en gran medida el tiempo que paso asegurándome de que los datos que paso "encajen" en cada función, porque las clases y las funciones mismas ahora me advierten cuando alguna entrada es mala (y algunas veces incluso corrige eso) y no lo hago. tengo que ir con un depurador a través de todo el código para descubrir dónde algo se volvió loco.
Por otro lado, esto también ha aumentado el código general.
Mi pregunta es, si este estilo de código es apropiado para resolver este problema?
Por supuesto, la mejor solución sería refactorizar completamente el proyecto y asegurarse de que los datos tengan una estructura uniforme para todas las funciones, pero dado que este proyecto está creciendo constantemente, terminaría gastando más y preocupándome por un código limpio en lugar de agregar cosas nuevas. .
(FYI: todavía soy un principiante, así que disculpe si esta pregunta fue ingenua; mi proyecto está en Python).
fuente
Respuestas:
Una mejor solución es aprovechar más las funciones y herramientas del lenguaje Python.
Este problema se mitiga con a
namedtuple
. Es liviano y le da un significado semántico fácil a los miembros de su matriz.Para aprovechar el beneficio de una verificación de tipo automática sin cambiar de idioma, puede aprovechar las sugerencias de tipo . Un buen IDE puede usar esto para avisarle cuando hace algo tonto.
También parece preocupado por las funciones obsoletas cuando cambian los requisitos. Esto puede detectarse mediante pruebas automatizadas .
Si bien no digo que la verificación manual nunca sea apropiada, un mejor uso de las funciones de idioma disponibles puede ayudarlo a resolver este problema de una manera más fácil de mantener.
fuente
namedtuple
y todas las otras cosas buenas. No lo hicenamedtuple
, y aunque sabía acerca de las pruebas automatizadas, realmente nunca lo usé mucho y no me di cuenta de cuánto me ayudaría en este caso. Todo esto realmente parece ser tan bueno como un análisis estático. (¡Las pruebas automatizadas podrían incluso ser mejores, ya que puedo captar todas las cosas sutiles que no se detectarían en un análisis estático!) Si conoce alguna otra, hágamelo saber. Voy a mantener la pregunta abierta un poco más, pero si no recibo ninguna otra respuesta, aceptaré la suya.OK, el problema real se describe en un comentario debajo de esta respuesta:
El problema aquí es el uso de una lista de cadenas donde el orden significa semántica. Este es un enfoque realmente propenso a errores. En su lugar, debe crear una clase personalizada con dos campos llamados
title
ybibliographical_reference
. De esa manera no los mezclará y evitará este problema en el futuro. Por supuesto, esto requiere un poco de refactorización si ya usa listas de cadenas en muchos lugares, pero créame, a largo plazo será más barato.El enfoque común en los lenguajes de tipos dinámicos es "escribir pato", lo que significa que realmente no te importa el "tipo" del objeto pasado, solo te importa si es compatible con los métodos que invocas. En su caso, simplemente leerá el campo llamado
bibliographical_reference
cuando lo necesite. Si este campo no existe en el objeto pasado, obtendrá un error, y esto indica que se pasó el tipo incorrecto a la función. Esta es una verificación de tipo tan buena como cualquiera.fuente
En primer lugar, lo que está experimentando en este momento es el olor del código : intente recordar lo que lo llevó a ser consciente del olor y trate de perfeccionar su nariz "mental", ya que cuanto antes note un olor del código, más rápido y más fácil. puede solucionar el problema subyacente.
La programación defensiva, como se llama esta técnica, es una herramienta válida y de uso frecuente. Sin embargo, como con todas las cosas, es importante usar la cantidad correcta, cheques muy pequeños y no detectará problemas, demasiados y su código se sobre-hinchará.
Esa podría ser una idea menos buena. Si nota que una parte de su programa está llamando a una función con datos formateados incorrectamente, CORREE ESA PARTE , no cambie la función llamada para poder digerir datos incorrectos de todos modos.
Mejorar la calidad y la capacidad de mantenimiento de su código es un ahorro de tiempo a largo plazo (en ese sentido, debo advertirle nuevamente contra la funcionalidad de autocorrección que incorporó en algunas de sus funciones: podrían ser una fuente insidiosa de errores. Solo porque su el programa no se bloquea y no significa que funcione correctamente ...)
Para responder finalmente a su pregunta: Sí, la programación defensiva (es decir, verificar la validez de los parámetros proporcionados) es, en buena medida, una buena estrategia. Dicho esto , como usted mismo ha dicho, su código es inconsitent, y me gustaría fuertemente recomiendo que pasar algún tiempo para refactorizar las partes que huelen - usted ha dicho que no quiere que preocuparse de código limpio todo el tiempo, pasar más tiempo en "limpiar" que en las nuevas funciones ... Si no mantiene limpio su código, puede pasar el doble de tiempo "guardar" para no mantener un código limpio en la eliminación de errores Y tendrá dificultades para implementar nuevas funciones: la deuda técnica puede aplastarte.
fuente
Esta bien. Solía codificar en FoxPro, donde tenía un bloque TRY..CATCH casi en cada gran función. Ahora, codifico en JavaScript / LiveScript y rara vez verifico parámetros en funciones "internas" o "privadas".
"Cuánto comprobar" depende del proyecto / idioma elegido más de lo que depende de su habilidad de código.
fuente