¿Otras personas corrigen errores cuando los ven, o esperan hasta que se producen bloqueos / pérdida de datos / personas mueren antes de arreglarlo?
Ejemplo 1
Customer customer = null;
...
customer.Save();
El código es claramente incorrecto, y no hay forma de evitarlo: está llamando a un método con una referencia nula. Sucede que no se bloquea porque Save
no tiene acceso a ningún dato de instancia; entonces es como llamar a una función estática. Pero cualquier pequeño cambio en cualquier lugar puede causar de repente un código roto que no se bloquea: comenzar a fallar.
Pero tampoco es inconcebible que corregir el código:
Customer customer = null;
...
customer = new Customer();
try
...
customer.Save();
...
finally
customer.Free();
end;
podría introducir un choque; uno no descubierto a través de pruebas unitarias con cobertura completa y pruebas manuales de usuario.
Ejemplo 2
float speed = 0.5 * ((G * mass1 * mass2) / R) * Pow(time, 2);
La gente que sabe la física reconocerán que se supone que debe ser R 2 en el denominador.
El código está mal, está absolutamente mal. Y sobreestimar la velocidad hará que los retrocohetes disparen demasiado pronto, matando a todos los ocupantes de la nave espacial.
Pero también es posible que quizás sobreestimar la velocidad esté enmascarando otro problema: las bolsas de aire no pueden desplegarse mientras el transbordador se mueve demasiado rápido. Si de repente arreglamos el código:
float speed = 0.5 * ((G * mass1 * mass2) / Pow(R, 2)) * Pow(time, 2);
Ahora la velocidad es precisa y, de repente, las bolsas de aire se están desplegando cuando no deberían.
Ejemplo 3
Aquí hay un ejemplo que tuve recientemente, comprobando si una cadena contiene caracteres no válidos:
if (StrPos(Address, "PO BOX") >= 0)
{
//Do something
}
¿Qué pasa si resulta que hay un error en la Do something
rama? Arreglando el código obviamente incorrecto:
if (StrPos("PO BOX", Address) >= 0)
{
//Do something
}
Corrige el código, pero introduce un error.
A mi modo de ver, hay dos posibilidades:
- arregla el código y te culpan por romperlo
- espere a que el código se bloquee y se le culpe por tener un error
¿Qué haces políticamente?
Ejemplo 4 - El error del mundo real de hoy
Estoy construyendo un objeto, pero llamando al constructor incorrecto:
Customer customer = new Customer();
Resulta que el constructor "sin parámetros" es en realidad un constructor parametrizado desde más atrás en la cadena de herencia:
public Customer(SomeObjectThatNobodyShouldBeUsingDirectly thingy = null)
public Customer(InjectedDependancy depends)
Llamarlo es un error, ya que omite todos los constructores posteriores.
Podría cambiar el linaje del objeto para no exponer un constructor tan peligroso, pero ahora tengo que cambiar el código a:
Customer customer = new Customer(depends);
Pero no puedo garantizar que este cambio no rompa nada. Al igual que mi Ejemplo 1 anterior, tal vez alguien, en algún lugar, de alguna manera, bajo algunas condiciones esotéricas, depende de lo construido Customer
para ser inválido y lleno de basura.
Tal vez el Customer
objeto, ahora que está construido correctamente , permitirá que se ejecute un código que nunca antes lo hizo, y ahora puedo obtener un bloqueo.
No puedo apostar la vida de tu esposa.
Y puedo probarlo desde aquí hasta el martes, no puedo jurar por la vida de tu hija que no introduje una regresión.
¿Yo:
- ¿Arreglar el código y ser culpado por romperlo? o
- ¿Dejar el error y ser culpado cuando el cliente lo encuentra?
fuente
Respuestas:
Esto depende enormemente de la situación, el error, el cliente y la empresa. Siempre hay una compensación a considerar entre corregir la implementación y potencialmente introducir nuevos errores.
Si tuviera que dar una pauta general para determinar qué hacer, creo que sería algo así:
Eso sí, esto solo se aplica cuando estás cerca de un lanzamiento. Si está en modo de desarrollo completo, simplemente registraría el defecto para que pueda rastrearse, arreglarlo y llamarlo. Si es algo que lleva más de, por ejemplo, media hora arreglarlo y verificarlo, iría al gerente / líder del equipo y veré si el defecto debe encajar o no en el ciclo de lanzamiento actual o programarse para un momento posterior.
fuente
Los clientes SIEMPRE encontrarán errores . No hay errores ocultos de los clientes, nunca. Al final, los errores que introduzcas siempre volverán a ti. No arreglarlos es simplemente una mala práctica profesional. Los profesionales no hacen esto.
Cuando los clientes encuentran errores, la empresa se ve mal, no un desarrollador individual. Esto es mucho peor para la empresa, por lo que está su caso para hacer el cambio. Si realmente no está seguro de hacer este cambio por temor a introducir otros errores, hable con un desarrollador más experimentado, un líder técnico del proyecto o con cualquier otra persona que esté en condiciones de tomar una decisión sobre dicho cambio y, posteriormente, manejar las consecuencias.
fuente
Arreglar el error
Somos profesionales aquí. Si encuentra una ruta de error en el código que causará un bloqueo o un comportamiento incorrecto, debe corregirlo. Dependiendo de los procedimientos de su equipo, es probable que necesite presentar un defecto, tal vez escribir una prueba de regresión y verificar la corrección en el momento correcto del ciclo de envío. Si se trata de un error de baja prioridad, verificar la corrección cerca del comienzo de un hito siempre es un buen momento porque si causa una regresión no afectará el ciclo de lanzamiento del hito.
No confunda esto con refactorizar o realizar mejoras de rendimiento que no estén relacionadas con un error de rendimiento.
Un sistema de control de fuente distribuido donde puede mantener un repositorio separado de 'pequeñas correcciones de errores' y luego combinar fácilmente al comienzo de un hito es de gran ayuda aquí.
fuente
¿Qué diría el cliente?
Así es como me imagino que esto se desarrolla:
Sí. Arregla el error. Ahorrará al cliente de una experiencia agravante y podrá solucionarlo antes de que se convierta en una emergencia.
Y si cree que su solución podría causar un bloqueo, entonces todavía no ha encontrado una solución.
fuente
Todos los ejemplos que dio parecen tener un hilo conductor. Parece que quiere corregir un error que no comprende completamente. Digo eso porque notas la posibilidad de consecuencias no deseadas en cada uno.
Diría que probablemente sea un gran error y, como escribe Ben Laurie , no arregles un error que no entiendes . En este famoso ejemplo, el equipo de Debian rompió el cifrado de OpenSSL para Debian y derivados como Ubuntu cuando siguieron los resultados de una herramienta de análisis.
Si cree que hay un defecto mirando el código, asegúrese de poder reproducir el defecto de una manera que el cliente pueda ver. Si no puede, ¿por qué no gasta sus recursos arreglando algo más?
fuente
Comience a reducir su deuda técnica tan pronto como pueda .
Sus ejemplos definitivamente parecen código heredado , tienen mucha deuda técnica y siento que existe el miedo al cambio (por cierto, esto no es una crítica o un juicio). Todo tu equipo tiene que reconocer que tienes esta deuda técnica (para que no te culpen solo) y luego puedes decidir cómo vas a lidiar con ella.
En el ejemplo 1, si
Save()
no accede a ningún dato de instancia, ¿qué datos del cliente guarda exactamente? Comienza a arreglar y probar eso.En el ejemplo 2, es fácil cubrir la calculadora de velocidad con pruebas y asegurarse de que calcule el resultado correcto en todos los ejemplos clave.
En el ejemplo 3, existe el peligro de devolver el código muerto. ¿Debería ese código ser eliminado por completo? ¿Cuál es la intención de la condición booleana bajo eso si? ¿Es para asegurar que la cadena no contenga caracteres no válidos? ¿O para asegurarse de que tiene "PO BOX"? Cuanto antes comience a abordar estas preguntas, mejor.
Después de que haya solucionado varios de estos problemas, tenga una especie de retrospectiva / post-mortem con su equipo. Es importante aprender de la experiencia para que pueda reducir la tasa de inyección de defectos en el futuro.
fuente
Ya tienes buenas respuestas. Solo agregaré algo sobre el tema de tener miedo de que algo se cuelgue.
Primero, en la situación ideal, el software es modular, está diseñado correctamente y hay una buena separación de preocupaciones. En este caso, es muy poco probable que los cambios que realice rompan algo, ya que tendrá el control de todo el código relacionado y no habrá sorpresas ocultas.
Lamentablemente, la situación ideal es ficticia. Independientemente de la medida en que el acoplamiento esté flojo, habrá acoplamiento y, por lo tanto, la posibilidad de romper algo más.
La solución a esto es doble:
Hacer que el código esté bien estructurado no se realiza reescribiendo todo el código en un nuevo diseño arquitectónico. Más bien, la refactorización guiada por pruebas es tu amigo aquí. En este paso, no cambia la funcionalidad.
El segundo paso es que arregles el error.
Algunos puntos son relevantes:
Estos ya son más que unos pocos puntos, así que supongo que me detendré aquí.
fuente
Primero debe considerar la definición de un error:
Parece que te estás centrando en el n. ° 1, donde el n. ° 2 es el mejor lugar para sentarte. Claro, los programadores queremos que nuestro código sea correcto (# 1), pero la gente nos paga para que funcione (# 2).
Lo que puede o no hacer a la base de código que podría introducir nuevos errores accidentalmente es irrelevante para la visión del software actual # 2. Sin embargo, # 1 es importante para usted o para el programador de mantenimiento que sigue. A veces es difícil decidir, pero cuando el # 2 y el # 1 entran en conflicto, debes saber que el # 2 es claramente más importante.
fuente
Ninguno. Hay una tercera forma: encontrar una manera de demostrar que "el código problemático" en realidad está causando problemas desde el punto de vista comercial. Confirme lo que encuentre con BA / QA o al menos con su gerente. Luego planifique la solución cuando todos estén al tanto del problema.
Hay más escenarios posibles además de un error válido en los casos que mencionó:
En cualquier caso anterior, si soy gerente, no quiero que los desarrolladores usen su criterio y corrijan el "error" en su lugar. Arreglar el error en su lugar puede ayudar la mayor parte del tiempo, pero cuando sale mal, puede causar más problemas que su buena intención.
fuente
Corrige el error, inicia las pruebas unitarias y, cuando tienen éxito, verifica su corrección.
(O, si las pruebas de su unidad tardan mucho tiempo, primero verifica su corrección y luego espera si su herramienta de CI le envía un correo porque su confirmación ha roto algo).
fuente
Solucionarlos si son errores de bloqueo / pérdida de datos. Enviar un programa con un error conocido de pérdida de datos es francamente malicioso e inexcusable.
Si el error es cosmético o no crítico (puede evitarse), entonces debe documentarse y proporcionarse una solución alternativa. Idealmente, debería repararse, pero a veces es demasiado costoso arreglarlo para la versión actual.
Observe cómo cada proyecto de software más grande tiene una sección de 'Problemas conocidos' en el archivo Léame que generalmente enumera exactamente eso: errores conocidos.
Conocer errores y NO comunicarlos es en mi humilde opinión solo aceptable para errores realmente menores / cosméticos.
fuente
Arreglalo y haz que lo pruebe. Si decide mantener los errores conocidos solo porque tiene miedo de encontrar más errores, su programa se convierte en un campo minado de bombas de tiempo tan rápidas que será irreparable antes de lo que cree.
Como usted es el maestro y el código es el subordinado, es posible que no tenga miedo de cambiarlo cuando vea que está mal. El miedo al código ("podría tomar represalias al romper en otro lugar") es simplemente inaceptable.
fuente
Si claramente hay un accidente, o algo mal , entonces debes solucionarlo. Si hay una ambigüedad en la especificación, es decir, si te encuentras pensando "bien, el cliente podría esperar esto, pero luego parece que podría ser un error" o un problema en la especificación, como "nos han pedido que hagamos esto pero apesta ", entonces necesitas saber qué hacer. Lanzar el código sobre la pared y esperar los comentarios de los clientes es malo: puede preguntarle al gerente de un producto si tiene uno, o preguntarle al cliente antes de implementar el producto.
Recuerde, "sabemos sobre ese problema y lo solucionaremos en una versión futura" es sinónimo de "sabemos sobre ese problema pero no nos preocupamos lo suficiente como para evitar que lo resuelva".
fuente
El curso de acción correcto es no ignorar el error ni "arreglarlo" en el acto; por las mismas razones que identificó en su pregunta.
Creo que primero deberías intentar entender el código. Si el código que está viendo tiene cierta antigüedad y nadie notó el "error" todavía, es probable que haya una razón para ello. Intenta encontrar esta razón. Esto es lo que me gustaría ver antes de tomar una decisión:
Historial : use su software de control de versiones para responder las preguntas: ¿Quién tocó el código? ¿Qué cambiaron? ¿Y con qué mensajes de confirmación lo registraron? ¿Puedes inferir una razón por la cual el código se ve así?
Uso : ¿Qué código usa el código defectuoso? ¿Y cómo? ¿El código está muerto? ¿Hay otro código que se base en el comportamiento defectuoso?
Autor : si no puede llegar a una conclusión rápidamente utilizando la información anterior, pregúntele al autor del código (al menos si eso es posible) por qué el código se ve de la manera en que lo hace. Por lo general, obtendrás un "¡Oups, eso debería arreglarse!" o un "¡No! ¡No lo cambies! ¡Se necesita de esa manera!" inmediatamente.
fuente