En términos muy generales, lo que hago es:
Intenta aislar el problema. Piense en lo que cambió cuando apareció el error por primera vez. ¿En qué trabajas? ¿Qué parte del código estabas cambiando? El 99% de mis errores se resuelven de esta manera. Suele ser algo tonto.
Si tengo una idea de dónde está el problema, eche un vistazo al código que parece ser la causa. Léelo Léelo en voz alta incluso. Pregúnteme: "¿Qué estoy tratando de lograr?". Para algunos tipos de problemas: ¿podría tener algunos efectos secundarios o podría verse afectado por el código en otro lugar de una manera que no había pensado?
Intente de varias maneras analizar qué sale mal, dónde y cuándo (ver más abajo).
Si todavía no tengo idea, verifico si una versión anterior de mi fuente tiene el mismo problema, trato de encontrar cuándo apareció por primera vez en mi línea de tiempo de desarrollo. Para hacer esto, debe trabajar con un buen sistema de control de versiones, como git (git tiene una característica llamada bisect exactamente para este tipo de depuración).
Si aún no tienes idea, tómate un descanso ... en realidad a menudo ayuda.
Regrese al tablero de dibujo: revise cómo se supone que debe funcionar su programa y si eso realmente tiene sentido.
Realmente depende del tipo de problema, pero suponiendo que tenga una idea general de dónde podría estar el problema, entonces:
Si sospecho que el problema está en alguna parte del código / cambio reciente, primero trato de eliminar / comentar / cambiar o lo que sea para que el error desaparezca al simplificar el código, y luego recuperar el código problemático y tomar un bien miralo.
Ejecute un depurador con puntos de interrupción (si es posible) y eche un vistazo a cómo se ven mis datos tratando de encontrar cuándo comienza a actuar mal, para tener una mejor idea de dónde van las cosas mal.
bzr qdiff
comando.Intento utilizar el desarrollo basado en pruebas ( TDD ). Escribo una prueba que replica el error, luego trato de pasar la prueba. A veces, el acto de escribir la prueba ayuda a encontrar el error.
Esto me mantiene alejado del depurador la mayor parte del tiempo y proporciona pruebas de regresión para evitar reintroducir el error.
Algunos enlaces:
fuente
Hay una serie de definiciones para la palabra ciencia, pero parece que posiblemente se esté refiriendo a lo que se podría denominar con mayor precisión el " método científico ". El método científico podría resumirse como la observación de algunos fenómenos (presumiblemente un error o un comportamiento inesperado del programa), la formulación de una hipótesis o hipótesis para explicar el comportamiento, y el experimento más probable para probarlo (escribir una prueba que reproduzca el problema de manera confiable).
Los tipos de errores (fenómenos) que pueden ocurrir son prácticamente infinitos y algunos no requieren necesariamente un proceso bien definido. Por ejemplo, a veces observa un error e instantáneamente sabe qué lo causó simplemente porque está muy familiarizado con el código. Otras veces, sabe que, dada alguna entrada (acción, serie de pasos, etc.), se produce un resultado incorrecto (bloqueo, salida incorrecta, etc.). Para esos casos, a menudo no requiere mucho pensamiento "científico". Un poco de pensamiento puede ayudar a reducir el espacio de búsqueda, pero un método común es simplemente recorrer el código en un depurador y ver dónde las cosas salieron mal.
Sin embargo, las situaciones que considero más interesantes y posiblemente dignas de un proceso científico son donde se le entrega un resultado final y se le pide que explique cómo sucedió. Un ejemplo obvio de esto es un volcado por caída. Puede cargar el volcado de memoria y observar el estado del sistema y su trabajo es explicar cómo llegó en ese estado. El volcado de bloqueo (o núcleo) puede mostrar una excepción, punto muerto, error interno o algún estado "indeseable" según lo definido por el usuario (por ejemplo, lentitud). Para estas situaciones, generalmente sigo los siguientes pasos:
Observación estrecha : estudie la información que rodea directamente el problema específico, si corresponde. Las cosas obvias aquí son la pila de llamadas, las variables locales si puede verlas, las líneas de código que rodean el problema. Este tipo de estudio de ubicación específica no siempre es aplicable. Por ejemplo, estudiar un sistema "lento" puede no tener una ubicación de inicio obvia como esta, pero una situación de bloqueo o error interno probablemente tendrá un punto de interés inmediato y obvio. Un paso específico aquí podría ser utilizar herramientas como windbg (ejecute! Analyse -v en un volcado de memoria cargado y mire lo que le dice).
Observación amplia : estudie otras partes del sistema. Examine el estado de todos los subprocesos en el sistema, mire cualquier información global (número de usuarios / operaciones / artículos, transacciones / procesos / widgets activos, etc.), información del sistema (SO), etc. Si el usuario proporcionó detalles externos , piense en aquellos en conjunto con lo que ha observado. Por ejemplo, si le dijeron que el problema ocurre todos los martes por la tarde, pregúntese qué podría significar eso.
Hipotetizar: Esta es la parte realmente divertida (y no estoy siendo gracioso acerca de que sea divertido). A menudo requiere una gran cantidad de pensamiento lógico a la inversa. Puede ser muy divertido pensar en cómo el sistema entró en el estado actual. Sospecho que esta es la parte que mucha gente piensa que es un arte. Y supongo que podría ser si el programador simplemente comienza a arrojarle cosas al azar para ver qué queda. Pero con experiencia, este puede ser un proceso bastante bien definido. Si piensa muy lógicamente en este punto, a menudo es posible definir posibles conjuntos de caminos que condujeron al estado dado. Sé que estamos en el estado S5. Para que eso suceda, S4a o S4b debían ocurrir y quizás S3 antes que S4a, etc. Más a menudo que no, puede haber múltiples elementos que podrían conducir a un estado dado. A veces puede ser útil escribir en un bloc de notas un diagrama de flujo o estado simple o una serie de pasos relacionados con el tiempo. Los procesos reales aquí variarán mucho dependiendo de la situación, pero un pensamiento serio (y un reexamen en los pasos anteriores) en este momento a menudo proporcionará una o más respuestas plausibles. También tenga en cuenta que una parte extremadamente importante de este paso es eliminar las cosas que son imposibles. Eliminar lo imposible puede ayudar a recortar el espacio de la solución (recuerde lo que dijo Sherlock Holmes sobre lo que queda después de eliminar lo imposible). También tenga en cuenta que una parte extremadamente importante de este paso es eliminar las cosas que son imposibles. Eliminar lo imposible puede ayudar a recortar el espacio de la solución (recuerde lo que dijo Sherlock Holmes sobre lo que queda después de eliminar lo imposible). También tenga en cuenta que una parte extremadamente importante de este paso es eliminar las cosas que son imposibles. Eliminar lo imposible puede ayudar a recortar el espacio de la solución (recuerde lo que dijo Sherlock Holmes sobre lo que queda después de eliminar lo imposible).
Experimento : en esta etapa, intente reproducir el problema en función de las hipótesis derivadas en el paso anterior. Si pensaste seriamente en el paso anterior, esto debería ser muy sencillo. A veces "engaño" y modifico la base del código para ayudar a una prueba dada. Por ejemplo, recientemente estaba investigando un accidente que concluí que era por una condición de carrera. Para verificarlo, simplemente coloco un Sleep (500) entre un par de líneas de código para permitir que otro hilo haga sus cosas malas en el momento "correcto". No sé si esto está permitido en la ciencia "real", pero es perfectamente razonable en el código que posee.
Si logra reproducirlo, lo más probable es que haya terminado (todo lo que queda es el simple paso de arreglarlo ... pero eso es para otro día). Asegúrese de verificar la nueva prueba en el sistema de prueba de regresión. Y debo señalar que tenía la intención de que la afirmación anterior sobre arreglarlo fuera simple de ser irónica. Encontrar una solución e implementarla puede requerir mucho trabajo. Es mi opinión que la reparación de un error no es parte del proceso de depuración, sino que es más bien un desarrollo. Y si la solución está involucrada, eso debería requerir cierta cantidad de diseño y revisión.
fuente
Intenta reducir el caso de prueba. Cuando es lo suficientemente pequeño, generalmente es más fácil localizar el código correspondiente que está causando el problema.
Es probable que un nuevo check-in esté causando el problema y que la compilación diaria anterior esté bien. En ese caso, su registro de cambios del control de origen debería ayudarlo a decidir a quién capturar.
Además, si está en C / C ++, considere ejecutar valgrind o purify para aislar problemas relacionados con la memoria.
fuente
La parte más difícil de la depuración es aislar el problema, particularmente cuando el problema está enterrado debajo de varias capas. En la universidad estudié grabación de música y, curiosamente, había una clase de Studio Electronics que se aplica directamente aquí. Voy a usar la depuración de un entorno de estudio como una ilustración del proceso de depuración sistemática.
El código de depuración realmente no es tan diferente. La depuración es mucho más fácil cuando el código arroja una excepción. Puede rastrear hacia atrás desde el rastro de la pila de esa excepción y establecer puntos de interrupción en las posiciones clave. Por lo general, justo después de establecer una variable, o en la línea que llama al método que arroja la excepción. Puede encontrar que uno o más de los valores no son correctos. Si no está bien (un valor nulo cuando no debería haberlo, o el valor está fuera de rango), entonces es un proceso de descubrir por qué no está bien. Los puntos de ruptura en un IDE son equivalentes a los puntos de prueba electrónicos (diseñados para que la sonda de un medidor verifique el circuito).
Ahora, una vez que haya pasado por esa parte difícil de descubrir dónde está mi verdadero problema, escribiré algunas pruebas unitarias para verificarlo en el futuro.
fuente
Con los errores desagradables que lucho por localizar a última hora de la tarde, mi estrategia más efectiva es levantarme y alejarme por unos minutos. Por lo general, nuevas ideas sobre posibles fuentes de error comienzan a fluir después de solo 30 segundos.
fuente
Para un enfoque más práctico:
Si el error está relacionado con una excepción no controlada, observe el seguimiento de la pila. La referencia nula, el índice fuera de límites, etc. y sus propias excepciones definidas son las más comunes, puede asignar este error a un desarrollador junior, probablemente sea fácil y una buena experiencia de aprendizaje.
Si no sucede en todas las máquinas, es probable que sea una forma de problema de carrera / enhebrado. Estos son súper divertidos de rastrear, pon a tu aburrido programador senior en él. Muchos registros, buenos conocimientos y buenas herramientas hacen esto.
Otra gran clase de errores es cuando al equipo de prueba o al cliente (s) no les gusta un comportamiento particular. Por ejemplo, no les gusta que decidas mostrar ID de usuario o que cuando buscas no se complete automáticamente. Estos son errores genuinos, considere tener una mejor administración de productos y desarrolladores con una visión más amplia. Al desarrollador le debería tomar un tiempo relativamente corto "arreglar" esto si construye el sistema con la expansión en mente.
El 80% de todos los otros errores se resuelven teniendo un buen sistema de registro y recopilando suficiente información para resolverlos. Utilice el rastreo integrado con múltiples niveles de sistemas de registro complejos como Log4Net / Log4J
los errores de rendimiento son una categoría propia, la regla del jugador de golf aquí es "¡medir primero, arreglar después!", y te sorprendería ver cuántos desarrolladores solo adivinan dónde está el problema y entran para solucionarlo solo para ver luego una mera disminución del 3-4% en el tiempo de respuesta.
fuente
Tengo dos enfoques de flujo:
Divide and Conquer
Paradigma.Este enfoque me ha ayudado la mayoría de las veces.
fuente