Trabajo para una empresa de productos de software. Tenemos grandes clientes empresariales que implementan nuestro producto y les brindamos asistencia. Por ejemplo, si hay un defecto, proporcionamos parches, etc. En otras palabras, es una configuración bastante típica.
Recientemente, se emitió y me asignó un ticket con respecto a una excepción encontrada por un cliente en un archivo de registro que tiene que ver con el acceso simultáneo a la base de datos en una implementación agrupada de nuestro producto. Por lo tanto, la configuración específica de este cliente puede ser crítica en la aparición de este error. Todo lo que obtuvimos del cliente fue su archivo de registro.
El enfoque que le propuse a mi equipo fue intentar reproducir el error en una configuración de configuración similar a la del cliente y obtener un registro comparable. Sin embargo, no están de acuerdo con mi enfoque y dicen que no necesito reproducir el error ya que consume demasiado tiempo y requeriré simular un clúster de servidores en máquinas virtuales. Mi equipo sugiere que simplemente "siga el código" para ver dónde está el código inseguro de transacciones y / o subprocesos y poner el cambio en función de un desarrollo local simple, que no es una implementación de clúster como el entorno del que ocurre del error se origina.
Para mí, trabajar a partir de un plan abstracto (código de programa) en lugar de una manifestación tangible y visible (reproducción en tiempo de ejecución) parece difícil, por lo que quería hacer una pregunta general:
¿Es razonable insistir en reproducir cada defecto y depurarlo antes de diagnosticarlo y repararlo?
O:
Si soy un desarrollador sénior, ¿debería ser capaz de leer código multiproceso y crear una imagen mental de lo que hace en todos los escenarios de casos de uso en lugar de requerir la ejecución de la aplicación, probar diferentes escenarios de casos de uso de manera práctica y pasar por el código línea por línea? ¿O soy un desarrollador pobre por exigir ese tipo de ambiente de trabajo?
¿La depuración de las mariquitas?
En mi opinión, cualquier corrección presentada en respuesta a un ticket de incidente debe probarse en un entorno simulado para estar lo más cerca posible del entorno original. ¿De qué otra manera puede saber que realmente solucionará el problema? Es como lanzar un nuevo modelo de vehículo sin chocar probándolo con un maniquí para demostrar que las bolsas de aire funcionan.
Por último, pero no menos importante, si estás de acuerdo conmigo:
¿Cómo debería hablar con mi equipo para convencerlos de que mi enfoque es razonable, conservador y más a prueba de balas?
new
. Y estos errores no se garantiza que sea reproducible de forma fiable, de acuerdo con la especificación de memoria de Java ModeloRespuestas:
Debes darle tu mejor esfuerzo. Sé que a veces hay condiciones y entornos que son tan complejos que no se pueden reproducir exactamente , pero sin duda deberías intentarlo si puedes.
Si nunca reprodujo el error y lo vio por sí mismo, ¿cómo puede estar 100% seguro de que realmente lo solucionó? Tal vez su corrección propuesta introduce algún otro error sutil que no se manifestará a menos que realmente intente reproducir el defecto original.
No confiaría en alguien que ejecuta el código "en su cabeza", si ese es su único enfoque. Es un buen lugar para comenzar . Reproducir el error, corregirlo y luego demostrar que la solución evita que el error vuelva a ocurrir, ahí es donde debería terminar .
Porque si nunca reprodujeron el error, no pueden saber con certeza si está solucionado. Y si el cliente regresa y se queja de que el error sigue ahí, eso no es bueno. Después de todo, le están pagando grandes $$$ (supongo) para lidiar con este problema.
Si no soluciona el problema correctamente, ha roto la fe con el cliente (hasta cierto punto) y si hay competidores en su mercado, es posible que no sigan siendo su cliente.
fuente
¿Cómo pretenden verificar que el error en cuestión se haya solucionado? ¿Quieren enviar código no probado al usuario y dejar que lo resuelvan? No se puede confiar en cualquier configuración de prueba que nunca se haya demostrado que reproduzca el error para mostrar la ausencia del error. Ciertamente no necesita reproducir todo el entorno del cliente, pero sí lo suficiente para reproducir el error.
No creo que sea irrazonable intentar reproducir cada error antes de corregirlo. Sin embargo, si intenta reproducirlo y no puede, entonces se convierte en una decisión comercial más de si los parches ciegos son una buena idea.
fuente
Idealmente, desea poder reproducir cada error para que, al menos, pueda probar que se ha solucionado.
Pero ... Eso puede no ser siempre factible o incluso físicamente posible. Especialmente con el software de tipo 'empresarial' donde cada instalación es única. También está la evaluación de costo / beneficio. Un par de horas revisando el código y haciendo algunas conjeturas sobre un problema no crítico puede costar mucho menos que tener un equipo de soporte técnico que pase semanas tratando de configurar y duplicar el entorno de un cliente exactamente con la esperanza de poder duplicar el problema. Antes, cuando trabajaba en el mundo 'Enterprise', solíamos volar a los codificadores y hacer que repararan errores en el sitio, porque no había forma de duplicar la configuración del cliente.
Entonces, duplique cuando pueda, pero si no puede, aproveche su conocimiento del sistema e intente identificar al culpable en el código.
fuente
No creo que deba hacer que la reproducción del error sea un requisito para mirar el error. Como ya mencionó, hay varias formas de depurar el problema, y debe usarlas todas. ¡Debería considerarse afortunado de que pudieran darle un archivo de registro! Si usted o alguien de su empresa puede reproducir el error, ¡genial! De lo contrario, aún debe intentar analizar los registros y encontrar las circunstancias bajo las cuales ocurrió el error. Puede ser posible, como sugirieron sus colegas, leer el código, descubrir qué condiciones podría ocurrir el error y luego intentar recrear el escenario usted mismo.
Sin embargo, no publique la corrección real sin probar. Cualquier cambio que realice debe pasar por la rutina estándar de desarrollo, pruebas de control de calidad y pruebas de integración. Puede resultar difícil de probar: mencionó código multiproceso, que es notoriamente difícil de depurar. Aquí es donde estoy de acuerdo con su enfoque para crear una configuración o entorno de prueba. Si ha encontrado un problema en el código, le resultará mucho más sencillo crear el entorno, reproducir el problema y probar la solución.
Para mí, esto es menos un problema de depuración y más un problema de servicio al cliente. Has recibido un informe de error de un cliente; usted tiene la responsabilidad de hacer la debida diligencia para encontrar su problema y solucionarlo.
fuente
En mi opinión ... como tomador de decisiones, debe ser capaz de justificar su posición. Si el objetivo del departamento de soporte de la tercera línea es corregir errores en el menor tiempo posible con el esfuerzo aceptable del cliente, entonces cualquier enfoque debe cumplir con ese objetivo. Además, si se puede demostrar que el enfoque brinda los resultados esperados más rápidos, entonces no debería haber ningún problema para convencer al equipo.
Después de haber trabajado en soporte, siempre he esperado razonablemente que el cliente pueda dar algún "guión" de las acciones que realizó para reproducir el error de manera consistente y, si no es así, los ejemplos de candidatos que han producido el error.
Si fuera nuevo en el sistema y no tuviera antecedentes con el código, mis primeros pasos serían intentar identificar las posibles fuentes del error. Puede ser que el registro sea insuficiente para identificar un código candidato. Dependiendo del cliente, podría inclinarme a darles una versión de depuración para que puedan devolverle los archivos de registro que brindan más pistas sobre la posición del código infractor.
Si puedo identificar rápidamente el bloque de código, entonces el mapeo visual del flujo puede ser suficiente para detectar el código. De lo contrario, la simulación basada en pruebas unitarias puede ser suficiente. Puede ser que la configuración de un entorno de replicación del cliente requiera menos tiempo, especialmente si existe una gran posibilidad de replicación del problema.
Creo que puede encontrar que su enfoque debe ser una combinación de las soluciones propuestas y que saber cuándo dejar una y pasar a la siguiente es clave para hacer el trabajo de manera eficiente.
Estoy bastante seguro de que el equipo respaldará la idea de que si existe la posibilidad de que su solución encuentre el error más rápido, les dará un marco de tiempo adecuado para demostrar que no afectará demasiado el tiempo que lleva corregir el error, lo que sea ruta que tomas.
fuente
Yo digo que sí, con algunas advertencias.
He estado en el lado del cliente de la mesa en este escenario. Estaba trabajando en una oficina del gobierno de EE. UU. Que utilizaba un clúster de base de datos Oracle increíblemente grande (varios terabytes de datos y procesaba millones de registros por día).
Nos encontramos con un extraño problema que nos fue muy fácil de reproducir. Reportamos el error a Oracle, y fuimos y vinimos con ellos durante semanas, enviándoles registros. Dijeron que no podían reproducir el problema, pero nos enviaron algunos parches que esperaban que pudieran solucionar el problema. Ninguno de ellos lo hizo.
Finalmente, llevaron a un par de desarrolladores a nuestra ubicación para depurar el problema en el sitio. Y fue entonces cuando se encontró la causa raíz del error y un parche posterior solucionó correctamente el problema.
fuente
Si no eres positivo sobre el problema, no puedes ser positivo sobre la solución. Saber cómo reproducir el problema de manera confiable en al menos una situación de caso de prueba le permite demostrar que sabe cómo causar el error y, por lo tanto, también le permite probar, por otro lado, que el problema se ha resuelto, debido a la falta posterior de error en el mismo caso de prueba después de aplicar la corrección.
Dicho esto, las condiciones de carrera, los problemas de concurrencia y otros errores "no deterministas" se encuentran entre los más difíciles de precisar para un desarrollador de esta manera, porque ocurren con poca frecuencia en un sistema con mayor carga y más complejidad que la copia de cualquier desarrollador. el programa, y desaparecen cuando la tarea se vuelve a ejecutar en el mismo sistema más adelante.
La mayoría de las veces, lo que originalmente parece un error aleatorio termina teniendo una causa determinista que hace que el error sea reproducible de forma determinista una vez que se sabe cómo. Los que desafían esto, los verdaderos Heisenbugs (errores aparentemente aleatorios que desaparecen al intentar probarlos en un ambiente estéril y monitoreado), están 99.9% relacionados con el tiempo, y una vez que comprende eso, su camino hacia adelante se vuelve más claro; busque cosas que podrían fallar si otra cosa tuviera una palabra de borde durante la ejecución del código, y cuando encuentre tal vulnerabilidad, intente explotarla en una prueba para ver si exhibe el comportamiento que está tratando de reproducir.
Generalmente se requiere una cantidad significativa de inspección de código en profundidad en estas situaciones; debe mirar el código, abandonar cualquier noción preconcebida de cómo se supone que debe comportarse el código e imaginar escenarios en los que podría fallar en la forma en que su cliente lo ha observado. Para cada escenario, intente desarrollar una prueba que pueda ejecutarse eficientemente dentro de su entorno de prueba automatizado actual (es decir, sin necesidad de una nueva pila de VM solo para esta prueba), que probaría o refutaría que el código se comporta como esperaba ( que, según lo que esperaba, probaría o refutaría que este código es una posible causa de los problemas de los clientes). Este es el método científico para ingenieros de software; observar, formular hipótesis, probar, reflexionar, repetir.
fuente
No, definitivamente no lo es. Esa sería una política estúpida.
El problema que veo con su pregunta y su propuesta es que no logran hacer una distinción entre
Un informe de error es la comunicación sobre un error. Te dice que alguien piensa que algo está mal. Puede o no ser específico sobre lo que se supone que está mal.
Un informe de error es evidencia de una falla.
Una falla es un incidente de algo que sale mal. Un mal funcionamiento específico, pero no necesariamente con alguna pista de lo que puede haberlo causado.
Una falla puede ser causada por un error.
Un error es una causa de fallas; algo que (en principio) se puede cambiar para evitar que ocurran fallas en el futuro.
A veces, cuando se informa un error, la causa es clara de inmediato. En tal caso, reproducir el error no tendría sentido. En otras ocasiones, la causa no está clara en absoluto: el informe de error no describe ninguna falla en particular, o lo hace, pero la falla es tal que no proporciona una pista sobre cuál podría ser la causa. En tales casos, creo que su consejo está justificado, pero no siempre: uno no insiste en estrellarse un segundo cohete espacial de $ 370 millones antes de aceptar investigar qué causó el primer accidente (un error particular en el software de control).
Y también hay todo tipo de casos en el medio; por ejemplo, si un informe de error no prueba, pero solo sugiere, que un problema potencial del que ya era consciente podría desempeñar un papel, esto podría ser un incentivo suficiente para que lo examine más de cerca.
Entonces, aunque insistir en la reproducibilidad es prudente para los casos más difíciles, no es prudente aplicarlo como una política estricta.
fuente
Como con todo lo demás en el desarrollo de software, la respuesta correcta es un compromiso.
En teoría, nunca debe intentar corregir un error si no puede probar que existe. Si lo hace, puede hacer cambios innecesarios en su código que finalmente no resuelven nada. Y probarlo significa reproducirlo primero, luego crear y aplicar un arreglo, luego demostrar que ya no sucede. Tu instinto aquí es guiarte en la dirección correcta: si quieres estar seguro de que has resuelto el problema de tu cliente, debes saber qué lo causó en primer lugar.
En la práctica, eso no siempre es posible. Quizás el error solo ocurre en grandes grupos con docenas de usuarios que acceden simultáneamente a su código. Quizás haya una combinación específica de operaciones de datos en conjuntos específicos de datos que desencadena el error y no tiene idea de qué es eso. Quizás su cliente ejecutó el programa interactivamente sin parar durante cientos de horas antes de que se manifestara el error.
En cualquiera de esos casos, existe una gran posibilidad de que su departamento no tenga el tiempo o el dinero para reproducir el error antes de comenzar a trabajar. En muchos casos, es mucho más obvio para usted, el desarrollador, que hay un error en el código que lo señala a la situación correcta. Una vez que haya diagnosticado el problema, es posible que pueda regresar y reproducirlo. No es lo ideal, pero al mismo tiempo, parte de su trabajo como desarrollador senior es saber leer e interpretar el código, en parte para localizar este tipo de errores enterrados.
En mi opinión, te estás centrando en la parte incorrecta de la pregunta. ¿Qué pasa si finalmente no puede reproducir el error en cuestión? Nada es más frustrante para un cliente que escuchar "sí, sabemos que bloqueó el programa, pero no podemos reproducirlo, por lo que no es un error". Cuando su cliente escucha esto, lo interpreta como "sabemos que nuestro software tiene errores, pero no podemos molestarnos en arreglarlos y solucionarlos, así que simplemente cruce los dedos". ¿Es mejor cerrar un error reportado como "no reproducible", o cerrarlo como "no reproducible", pero hemos realizado algunos cambios razonables para tratar de mejorar la estabilidad?
fuente
A menos que el error sea evidente, obvio y trivial, con un mensaje de error muy específico, etc., a menudo es muy difícil corregir un error si el usuario o el mantenedor no pueden replicarlo.
Además, ¿cómo les probarías que el error se soluciona si no puedes replicar los pasos?
El problema con su caso es que el usuario tampoco sabe cómo ocurrió el error, es decir, en qué pantalla hacer qué operación. Simplemente tienen el registro.
Creo que tu punto es razonable. Si tuvieras poderes psíquicos , posiblemente no estarías trabajando por un salario.
Creo que debería decirles a sus jefes que, sin poder replicar el error, tomaría una cantidad de tiempo desconocida descubrirlo, y no hay garantía alguna de que lo haga.
El problema será cuando algún compañero de trabajo encuentre el error por pura suerte y lo arregle.
fuente
Llevémoslo al extremo y supongamos que encontraste el error mucho antes: en tu código, como lo estabas escribiendo. Entonces no tendrías reparos en arreglarlo allí mismo: ves una falla lógica en el código que acabas de escribir, no hace lo que querías que hiciera. No sentiría la necesidad de configurar un entorno completo para mostrar que en realidad es un error.
Ahora entra un informe de error. Hay varias cosas que puede hacer. Una de ellas es volver al código y volver a leerlo. Ahora suponga que en esta segunda lectura, inmediatamente encuentra el error en el código: simplemente no hace lo que pretendía que hiciera y no se dio cuenta cuando lo escribió. Y , ¡explica perfectamente el error que acaba de llegar! Tú haces la solución. Te llevó veinte minutos.
¿Eso solucionó el error que causó el informe del error? No puede estar 100% seguro (puede haber dos errores que causen lo mismo), pero probablemente lo hizo.
Otra cosa que podría hacer es reproducir la configuración del cliente lo mejor que pueda (unos días de trabajo) y, finalmente, reproducir el error. En muchos casos, hay problemas de sincronización y concurrencia que significan que no puede reproducir el error, pero puede intentarlo mucho tiempo y, a veces, ver que sucede lo mismo. Ahora comienza a depurar, encuentra el error en el código, lo coloca en el entorno e intenta muchas veces nuevamente. Ya no ves que ocurra el error.
¿Eso solucionó el error que causó el informe del error? Todavía no puede estar 100% seguro: uno, es posible que haya visto un error completamente diferente al que hizo el cliente, dos, tal vez no lo intentó con la frecuencia suficiente y tres, tal vez la configuración sigue siendo ligeramente diferente y es arreglado en este sistema, pero no en el del cliente.
Por lo tanto, es imposible obtener certeza en cualquier caso. Pero el primer método es mucho más rápido (también puede darle un parche al cliente más rápido), es mucho más barato y, si encuentra un error de codificación claro que explica el síntoma, es más probable que también encuentre el problema.
Entonces eso depende. Si es barato configurar un entorno de prueba (o mejor: una prueba automatizada que muestra el problema), entonces hazlo. Pero si es costoso y / o las circunstancias en las que el error muestra son impredecibles, siempre es mejor tratar de encontrar el error leyendo primero el código.
fuente
Al leer la pregunta, no veo ninguna oposición fundamental entre tu posición y la de tu equipo.
Sí, debe hacer su mejor esfuerzo para reproducir el problema que ocurre en la configuración del cliente. Pero el mejor esfuerzo significa que debe definir un cuadro de tiempo para eso, y puede que no haya suficientes datos en el registro para reproducir realmente el problema.
Si es así, todo depende de la relación con este cliente. Puede ir desde que no tendrá nada más de él, hasta que pueda enviar un desarrollador en el sitio con herramientas de diagnóstico y la capacidad de ejecutarlas en el sistema que falla. Por lo general, estamos en algún punto intermedio y si los datos iniciales no son suficientes, hay maneras de obtener más.
Sí, un desarrollador senior debería poder leer el código y es probable que encuentre la razón del problema después del contenido del registro. Realmente, a menudo es posible escribir alguna prueba unitaria que muestre el problema después de leer cuidadosamente el código.
Tener éxito escribiendo tales pruebas unitarias es casi tan bueno como reproducir el entorno funcional de última hora. Por supuesto, este método tampoco garantiza que encontrará nada. Comprender la secuencia exacta de eventos que conducen a fallas en algunos software de subprocesos múltiples puede ser realmente difícil de encontrar simplemente leyendo el código, y es probable que la capacidad de depurar en vivo se vuelva crítica.
En resumen, trataría de ambos enfoques simultáneamente y pediría un sistema en vivo que muestre el problema (y que muestre que se solucionó después) o que se rompa alguna prueba de la unidad del problema (y que también se muestre solucionado después de la solución).
Intentar arreglar el código y enviarlo en la naturaleza, de hecho, parece muy arriesgado. En algunos casos similares que me ocurrieron (donde no pudimos reproducir el defecto internamente), dejé en claro que si una solución salía a la luz y no resolvía el problema del cliente, o tenía otras consecuencias negativas inesperadas, el tipo que propuso Tendría que ayudar al equipo de soporte a encontrar el problema real. Incluyendo tratar con el cliente si es necesario.
fuente
Me parece que necesita un registro más detallado.
Si bien agregar más registros no puede garantizar que no necesite depurar (o, en este caso, reproducir la situación), le dará una mejor idea de lo que realmente salió mal.
Especialmente en situaciones complicadas / enhebradas, o cualquier cosa en la que no pueda usar un depurador, recurrir a "debug by printf ()" podría ser su único recurso. En ese caso, registre todo lo que pueda (más de lo que espera necesitar) y tenga algunas buenas herramientas para filtrar el trigo de la paja.
fuente
Como nadie lo dijo en términos claros todavía: ¡ Absolutamente no!
Como todo lo demás en el desarrollo de software, la corrección de errores significa tener en cuenta el tiempo, el riesgo y el costo. Encontrar un equilibrio entre estos es la mitad de la descripción del trabajo de un desarrollador.
Algunos errores no son lo suficientemente importantes como para pasar 2 días, pero lo suficientemente importantes como para pasar 10 minutos para solucionarlos. Otros errores no son deterministas y usted ya sabe que un entorno de prueba no puede probar que se han solucionado. Si configurar el entorno de prueba lleva 2 días, no lo hace para estos errores. En cambio, pasa el tiempo en cosas más inteligentes, como encontrar formas de configurar un entorno de prueba en 5 minutos en lugar de 2 días.
Y, por supuesto, hay errores en los que si se equivoca, un cliente perderá $ 100'000 +. Y errores en los que el cliente perderá $ 100'000 + por cada hora que el error no se corrige. Debes mirar el error y tomar una decisión. Las declaraciones generales para tratar todos los errores de la misma manera no funcionan.
fuente
Muy buena pregunta! Mi opinión es que si no puede reproducir el problema, entonces no puede 100% seguro decir que la solución que realizó no:
a) realmente soluciona el problema. b) crear otro error
Hay momentos en que ocurre un error y lo soluciono y no me molesto en probarlo. Sé 100% seguro de que funciona. Pero hasta que nuestro departamento de control de calidad diga que está funcionando, entonces considero que todavía existe la posibilidad de que todavía haya un error presente ... o un nuevo error creado a partir de la corrección.
Si no puede reproducir el error y luego instala la nueva versión y confirma que está solucionado, no puede, con 100% de certeza, decir que el error se ha ido.
Intenté por unos minutos pensar en una analogía para ayudarlo a explicar a los demás, pero en realidad no se me ocurrió nada. Una vasectomía es un ejemplo divertido, pero no es la misma situación :-)
fuente
InvariantCulture
dentro de unCompareExchange
ciclo, pero luego la restablece [de modo que siCompareExchange
falla la primera vez, la variable de cultura "guardada" se sobrescribirá] . Reproducir las circunstancias del fallo sería difícil, pero el código es claramente incorrecto y podría causar el problema indicado.No pasaría demasiado tiempo intentando reproducirlo. Parece un problema de sincronización y se encuentran con mayor frecuencia razonando (comenzando desde registros como el que tiene que identificar el subsistema en el que ocurre el problema) que al encontrar una manera de reproducirlo y atacarlo con un depurador . En mi experiencia, reducir el nivel de optimización del código o, a veces, e incluso activar instrumentación adicional puede ser suficiente para agregar suficiente retraso o la falta de primitiva de sincronización para evitar que el error se manifieste.
Sí, si no tiene una manera de reproducir el error, no podrá estar seguro de que lo soluciona. Pero si su cliente no le da la forma de reproducirlo, también puede estar buscando algo similar con la misma consecuencia pero una causa raíz diferente.
fuente
Ambas actividades (revisión de código y pruebas) son necesarias, ni son suficientes.
Podrías pasar meses construyendo experimentos tratando de reprobar el error, y nunca llegar a ningún lado si no miras el código y formulas una hipótesis para reducir el espacio de búsqueda. Puede pasar meses mirando su ombligo tratando de visualizar un error en el código, incluso podría pensar que lo ha encontrado una, dos, tres veces, solo para que el cliente cada vez más impaciente diga: "No, el error sigue ahí. "
Algunos desarrolladores son relativamente mejores en una actividad (revisión de código versus pruebas de construcción) que en la otra. Un gerente perfecto sopesa estas fortalezas al asignar errores. Un enfoque de equipo puede ser aún más fructífero.
En última instancia, puede que no haya suficiente información para reprobar el error, y debe dejarlo marinar por un tiempo esperando que otro cliente encuentre un problema similar, lo que le dará más información sobre el problema de configuración. Si el cliente que vio el error realmente quiere que se solucione, trabajará con usted para recopilar más información. Si este problema solo surgió una vez, probablemente no sea un error de alta prioridad, incluso si el cliente es importante. A veces, no solucionar un error es más inteligente que pasar horas de trabajo buscando un defecto realmente oscuro con información insuficiente.
fuente