¿Cómo pasar menos tiempo en la depuración? [cerrado]

15

Siguiendo la regla de Pareto, un programador dedica solo el 20% de su tiempo a cosas realmente útiles.

Paso el 80% de mi tiempo depurando, arreglando cosas pequeñas para que todo funcione.

¿Hay alguna manera de pasar menos tiempo depurando?

uhbif19
fuente
99
No estoy seguro de cómo interpretaría el principio de Pareto.
c_maker
66
<meme> Echa un vistazo a TDD. </meme>
StuperUser
1
¿Qué es lo que realmente hace al depurar?
3
necesita dedicar más tiempo a su atención a los detalles
1
Hay mucho que ganar simplemente mirando su código de vez en cuando. Mejor aún, escriba comentarios cuando sienta la necesidad, para que sea más fácil notar errores más tarde.
Joey Adams

Respuestas:

5

Código en Agda o Coq . Una vez que su código se compila, funcionará. Si es demasiado duro, elija un idioma con un sistema de tipo más débil, por ejemplo, Haskell o F #.

Pero aún así, en la mayoría de los casos será mucho más productivo gastando el 20% de su tiempo en codificación y el 80% en pruebas y depuración. El 100% de una semana es mucho más que el 20% de una hora. Si la depuración es lo que necesita para hacer las cosas, entonces la depuración no es una pérdida de tiempo y no debería molestarse en "mejorar" esta proporción.

SK-logic
fuente
1
JUst porque algo corre no significa que no tiene errores. Los errores son a menudo el resultado del código que hace lo incorrecto.
HLGEM
3
@HLGEM, antes de votar, debería haber leído más sobre Agda y Coq. Si su código se compila, está garantizado y demostrado que hace exactamente lo que dice su especificación. Por supuesto, también puede haber un error en la especificación, pero no llamaría a la solución de este tipo de "depuración".
SK-logic
2
@HLGEM, entonces su noción de "depuración" es bastante creativa y está lejos de ser la corriente principal. Y de todos modos, con este enfoque, una proporción entre codificación y "depuración" estaría lejos de 20/80. Entonces, por favor, no olvide explicar su voto negativo.
SK-logic
1
@HLGEM, no estaba en una lista de requisitos de OP. No se sabe cuántos desarrolladores hay, quién está a cargo, etc. La única pregunta era "cómo medir la relación 20/80", y el uso de un lenguaje verificado estáticamente es claramente la respuesta más obvia. Pero, como ya dije, esta respuesta solo es aplicable en casos muy raros, y en general apegarse a la regla 20/80 es una opción mucho mejor.
SK-logic
1
@ uhbif19 Knuth quiso ser gracioso al decir eso. ¿Sabes a qué se refería realmente?
Phil
44

Examen de la unidad.

Después de que comencé a aplicar pruebas unitarias, descubrí que el código que escribí se estructuraba mejor. Entonces era más fácil de evitar y detectar errores. Pasé menos tiempo depurando, pero más tiempo escribiendo pruebas unitarias.

También creo que el tiempo invertido en pruebas unitarias tiene un mejor retorno de la inversión que la depuración. Después de una sesión de depuración, acabo de arreglar el código. El mismo error puede aparecer semanas después y tengo que depurar nuevamente. Si escribo una prueba unitaria, el error se documenta como una prueba unitaria y luego actúa como una prueba de regresión. Si el error aparece nuevamente, las pruebas unitarias me lo revelan.

Theo Lenndorff
fuente
Uso pruebas unitarias y estoy completamente de acuerdo con usted. Pero no puedo probar todo.
uhbif19
55
Seguro que puede. Bueno, no todo , pero todo lo que importa. Mediante el uso de interfaces, inyección de dependencia, falsificación y burla de clases / métodos, podrá escribir pruebas para casi todo su código.
Fredrik el
8
@Fredrik, no puede probar la unidad correctamente ni siquiera el a + bfragmento de código (a menos que su prueba cubra todo el rango de su tipo de datos aritméticos).
SK-logic
"Después de una sesión de depuración, simplemente arreglé el código". -- ¿De Verdad? Creo que después de una sesión de depuración acabo de introducir más errores, simplemente no sé dónde están.
B Seven
35
  • Prueba de unidad, para que sepa si su código funciona en primer lugar.
  • Al menos una cierta cantidad de diseño inicial, para que sepa lo que está codificando.
  • Revisiones de código, porque dos cabezas son mejores que una, y cuatro ojos son mejores que dos. Sin mencionar que incluso tratar de explicar su código a otra persona revela muchos problemas.
  • Control de versiones, para que pueda aislar rápidamente qué cambios pueden haber causado el error.
  • Refactorización, para que el código no se convierta en un horrible desastre incomprensible.
  • Lea "Código limpio" de Robert C. Martin y haga lo que él le diga. Te sorprenderán los resultados.
Dima
fuente
55
Exactamente: ninguna práctica individual (por ejemplo, pruebas unitarias) dará un orden de mejora de magnitud, pero una combinación de prácticas puede hacerlo . En otras palabras ... no hay bala de plata.
Michael
Añadiría TDD (cuando sea posible).
Tom
1
De hecho, ordenaría el código limpio y la refactorización primero. Las pruebas unitarias son buenas para encontrar y corregir errores temprano, pero no reducirán la cantidad de ellos (reducirán un poco el tiempo, porque corregirá errores cuando tenga todo nuevo en la memoria, pero aún así). Escribir código limpio, por otro lado, reduce la cantidad real de errores.
Jan Hudec
1
@JanHudec Refactorización + código limpio + pruebas = TDD
Tom
1
@Tom: Sí, pero las diferentes partes tienen diferentes efectos. Aprender a escribir código limpio lo ayudará a reducir el tiempo de depuración sin ninguna prueba. Las pruebas están ahí para que pueda probar los módulos antes de que se implemente su uso y para verificar que no modificó el comportamiento cuando refactoriza, lo que es necesario para limpiar el viejo código desordenado.
Jan Hudec
8

Las pruebas unitarias ayudarán con la esperanza de que si introduce errores se rompan antes de su código de producción; las pruebas unitarias bien escritas también le dirán exactamente qué se rompió.

Eso lo llevará a la mayor parte del camino, pero para el 99.999% de los proyectos aún necesitará depurar las cosas a tiempo. Lo mejor que puedo hacer aquí es 4 cosas:

  1. use tipos inmutables siempre que sea posible; si algo tiene un valor incorrecto, sabrá exactamente dónde buscar de inmediato (dónde se está construyendo).
  2. imponga invariantes en el código: si sabe que un valor definitivamente no está permitido, verifíquelo y arroje una excepción en los puntos de entrada a métodos y constructores. Si combina esto con tipos inmutables, también puede comenzar a hacer ciertas suposiciones sobre lo que es válido o no.
  3. asegúrese de tener un registro adecuado: obtenga esto temprano y le dará mucha información importante sobre cuándo las cosas salen mal. AOP funciona muy bien aquí. Iniciar sesión como una idea de último momento suele ser un poco inútil: consíguelo temprano como parte de la configuración del proyecto.
  4. si su base de código es lo suficientemente grande / compleja, evite usar primitivas; por ejemplo, tenga un tipo llamado 'Age' en lugar de solo usar un int. Al principio parecerá un poco inútil, pero poder rastrear todos los usos de algo en un instante es una gran victoria de depuración.
FinnNk
fuente
6

Mi 80% es depuración. Estoy arreglando errores simples y tratando de hacer que todo funcione.

Comience escribiendo pruebas unitarias e intente tener la mayor cobertura posible. Alguien mencionó TDD, pero yo iría con BDD .

Al final, lo más probable es que gaste el 80% en la depuración de errores complejos.

BЈовић
fuente
6

¿Cómo pasar menos tiempo depurando? Escribe menos código.

En serio, siempre y cuando escribas código, deberás depurarlo. Las pruebas unitarias, etc., ayudan enormemente, pero no piense que alguna vez eliminará por completo la necesidad.

Daniel Roseman
fuente
4

Comprenda el qué y el por qué antes de comenzar a escribir código. Luego use una metodología de manera consistente. La metodología que elija no es tan importante como el uso repetido constante de la metodología. Si desea resultados consistentemente buenos, debe hacer un trabajo consistentemente bueno y tener un "método para su locura" es el primer paso para obtener estos resultados. A medida que identifique problemas, puede ajustar su metodología según sea necesario y, con el tiempo, mejorará su proceso de desarrollo y, con suerte, menos errores y más desarrollo nuevo y significativo.

cdkMoose
fuente
3

Lea detenidamente su código antes de incluso compilarlo. Una lectura muy cuidadosa para la sintaxis y la funcionalidad. Puede ser sorprendentemente informativo, y también es un buen indicador si una sección de código es demasiado complicada.

luego
fuente
Estoy totalmente de acuerdo. Leer su código inmediatamente después de escribirlo puede revelar rápidamente algunos errores evidentes, como copiar y pegar errores tipográficos (que a veces pueden ser difíciles de encontrar después).
jirkamat el
3

La mayoría de las respuestas parecen centrarse en cómo reducir la cantidad de problemas que tiene que depurar y eso es valioso. Sin embargo, la depuración siempre será necesaria, por lo que es útil buscar formas de acelerar la depuración.

  • Sepa cómo usar su software de control de versiones.

    • El uso de ramas lo ayudará a separar las áreas de desarrollo y podrá ver qué área de desarrollo tiene el error y cuáles no.
    • Aprenda cómo usar la bisección en su VCS, Git tiene esto incorporado. Si usa un VCS diferente que no tiene bisección incorporada, busque una herramienta que funcione como git bisect pero para su VCS (sé que esto existe para SVN y no debería ser demasiado difícil de crear para otros VCS). Esto lo ayudará a reducir el cambio de código que introdujo el error, lo que ayudará a saber dónde apuntar su depurador. Este proceso de bisección será más rápido si tiene pruebas para el error y saber qué confirmación contiene el cambio ofensivo será más útil si practica confirmaciones atómicas.
  • Mejore su comprensión del lenguaje de programación que utiliza.

    • Lea libros, blogs y códigos sobre el lenguaje de programación.
    • Cada vez que solucione un error, asegúrese de comprender completamente por qué el código no funcionó y por qué funciona su corrección. Con el tiempo, aprenderá muchas trampas en su idioma que lo ayudarán a evitar sus problemas y detectar sus síntomas si vuelven a ocurrir.
  • Ser lógico

    • No cambie más de una cosa a la vez; de lo contrario, si el comportamiento cambia, no sabrá qué cambio causó el cambio en el comportamiento.
    • Verifica tus suposiciones.
Stephen Paulger
fuente
2

Agregando a los comentarios para Pruebas unitarias, pero solo es realmente bueno si su código se ha separado para admitirlo (por ejemplo, MVC). Si no puede implementar MVC (o similar) (proyecto heredado), las pruebas unitarias no funcionan para su interfaz de usuario. Luego agregaría pruebas de IU automatizadas (Pruebas de IU codificadas de Microsoft, WaitN) ya que esto reducirá los errores en esa parte de su código.

También recomendaría encarecidamente ejecutar herramientas de análisis estático (por ejemplo, FxCop / Microsoft Code Analysis, Resharper, JustCode para el mundo MS). Estos pueden encontrar todo tipo de problemas de codificación comunes que pueden reducir las tontas tareas de depuración y centrarse más en la depuración de la lógica empresarial.

Scott Wylie
fuente
2

Haz que funcione, luego hazlo rápido, luego hazlo bonito. La mayoría de los errores provienen de optimizaciones tempranas o re-factorización en líneas de código que estaban totalmente bien. Si opta por la orientación a objetos, no se repita, manténgalo simple y siempre realice controles de cordura de los rangos de valores, especialmente si sus métodos seguirán funcionando con restricciones. No lo ayudará a cometer menos errores, pero probablemente lo ayudará a detectar errores más rápido y, por lo tanto, la depuración lleva menos tiempo.

kibotu
fuente
1
Su afirmación "La mayoría de los errores provienen de ..." suena bien, pero ¿tiene evidencia para respaldar eso? Creo que sonaría igualmente convincente si dijera que "la mayoría de los errores provienen de requisitos mal especificados o la falta de un diseño claro". Debe agregar un enlace o una cita a la investigación que respalde su declaración.
Caleb
2

Recientemente he pensado mucho en este problema: la respuesta simple es ir a leer El diseño de las cosas cotidianas de Don Norman; Escriba el código como diseñaría un producto.

Parafraseando, un buen diseño minimiza el error. Eso significa que, pocas cosas, la mayoría de los cuales usted ya hace (aunque puede que no sepa exactamente por qué ).

-Nombre funciona intuitivamente. Esto se conoce formalmente como asequibilidad. Es decir, un botón permite presionarlo, una palanca permite cambiar, un mango para tirar, etc.

-Es difícil escribir código incorrecto. Compruebe si hay errores de entrada y arroje errores más temprano que tarde, use aplicaciones húngaras cuando sea apropiado, etc. Estas se llaman funciones de bloqueo.

-Utilice la abstracción donde corresponda. La memoria a corto plazo es débil.

-La documentación es obviamente importante, pero es la menos efectiva para asegurarse de que el código se use correctamente. En resumen, los productos bien diseñados no necesitan ninguna documentación. (La forma más obvia de ver esto es mirando malos ejemplos: a saber, puertas con manijas que se supone que debes empujar).

-Unidad de pruebas. Estos realmente no evitan errores, sino que hacen que sea obvio dónde están los errores y proporcionan cordura.

Estoy seguro de que me faltan muchos más principios, pero el punto es leer sobre el diseño por error.

Ceasar Bautista
fuente
1

La mejor manera de disminuir la depuración, IMO, es concentrarse y reducir la velocidad al codificar. ¡Esto te obliga a ver los errores que hayas cometido!

Dinámica
fuente
1

Si bien apoyo totalmente las pruebas unitarias sugeridas anteriormente, TDD o BDD serán de gran valor ya que primero debe pensar en el problema y la solución.

Pero personalmente para mí, tomarme unos minutos para sentarme en silencio y pensar sobre el problema y cómo abordarlo y cualquier pros y contras con cada enfoque, hace maravillas por mi calidad de código y ayuda a despejar mi mente del desorden.

A veces, un garabato rápido en una hoja de papel te ayuda a ver las piezas conectadas más grandes del rompecabezas.

Escribo el peor código cuando solo me sumerjo de cabeza y golpeo el teclado. Un poco de pensamiento y contemplación hace un mundo de diferencia.

PD. Quiero decir 5 tal vez diez minutos, no horas escribiendo una gran especificación.

SetiSeeker
fuente
1

Algunas buenas respuestas ya, solo un poco más de comida, aunque además de lo que otros han dicho.

Aprende de tus errores. No sigas haciendo los mismos una y otra vez.

Asegúrese de cubrir los casos extremos al programar; esos son lugares donde frecuentemente hay errores.

Presta atención al requisito. Incluso si funciona pero no cumple con el requisito especificado, eso es un error.

Los registros de excepciones pueden ser de gran ayuda cuando algo sale mal dentro de seis meses. Acostúmbrate a registrar excepciones.

HLGEM
fuente
0

Mis dos pensamientos principales son 1) Escribir un mejor código que fallará cuando haces algo inesperado 2) Mejora la depuración

Mi código está lleno de

if(value!=null) throw new NotImplementedException();
if(obj.v>0) throw new Exception(); //sometimes i dont write NotImplementedException
if(value=="thing") throw ...;

Cada vez que ejecuto ese fragmento de código, se produce la excepción que hace que el depurador se detenga, lo que me permite codificar las nuevas funciones o evitar las condiciones en lugar de confundirme sobre lo que está sucediendo / tener un error

Para mejorar en la depuración, la pila de llamadas, los puntos de interrupción (con condiciones), la ventana inmediata (también conocida como ventana de solicitud o respuesta), las variables de 'observación' y cualquier otra cosa.

usuario2528
fuente