Ayer, lancé una versión v1.0 de un proyecto web en el que pasé unas 6 semanas trabajando (de vez en cuando, claro). No he hecho ningún registro exacto de mi tiempo, pero de acuerdo con mis experiencias, estimaría que de todo el tiempo que pasé programando, la mitad se dedicó a la depuración. Calculo que se trata de una buena depuración de 15-20 horas, lo que para mí es un tiempo precioso que podría haberse gastado mejor escribiendo un nuevo código o terminando el proyecto antes. Tampoco ayuda especialmente que sea un estudiante de primer año en la universidad en 5 semanas.
La cosa es que me siento mal por pasar todo ese tiempo depurando. Todo el tiempo dedicado a la depuración me hace darme cuenta de que cometí algunos errores bastante estúpidos mientras desarrollaba mi proyecto, errores que me costaron una gran cantidad de tiempo para solucionarlos.
¿Cómo puedo evitar que esto suceda en el futuro? No quiero pasar el 50% de mi tiempo depurando, prefiero pasar el 10% de depuración y el resto escribiendo código nuevo. ¿Cuáles son algunas técnicas que puedo tratar de ayudarme a alcanzar este objetivo?
Respuestas:
Estás pidiendo el Santo Grial de la ingeniería de software, y nadie tiene "la" respuesta a esta pregunta todavía.
Lo esencial es hacer un seguimiento de los tipos de errores que está cometiendo y luego hacer un análisis de esos errores para determinar si hay una tendencia común. El análisis de causa raíz es el nombre formal para este tipo de introspección, y hay mucho material en la web al respecto.
Los profesionales usan un sistema de seguimiento de errores para que puedan (1) saber lo que necesita ser arreglado, pero también (2) analizar lo que tuvo que arreglarse después del hecho. No es necesario que sea tan formal, solo llevar una cuenta en un cuaderno puede estar bien para usted.
Defectos de la etapa de diseño
Si descubre que la mayoría de sus errores provienen de un malentendido de la declaración del problema, o si sigue encontrando que ha elegido el algoritmo o el camino incorrecto a seguir para resolver sus problemas, tiene problemas en la etapa de diseño.
Le convendría tomarse más tiempo al comienzo del proyecto y escribir exactamente lo que debe hacerse y cómo debe hacerlo. Revise este trabajo cuidadosamente y revise el problema original y determine si realmente lo está abordando de la manera correcta. Una hora o tres adicionales al comienzo pueden ahorrarle muchas horas más adelante.
Errores de codificación
Si su diseño es sólido, pero constantemente está luchando contra el lenguaje con el que está codificando, consiga algunas herramientas que analizarán su código por usted y le advertirán temprano y, a menudo, que está cometiendo errores.
Si está programando en C, active todas las advertencias del compilador, use un verificador semántico como
lint
y use una herramienta comovalgrind
para detectar problemas comunes relacionados con la memoria dinámica.Si estás programación Perl, encienda
strict
ywarnings
y hacer caso de lo que dice.No importa qué idioma esté usando, probablemente existan muchas herramientas para ayudar a detectar errores comunes mucho antes de llegar a la etapa de depuración.
Defectos de la etapa de integración
A medida que desarrolla su código siguiendo buenas prácticas de modularidad, debe comenzar a pegar las piezas separadas. Por ejemplo, las diferentes secciones de su código pueden tener que ver con la entrada del usuario, la interacción de la base de datos, la visualización de datos, los algoritmos / lógica, y cada uno de ellos está construido de manera relativamente independiente el uno del otro (es decir, tiende a concentrarse en la sección en cuestión) en lugar de preocuparse por la integración con todo lo demás).
Aquí es donde el desarrollo impulsado por pruebas (TDD) es muy útil. Cada módulo de su código puede tener pruebas que verifiquen que funcionan de acuerdo a cómo fueron diseñadas. Estas pruebas deben escribirse primero o muy temprano en el proceso para que pueda tener un conjunto de "ayudantes" que lo mantengan honesto. Cuando comience a hacer que todo funcione en conjunto, y descubra que tiene que cambiar la forma en que esto o aquello se implementa o interactúa con otro subsistema, puede recurrir a sus pruebas para asegurarse de que lo que ha hecho para hacer todo funciona en conjunto no rompe la exactitud del código.
Y así...
Elija algunos libros sobre ingeniería de software y técnicas prácticas de codificación, y aprenderá muchas formas diferentes de hacer que el desarrollo sea menos caótico y más confiable. También descubrirá que la experiencia simplemente antigua, obtener un título de la escuela de golpes duros, también lo pondrá en forma.
Lo que casi todo se reduce a eso es que un poco de tiempo y trabajo por adelantado vale la pena en grandes dividendos más adelante en el proceso de desarrollo / lanzamiento.
El hecho de que hayas notado estos problemas tan temprano en tu carrera habla bien para tu futuro, y te deseo la mejor de las suertes.
fuente
Escribir pruebas unitarias
Escribir pruebas unitarias para su código lo obligará a pensar en su arquitectura y lo alentará a escribir su código en piezas pequeñas, cuidadosamente controladas y comprobables. Esto reducirá en gran medida su esfuerzo de depuración, y la pequeña cantidad de depuración que realice se limitará a pequeños fragmentos de código bien enfocados.
Además, las pruebas que escriba "cubrirán" su código; podrá saber cuándo un cambio que realiza en el código rompe algo, porque una o más de sus pruebas existentes fallarán. Esto reduce la complejidad general de su esfuerzo de depuración y aumenta su confianza en que el código funciona.
El problema, por supuesto, es que el tiempo dedicado a la depuración ahora se dedica a escribir pruebas. Pero solo tiene que escribirlos una vez, y se pueden ejecutar tantas veces como sea necesario después de escribirlos.
fuente
El 50% para la depuración (en un sentido amplio) no es tan malo. Por lo general, las personas pasan mucho más tiempo diseñando, probando, reparando errores, refactorizando y escribiendo pruebas unitarias que usted escribiendo el código real. Es parte del trabajo.
Y para ser honesto, es mucho peor en la programación de mantenimiento: con bastante frecuencia, pasaba una hora averiguando qué funciona mal, luego cinco minutos escribiendo el código para solucionarlo, y luego media hora probando todo. Eso es un poco más del 5% de codificación frente a casi el 95% de no codificación.
Sin embargo, hay algunas cosas que puede hacer para reducir el tiempo de depuración:
fuente
Más planificación
Es inevitable que pases una buena parte del tiempo depurando, el 10% es un objetivo bastante ambicioso. Aunque una de las mejores formas de reducir el tiempo dedicado a la depuración y el desarrollo es pasar más tiempo en la fase de planificación.
Esto puede variar desde diagramas hasta pseudocódigo en una plataforma de planificación. De cualquier manera, tendrá más tiempo para mordisquear lo que planea hacer en lugar de cometer esos errores durante el desarrollo.
fuente
Trabajar con más cuidado
Este es el equivalente de software de "medir dos veces cortar una vez":
Dicho todo esto, nada eliminará por completo los defectos. Necesitas aceptar esto como un hecho de la vida. Dado este hecho, planifique defectos, p. Ej. Prueba unitaria. Tampoco tome esto como "tomar para siempre" (también conocido como análisis-parálisis). Se trata de encontrar el equilibrio.
fuente
Otras respuestas ya han cubierto la mayor parte de lo que quiero decir, pero de todos modos quiero darle mi opinión (brutalmente honesta):
Básicamente, para el trabajo de software no trivial, espere pasar la gran mayoría de su tiempo en mantenimiento y depuración. Si está trabajando en un sistema de software de producción maduro y está gastando menos del 80-90% de su tiempo en mantenimiento y depuración, ¡lo está haciendo bien!
Ahora, obviamente, la distinción entre "mantenimiento" y "depuración" es un poco subjetiva. ¿Considera que los "errores" son problemas con el código que se encuentra después de su lanzamiento y los usuarios se han quejado de ellos? ¿O es cada pequeña cosa que sale mal con su código una vez que ha agregado algo (que se encuentra en sus propias fases de prueba de prelanzamiento)? En un sistema de software no trivial (dependiendo de los patrones de uso) uno puede ser mucho más grande que el otro. Pero, en cualquier caso, esto es lo que requiere la programación de algo más grande que un programa "Hello world" de juguete: mucho mantenimiento y depuración. Algunas personas incluso dicen algo así como "se debe esperar que todo después de la primera línea de código sea 'modo de mantenimiento',
TL; DR: Simplemente me parece que puede tener una imagen poco realista de lo que se trata la programación de sistemas de software no triviales. La gran mayoría del esfuerzo consiste en afinar, mantener, refactorizar, corregir errores y, en general, hacer cosas que estarían bajo "depuración" (mantenimiento), al menos en un sentido muy general, en lugar de hacer un trabajo nuevo y totalmente nuevo. escribiendo nuevo código nuevo.
fuente
Es difícil dar técnicas específicas sin detalles específicos sobre lo que está haciendo y qué tecnologías está utilizando. Pero incluso los codificadores realmente buenos pasan mucho tiempo probando y depurando.
Mucho escribir buen código sin muchos errores es experiencia. Cometes errores, luego los corriges, luego recuerdas cuáles fueron los errores y lo que tenías que hacer para corregirlos, y no cometes el mismo error la próxima vez. Y si aún no estás en la universidad y ya estás empezando a pensar seriamente en formas de cometer menos errores, diría que definitivamente estás por delante del juego.
fuente
INTEGRACIÓN CONTINUA (CI) es la respuesta.
Integración continua = Sistema de gestión de configuración (a saber, Git, Mercurial, SVN, etc.) + Herramienta CI + Pruebas unitarias + Pruebas de humo
Esa fórmula debería impulsarlo a leer más sobre Integración Continua (CI). A continuación se presentan algunos recursos en esta área:
fuente
Realmente, para reducir la depuración, puede realizar una carga frontal planificando con mayor profundidad. ¿Aún no has ido a la universidad? Creo que verá en sus clases universitarias de mediados a finales que cubrirá detalles del ciclo de vida de desarrollo de software que muy bien pueden arrojar algo de luz sobre sus locuras.
Mientras trato de explicarles a mis empleadores, la mejor manera de reducir el mantenimiento del código y el soporte técnico es pasar el tiempo para planificar su código de manera integral por adelantado.
fuente
El desarrollo basado en pruebas puede ayudar a reducir el tiempo de depuración al:
Incluso si usa TDD, aún tendrá momentos en los que necesite usar el depurador. Cuando esto sucede, debe intentar escribir una prueba unitaria para reproducir el escenario que causó la sesión de depuración. Esto asegurará que si ese problema vuelve a ocurrir, se detectará rápidamente cuando la prueba falle, y la prueba actuará como un marcador para el área de código que causó el problema, reduciendo la necesidad de depuración.
fuente
La depuración es inevitable en la programación, pero la clave aquí es, ¿es su código fácil de depurar o no? Si necesita pasar horas solo para depurar algo simple, entonces debe haber algo realmente mal con su arquitectura de código.
Debería acostumbrarse a escribir código limpio y eliminar los malos hábitos como copiar el código de pegado y escribir métodos largos, etc.
Además, debe refactorizar su código de vez en cuando. Le sugiero que lea el libro de Martin Fowler: Refactorización: Mejora del diseño de código existente
fuente
Otros han mencionado pruebas y revisión de código. Ambos son extremadamente útiles pero tienen una diferencia clave: cuándo es mejor realizarlos. La prueba se realiza mejor cerca de escribir el código originalmente, para que pueda recordar más fácilmente por qué hizo las cosas de cierta manera y pueda localizar el problema más rápidamente cuando falla la prueba. La revisión del código, por otro lado, se hace mejor un poco más adelante. Desea tener que mirar el código sin un recuerdo perfecto para no pasar por alto detalles en los que recuerda haber pensado pero que no ingresó. Desea darse cuenta de los lugares donde su código no está claro. Desea el pequeño esfuerzo adicional de tener que descubrir qué está haciendo el código. Desea poder aplicar cualquier conocimiento nuevo que haya adquirido sobre el problema o las interacciones con otro código o nuevas técnicas. Básicamente,
Sin embargo, todo esto sigue siendo tangente a su pregunta. Para pasar menos tiempo depurando, debe comprender por qué tuvo que depurar en primer lugar. El malentendido del problema, el conocimiento imperfecto de sus herramientas y tecnologías, y el simple hecho de que "los datos reales no coinciden con los datos de muestra", todos los tipos de problemas se manifestarán de diferentes maneras y necesitarán diferentes técnicas y tipos de práctica para evitar en el futuro.
El último punto que haré es la experiencia. No hay una manera fácil de obtener esto, solo tiene que dedicarle tiempo. A medida que gane experiencia, pasará menos tiempo depurando porque comenzará a escribir un código mejor, notará problemas antes y desarrollará una mejor intuición de cuál podría ser la fuente de un problema. Sigue así y crecerás constantemente a lo largo de tu carrera.
fuente
Grandes respuestas anteriores, pero nadie mencionó directamente (aunque la mayoría insinuó esto):
LEER LEER LEER LEER et en nauseam ...
Cuanto más sabes, menos no sabes. Un poco cliché, pero sigue siendo la verdad básica.
Una vez que haya seguido los consejos anteriores y haya documentado analíticamente los errores, intente clasificarlos y luego lea la literatura pertinente.
¿Fue un problema de decisión de diseño? Lea sobre Patrones de diseño.
¿Fue una falta de conocimiento del marco o el lenguaje? ¡Hágase con eso!
etc.
Hay dos cosas que un desarrollador (en vivo) nunca puede escapar: el cambio (la única constante en TI) y RTFMing ...
fuente
Pruebas unitarias y afirma
Siempre que sea posible, factorice su código en piezas pequeñas que se puedan probar de forma aislada. Sin embargo, esto no siempre es práctico. Algunas piezas de funcionalidad dependen de entradas extremadamente complicadas. Algunos hacen algo que no se puede verificar fácilmente de una manera automatizada, como dibujar cosas en la pantalla. A veces está involucrado el no determinismo, etc.
Cuando no puede escribir buenas pruebas unitarias, la siguiente mejor opción es la afirmación. Mientras que las pruebas unitarias verifican si obtiene la respuesta correcta en alguna entrada predeterminada, afirma verificar la cordura de los pasos intermedios en las entradas del mundo real. Si su código tiene errores, fallará rápidamente, cerca de la raíz del problema y con un mensaje de error claro, en lugar de estar lejos del problema con un mensaje de error ambiguo. Además, afirma suposiciones de documentos y hace que su código sea más legible.
fuente
Cuando comienza un proyecto, ¿cuántos enfoques alternativos identifica?
¿Tiene de dos a cuatro enfoques diferentes, con pros y contras para cada uno? ¿Entonces haces una selección razonada de entre ellos?
Entonces, lo más importante, ¿considera que la simplicidad es tan importante?
La razón por la que pregunto es, en mi experiencia, el volumen de código, y por lo tanto la cantidad de errores (sin mencionar el rendimiento), puede variar en más de un orden de magnitud entre un enfoque de diseño y otro. Lo que veo a personas con mucha experiencia haciendo es realizar trabajos sin más código del necesario.
Son completamente competentes y conocen todos los algoritmos de estructura de datos, características de lenguajes orientados a objetos, etc., pero su código parece no serlo , porque usan esas cosas con moderación , o no lo hacen, si el problema persiste. No los requiero.
fuente
Cada vez que arregles un error, debes evitar cometer el mismo error nuevamente. Para hacerlo, puede hacer lo siguiente:
Anótelo en un registro de registro de defectos , que incluye:
Adopta una guía de estilo para normalizar el estilo del código que escribes
Integre reglas de codificación seguras en su proceso de revisión de código
Visualice el flujo de control y los datos.
Referencias
Un estudio empírico del impacto de PSP en ingenieros individuales (pdf)
Guía de estilo de CPP de Google
Admitiendo derrota en K&R en LCTHW - Zed A. Shaw
Complementos IDE: una forma de prueba de seguridad para automatizar la revisión de código | Comunidad de seguridad cibernética de TCS
Conjunto de reglas de reglas de seguridad para código administrado
Codificación segura en C ++ 11 y C ++ 14
Visualice la ejecución del código Java
Visualización SPARQL
Tutorial WWW2012 Visualización de consultas SPARQL
fuente