c# - practices - Mejores prácticas para la depuración
remarks c# (16)
Al igual que sugiere Conceptual Blockbusting , me gusta probar diferentes formas cada vez que me quedo atascado. "depuración de printf", pensando en el comportamiento, búsqueda binaria en el código, búsqueda binaria en confirmaciones de control de versión, escribir una prueba de unidad para aclarar, refactorizar y también desencadenar el depurador.
Últimamente he estado depurando bastante las aplicaciones administradas usando tanto Visual Studio como WinDbg, y como tal a menudo me piden que ayude a mis colegas en situaciones de depuración. En varias ocasiones he encontrado personas que simplemente insertan puntos de quiebre aquí y allá y esperan lo mejor. En mi experiencia, rara vez es una técnica útil.
Mi enfoque es algo como esto.
Reproduce el problema. Lo ideal sería reducir la entrada tanto como sea posible.
Examine qué va mal y enumere las teorías sobre dónde puede estar el error.
Examine una teoría a la vez depurando esa área específica del código.
Repita los pasos según sea necesario.
Para problemas complejos de depuración, a menudo trabajo con un colega. Para WinDbg esto es especialmente útil.
¿Algún otro consejo útil o mejores prácticas para la depuración?
Como dice otro cartel, con algunas ideas difíciles, a menudo es posible ver el error de lógica si entiendes lo que está sucediendo.
Pero a menudo creemos que sí, y no lo hacemos, o simplemente nos obligan a arreglar algo que no entendemos demasiado bien, así que volvemos a los primeros principios.
Reproducir el problema es ciertamente un primer paso vital. Si no puedes hacer esto, entonces no tienes ninguna posibilidad de encontrar el problema, excepto por accidente.
El siguiente paso es establecer sin lugar a dudas el camino a través del código que realmente se ejecuta cuando se produce el error. En una aplicación WinForms que podría tener muchos eventos y más de un hilo, esto puede ser cualquier cosa menos un ejercicio trivial.
Hasta que sepa exactamente a dónde va el código, todas las teorías del mundo sobre dónde puede estar el error no tienen valor. Y si el código es complejo, descubrir que el código no se detiene en un punto de interrupción puede ser tan informativo como detenerlo.
Por lo tanto, en mi experiencia, el uso temprano de los puntos de interrupción ya menudo puede ser una herramienta esencial para descubrir cómo funciona un código.
A menudo encuentro que cuando un problema parece particularmente difícil de resolver, es porque he asumido fatalmente lo que está sucediendo y no lo he verificado realmente.
Entonces, mi ''mejor práctica'' es no seguir adelante hasta que esté seguro de entender, y no adivinar.
Las barreras de entrada para el depurador en VS.NET con un lenguaje como C # o VB.NET son tan ridículamente bajas que a menudo es más fácil insertar un punto de quiebre o dos donde sabes que el problema es y simplemente lo atraviesas.
A veces me encuentro usando Editar y Continuar para escribir código. Es genial. Puedes ver resultados de inmediato. A menudo es más útil cuando hay algún algoritmo o lazo relativamente difícil de entender.
No se relaciona directamente con la depuración, pero para facilitar la depuración en el futuro, hay algunas cosas que se deben tener en cuenta:
- Las pruebas de unidades de implementación, preferiblemente en forma de TDD, lo obligan a permanecer en la tarea y desarrollarse solo con el objetivo de pasar las pruebas. Es más difícil "vagar" cuando está codificando para una prueba, en lugar de una tarea.
- Póngase en la práctica de refactorizar regularmente su código. Los métodos pequeños y puntuales son más fáciles de depurar que los métodos monolíticos de "jack of all trades".
- Utiliza a los miembros de tu equipo. A menudo, agregar un par de ojos adicionales puede ayudar a eliminar algo. Lo más probable es que, si no encuentra algo de una manera relativamente rápida, vaya a continuar pasándolo por alto durante un tiempo.
- Siempre puede revertir el código en su sistema de control de versiones para tratar de aislar qué versión de un archivo causó la introducción del error. Una vez que haces eso, puedes diferenciar entre el último bien y el primer mal y solo enfocarte en los cambios entre los dos.
Si hubiera un consejo que pudiera darles a todos acerca de la depuración sería romperlo de nuevo.
Es decir, cuando crees que has encontrado la solución y el sistema parece funcionar. Retroceda la reparación y vea si el sistema se rompe nuevamente.
A veces puede perderse en la secuencia de lo que ha probado como soluciones potenciales y termina en un área totalmente diferente del sistema mientras depura el problema. Entonces olvidas lo que has cambiado en el área original donde estabas trabajando.
Respaldar el arreglo y luego reproducir el problema asegura que la corrección candidata no dependa de otra cosa que hayas cambiado en otra parte del sistema. Que su parche para la solución sea una solución independiente correcta.
HTH.
aclamaciones,
Robar
Una buena práctica es no sumergirse en el depurador inmediatamente, sino mirar el código y pensar detenidamente durante un tiempo.
Una buena práctica es asegurarse de que no está solucionando un síntoma, sino la causa.
A menudo, uno puede ver un valor extraño mientras depura y arreglarlo allí, sin verificar qué causó que el valor llegue allí en primer lugar. Esta es, por supuesto, una muy mala idea.
Por cierto, esta es la razón por la cual Linus objetó agregar soporte integrado para la depuración del kernel.
Una cosa que me gusta recalcar es que cuando tienes una instancia trabajando y otra no (por ejemplo, producción y desarrollo) se trata de las diferencias y necesitas identificar claramente cuáles podrían ser y tratar con ellas de a una por vez . Los problemas ambientales pueden ser los más difíciles de rastrear y te volverás loco si no trabajas sistemáticamente.
Por cierto, esta es una de las razones por las que habitualmente administro mis proyectos de aplicaciones VS de VS a través de IIS no cassini.
La demasiada preparación de la OMI es una pérdida de tiempo. Si conoces la base de código bastante bien, normalmente siempre puedes pensar en algunos lugares clave donde se manifiesta el problema. Ponga puntos de quiebre allí y vea si tiene razón. Cada vez que veas mejores puntos clave, mueve tus puntos de quiebre para acercarte al problema.
Cuando persigue datos erróneos, como un puntero nulo, depende de dónde viene: si se pasa como argumento, mire la pila de llamadas para saber de dónde viene. Si es parte de alguna estructura de datos u objeto (el caso más fácil), coloque un punto de interrupción allí para ver cuándo y cómo se modifica.
Los puntos de corte conition pueden ser de gran ayuda; de lo contrario, puede simularlos agregando if statements que incluyan no-ops. Si tiene un punto de quiebre en un punto caliente que recibe demasiado a menudo antes de llegar al problema, desactívelo y coloque otro en un lugar que sepa que será golpeado poco antes de que se manifieste el problema, luego active el que está en el punto caliente.
Algo que ayuda, especialmente cuando eres nuevo en la depuración, es mantener algún tipo de diario de depuración, con soluciones a problemas que has resuelto en el pasado. La mayoría de los errores siguen patrones relativamente comunes (por ejemplo, los problemas aparentemente aleatorios en las aplicaciones sin subprocesos generalmente se deben a variables indefinidas, o al uso similar de memoria no inicializada) y al realizar un seguimiento de esos patrones, obtendrá mucho mejor para obtener problemas futuros
Después de un tiempo, solo desarrollas la intuición necesaria (y luego tu diario se convierte en un recuerdo muy divertido de todos los enemigos desagradables que has conquistado)
Este libro es honestamente el mejor que he leído sobre la depuración, especialmente cuando estás más allá de la situación normal de depuración. Contiene muchos trucos y es divertido de leer con toda la "historia real". Si trabajas con una gran cantidad de código que no has escrito, especialmente si es malo, ¡este libro es obligatorio!
texto alternativo http://ecx.images-amazon.com/images/I/51RQ146x9VL._SS500_.jpg
No estoy seguro de dónde leí sobre "Rubber Duck Debugging", pero creo que es genial. La idea básica es colocar un pato de goma en su escritorio y explicarle el código. La idea es que mientras explicas el código al pato, eventualmente te encuentres diciendo "Ahora, esto sucede", y notarás que "esto" no es lo que pretendes que ocurra.
Al carecer de un pato, descubro que simplemente reviso el código y me lo explico. Funciona, pero todavía creo que podría traer un pato.
[EDIT] Encontré donde leo sobre el pato de goma Rubber Duck Debugging
Otra cosa que he comenzado a hacer en todos mis proyectos es agregar un TraceListener (o una clase derivada) y usarlo para tomar instantáneas clave de mi aplicación.
Esto generalmente me da una buena idea de dónde enfocar mis esfuerzos iniciales de depuración.
Además, puedo activar / desactivar el uso de un interruptor de archivo de configuración, por lo que incluso puedo obtener una pista sobre un sistema de producción, sin volver a compilar el código.
Esto no es un consejo técnico, pero a menudo funciona en mi caso.
Simplemente deja de trabajar duro para encontrar una causa raíz o corregir un error. Relájese por un momento: salga a caminar, coma la cena o simplemente cambie a otra tarea (con suerte, mucho más fácil), lo que quiera ...
... Luego piensa en un problema un poco más tarde, cuando estés "fresco" de nuevo. Haga un seguimiento de todo el proceso mental de depuración que ya ha experimentado (teorías, experimentos, suposiciones, etc. que hizo). Lo más probable es que vea instantáneamente algún factor clave que haya pasado por alto antes;).
Los programadores (o al menos yo) tienden a reducir gradualmente su perspectiva de problema y desgaste de la creatividad durante una sesión de depuración larga. ¡Pero una amplia perspectiva combinada con ideas creativas es el arma más poderosa del hombre en la batalla contra los insectos!
Acabo de reproducir en otra publicación , la pregunta era C depuración, pero como dije en mi repetición, creo que las técnicas de depuración son independientes del lenguaje.
Voy a parafrasear mi respuesta en un hilo similar (que es esencialmente el último punto en la respuesta de joseph.ferris a este hilo ):
Usando su sistema de control de versiones, aísle la revisión del archivo donde se introdujo el error, utilizando el enfoque del árbol de búsqueda binaria.
Difiere esa revisión del archivo fuente en comparación con la revisión anterior. La diferencia puede hacer que la razón del error sea evidente.