La capacidad de encontrar y resolver errores de manera rápida y efectiva en sistemas nuevos y establecidos es una de las habilidades de ingeniería más valiosas que puede desarrollar. Dado que esta habilidad permite el rápido desarrollo y mantenimiento de sistemas de ingeniería de alta calidad, es fundamental para muchas empresas de tecnología y es una de sus habilidades más valoradas y buscadas. Sin embargo, esta habilidad rara vez se evalúa en la codificación de entrevistas y, a menudo, se comprende y se documenta poco.
He depurado y resuelto muchos problemas difíciles en muchos tipos diferentes de sistemas, incluidos procesadores informáticos enormemente complejos, servidores y aplicaciones de subprocesos múltiples, e individuos, familias y organizaciones con problemas. El procedimiento óptimo para encontrar y corregir errores es esencialmente el mismo en todos los dominios. Sorprendentemente, muchos ingenieros de software no tienen una comprensión clara del proceso. Tengo la intención de abordar este déficit ahora. Aquí está mi tratado sobre la depuración.
Cuando algo no funciona como se esperaba, es fácil suponer que todo está roto. Tómese el tiempo para encontrar las cosas que están funcionando en el ámbito del problema. Esto ayudará a circunscribir el problema y crear una imagen clara en su mente de sus bordes.
En el proceso de determinar qué funciona, catalogará un conjunto de operaciones o comportamientos que no funcionan. Dedique tiempo a desarrollar esta lista. Sea claro sobre cómo el sistema no está funcionando como se esperaba. Aunque pueda parecer que estos primeros pasos no tienen sentido porque el problema es "obvio", a menudo lanzarse a resolver el problema demasiado pronto puede conducir a una pérdida de tiempo y esfuerzo, y a una solución parcial o no óptima.
El comportamiento problemático que se descubre en una situación compleja puede ser difícil de reproducir o generalizar, especialmente cuando hay efectos no deterministas o estadísticos. Cualquier intento de simplificar el caso de prueba manteniendo el comportamiento problemático siempre es tiempo bien invertido.
Por ejemplo, si el comportamiento problemático se produce al procesar un conjunto de datos muy grande, es posible que desee intentar reproducir el problema con conjuntos de datos cada vez más pequeños. Por supuesto, este ejemplo no sería posible si el problema está relacionado con grandes conjuntos de datos. En ese caso, la creación de un conjunto de datos simple aunque grande podría tener más sentido.
Al reducir gradualmente la situación en la que surge el problema, no solo aumenta su claridad sobre lo que funciona y lo que no funciona, sino que también comienza naturalmente a construir hipótesis sobre lo que podría estar causando el problema.
Los casos de prueba simples son útiles para comunicar con precisión el error a otros, para probar rápidamente si los cambios afectan el error y también pueden convertirse en parte de sus pruebas antirregresión (consulte el paso 7). Dado que los casos de prueba simples generalmente se pueden ejecutar rápidamente, también admiten la prueba de hipótesis (consulte el paso 5).
Puede llegar a este punto después de minutos, horas, días o incluso semanas de trabajo. No importa cómo llegó aquí o cuánto tiempo tomó, ahora tendrá datos y habrá aprendido algo sobre la forma en que se manifiesta el problema. Este conocimiento le permite formular hipótesis sobre lo que podría estar causando el problema. Estas son teorías sobre qué proceso dentro (o incluso fuera) del sistema podría estar conduciendo al comportamiento problemático observado.
Tomando cada hipótesis por turno, sumérgete en el sistema y encuentra una subunidad en la que creas que algo puede estar saliendo mal. Luego ejecute su pequeño caso de prueba y observe el comportamiento interno antes y después de esa subunidad. Si encuentra un problema antes de esa subunidad, entonces su hipótesis puede haber sido incorrecta, y al menos sabe que necesita investigar más atrás hacia la entrada del sistema. Si, por otro lado, la entrada a esa parte del sistema parece correcta, pero la salida parece incorrecta, entonces tiene respaldo para su hipótesis y puede acercarse más.
En este punto, si no tiene completamente claro cuál es el error, vuelva al paso 1 en esta subunidad identificada.
En este punto, es posible aplicar divide y vencerás de manera muy ingenua: dividir el sistema arbitrariamente en dos mitades, buscar un problema en cada mitad y luego acercar recursivamente la mitad no funcional. No recomiendo este enfoque porque suele ser muy lento y engorroso.
Por otro lado, es posible ahorrar mucho tiempo y esfuerzo utilizando el divide y vencerás basado en hipótesis , como se describió anteriormente. Todavía verifica si el comportamiento es el esperado justo antes de la subunidad que se supone que está rota, pero, si las cosas funcionan allí, va directamente a la salida de esa subunidad. Esto permite un acercamiento muy rápido al error.
Solo continúe con el siguiente paso una vez que tenga claro cuál es el error.
A veces, los errores son causados por simples errores tipográficos o malentendidos únicos, y este tipo de errores se pueden corregir de forma aislada. Sin embargo, es mucho más común que los errores representen una clase de problemas mucho mayor.
Después de dedicar tiempo y esfuerzo para llegar a este paso, por lo general tendrá una percepción increíblemente clara de las partes relevantes del sistema y del problema. Serás el experto de clase mundial en este error. Por esta razón, ahora es el momento de aprovechar todo ese conocimiento. En un mes, ya no tendrás esta claridad de percepción con respecto a este problema específico.
Dedique tiempo ahora a aprovechar al máximo su inversión. Piense y documente la clase general de error, y determine si es probable que el sistema manifieste otras expresiones de los problemas subyacentes, ya sea que esas expresiones particulares se hayan manifestado a los usuarios o no.
No queremos poner una tirita en un tumor maligno y enviar al paciente a casa.
Incluso si no diseña sistemas utilizando el desarrollo basado en pruebas, le recomiendo que utilice la corrección de errores basada en pruebas.
Asegúrese de escribir pruebas a nivel de unidad y/o a nivel de sistema que ejerzan la mayor cantidad posible de la clase de error. Asegúrese de que las pruebas que espera que fallen, de hecho fallen. La razón principal por la que existe el error es que no hubo pruebas para detectarlo. Esto significa que había un agujero en el conjunto de pruebas. A menudo digo que si algo no se prueba, entonces está roto. Esto se debe a que debe suponer que está roto ahora o que se romperá en algún momento en el futuro, y luego la primera persona en descubrir que está roto será un cliente.
Dado que tiene un sistema roto en este momento, ahora es una oportunidad perfecta para desarrollar pruebas y asegurarse de que fallen. Estas oportunidades no surgen con frecuencia, así que aprovéchelas mientras estén disponibles.
Me gusta llamar a las pruebas de regresión pruebas anti -regresión, porque evitan que el producto regrese a un estado anterior roto. Ejecute su conjunto de pruebas con todas sus pruebas antes de lanzar nuevas revisiones de su producto.
Si ha sido diligente, corregir los errores ahora será extremadamente fácil; es solo una formalidad.
Este tipo de corrección de errores se puede realizar con mucha calma y confianza. La solución está envuelta en un proceso de ingeniería de software de alta calidad, un proceso que lo informa y lo prueba. Por el contrario, he sido testigo de ingenieros que operan en el extremo opuesto de la escala, cambiando el código casi al azar con la esperanza de que solucione el problema general. Es más probable que ese tipo de enfoque introduzca nuevos errores que corrija los existentes.
Mientras corrige los errores, es posible que note otros problemas. En ese caso, también vuelva a un paso anterior, como el paso 6.
Todas las nuevas pruebas deberían pasar ahora. Si no pasan, deberá volver a un paso anterior y resolver el problema.
En este punto, debería ser posible ejecutar los casos de prueba simples que desarrolló en el paso 3, y deberían funcionar correctamente. De lo contrario, vuelva a un paso anterior para resolver el problema.
Ahora debería poder realizar los comportamientos originalmente informados como problemáticos, y ya no debería ver un problema. Si ve un problema, vuelva a un paso anterior para resolverlo.
Acabas de realizar un conjunto de maniobras de ingeniería de muy alta calidad. Este es el material del que están hechas las leyendas. Es posible que seas la única persona que está al tanto de tus acciones heroicas. Anótelos para que puedan convertirse en parte de la tradición de la ingeniería. Documente el código, documente el plan de prueba, documente el conjunto de pruebas, escriba una página wiki o una publicación de blog. Haz algo para capturar la sabiduría que has desarrollado y ponerla a disposición de los demás. Su documentación también educará y guiará a otros. Estará dando un buen ejemplo a otros ingenieros, un ejemplo de cómo usar los recursos de manera efectiva y eficiente, y también de cómo ejecutar un trabajo de ingeniería desafiante de una manera que sea profundamente satisfactoria y nutritiva para el alma.
Durante el tiempo que ha centrado su atención en resolver este problema en particular, es posible que haya notado otras clases potenciales de errores y posiblemente otras clases manifiestas de errores. Presente informes de errores para problemas que se manifiestan en un comportamiento disfuncional, o que está seguro de que están al acecho sin ser detectados. Para otras posibles clases de errores que pueden no estar presentes pero que tampoco se pueden probar actualmente, tome las medidas necesarias para dirigir el esfuerzo de prueba hacia ellos. Por ejemplo, puede actualizar un documento de ideas de planes de prueba.
Publique su solución, ya sea interna o externamente, y asegúrese de que todos sepan lo que hizo. Resuma el problema y la solución de manera sucinta e incluya vínculos a la documentación que creó.
Acabas de hacer una ingeniería increíble y de alta calidad. Date una palmadita en la espalda y dirígete a hacer otra cosa que sea sobresaliente.