¿Corregir errores o esperar a que el cliente los encuentre?

35

¿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 Saveno 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 somethingrama? 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 Customerpara ser inválido y lleno de basura.

Tal vez el Customerobjeto, 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?
Ian Boyd
fuente
33
Si no está dispuesto a cambiar nada porque podría romper algo, y considera que no está calificado para ver lo que podría suceder en otras partes del código, ¿qué está haciendo aquí? ¿Estás paralizado por el teclado porque la línea de código que estás a punto de escribir puede estar equivocada?
David Thornley
3
sin duda una pregunta bien investigada
Muhammad Alkarouri
2
"Hacer algo" es a menudo una llamada a otras funciones que escribió o funciones de bibliotecas, en cualquier caso, el código debería haber sido probado por la unidad. El procedimiento en sí también se prueba en la unidad, lo que deja la posibilidad de que se introduzcan nuevos errores cuando arreglas uno muy bajo ... Si construyo un puente, lo probaría primero en una escala más pequeña en lugar de dejar morir a las personas que caminan sobre el puente . Si no está haciendo pruebas unitarias cuando le preocupan los errores, lo está haciendo mal. En cualquier caso, si lo arreglas, te echan la culpa, por lo que, en lugar de arreglarlo, podrías evitarlo y no ser culpado en absoluto.
Tamara Wijsman
2
¡"espere hasta que la gente muera antes de arreglarlo"! Santa vaca, en serio espero que solo haya una respuesta para esto ...
Chris Knight
3
Como comentario específico sobre una cosa que dijiste: no sabes si en algún otro lugar del código, se basan en el comportamiento esotérico: ¿entonces? Si alguien está abusando de una regla de alcance claramente incorrecta como un hack en su código, entonces su código es INCORRECTO. Una buena OOP habría evitado ese error, pero no solucionarlo porque usaron una mala práctica está agravando el problema, dejándolo abierto a nuevos abusos y haciendo que el sistema sea más inestable en todos los sentidos. Solucione el error, espero que las pruebas detecten cualquier problema, solucione más errores si no lo hace. La estabilidad a largo plazo del producto es una métrica vital.
CodexArcanum

Respuestas:

34

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í:

  1. Registre el defecto en el sistema de seguimiento de su elección. Discuta con la gerencia / compañeros de trabajo si es necesario.
  2. Si se trata de un defecto con consecuencias potencialmente graves (por ejemplo, su ejemplo # 2), corra, grite, salte hacia arriba y hacia abajo hasta que alguien con autoridad lo note y determine un curso de acción apropiado que mitigue los riesgos asociados con la corrección de errores. Esto puede retrasar su fecha de lanzamiento, salvar vidas, lavar sus ventanas, etc.
  3. Si es un defecto que no se rompe o existe una solución alternativa, evalúe si el riesgo de solucionarlo supera el beneficio de la solución. En algunas situaciones, será mejor esperar a que el cliente lo mencione, ya que sabe que no está pasando tiempo arreglando / volviendo a probar cosas cuando no es 100% requerido.

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.

Adam Lear
fuente
Muy cierto. Es por eso que (algunas) compañías tienen gerentes técnicos, rastreadores de errores, etc.: para priorizar las cosas. No digo que no tome la iniciativa, para nada, pero debe usar su buen juicio. Tomar la iniciativa equivocada en el momento equivocado se llama "ser un cañón suelto" y puede matar a una empresa. Además, la importancia de un error en particular varía de una compañía a otra. Para algunos programas, un error tipográfico en un cuadro de diálogo es un error cosmético de baja prioridad que se solucionará en una versión futura, y en otros es una emergencia de parada.
Bob Murphy
66
+1 para registrar el defecto. Otros defectos pueden tener prioridad ...
Shug
35

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.

ysolik
fuente
2
Esa es una triste verdad. Tuvimos que entregar un proyecto que probamos como loco, y aún así el cliente logró bloquearlo en 3 minutos.
Oliver Weiler
44
Método @Helper: Tal vez si lo hubieras probado como personas sensatas hubiera sido mejor.
Vinko Vrsalovic 28/10/10
Método @Helper: Aunque, más en serio, si realmente fueron tres minutos, parece que los evaluadores no sabían cuáles eran los casos de uso reales que esperaba el cliente.
Vinko Vrsalovic
8
Método @Helper: involucra al cliente en las pruebas (suponiendo cliente == cliente). Los desarrolladores que escriben y prueban el código es un problema, los desarrolladores no usan el software de la misma manera. Los desarrolladores son gentiles. Es su trabajo, su arte: los clientes lo golpean como un mono en un panio. Cuando sea posible, comparta el esfuerzo de prueba, comparta la responsabilidad. Esto no encaja en todos los entornos, pero al trabajar con los clientes como un equipo, no los asesores pueden lograr un mejor software.
Brian Chandley
Er, peor? (relleno)
Hello71
24

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í.

Jay Beavers
fuente
44
+1. Arreglalo. Si la solución rompe algo más, entonces esa otra cosa se rompió de todos modos, arréglalo también. Si su prueba no detecta estos descansos, entonces su prueba está rota, arregle eso también. No puede dejarse asustar de cambiar el código por temor a romper algo; ese camino solo conduce a la ruina total.
Tom Anderson
21

¿Qué diría el cliente?

Así es como me imagino que esto se desarrolla:

Cliente: Se bloquea cuando hago x.

Programador: ¡Oh sí! Recuerdo que lo vi hace un tiempo. Pensé que aún no era un gran problema, así que lo dejé allí.

Cliente: [alcanza un objeto contundente]

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
8

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?

Conrad Frix
fuente
7

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.

azheglov
fuente
5

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:

  1. Haga el código lo mejor estructurado posible.
  2. Cuando el código esté lo suficientemente aislado como para saber que nada más se romperá, arréglalo.

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:

  1. El control de versiones es absolutamente necesario para este proceso.
  2. El paso de refactorización y el paso de corrección de errores están mejor comprometidos con el control de versiones como confirmaciones separadas, por lo que cada uno tiene una funcionalidad histórica bien definida.
  3. No te obsesiones con la posibilidad de cometer otro error, no harás nada. Más bien, piense en mejorar su código. En otras palabras, a menos que sepa que está aumentando los errores en lugar de disminuirlos, debe hacerlo.
  4. Relacionado con el último punto: no intentes predecir el futuro. Los humanos están predispuestos a pensar que son muy buenos para predecir. En realidad, nuestros poderes de predicción son a corto plazo. Así que no te preocupes por un vago futuro indefinido. Este es también el principio detrás de YAGNI .
  5. La herramienta correspondiente para el control de versiones en el mundo de los errores es el rastreador de errores . Necesitarás eso también.
  6. Debe corregir los errores por dos razones: para satisfacer al cliente; y para poder progresar en su desarrollo. Para usar el ejemplo 3 (el de física): si el programa satisface al cliente con una ecuación tan rota, entonces hay muchas otras partes del software que están mal desarrolladas para mitigar este error (por ejemplo, la implementación del airbag). Si se requiere una versión 2 (o 1.1) para este software, le resultará cada vez más difícil desarrollar un código correcto basado en este defectuoso. Entonces te diriges a la gran reescritura o al gran fracaso. Los cuales debes evitar.

Estos ya son más que unos pocos puntos, así que supongo que me detendré aquí.

Muhammad Alkarouri
fuente
3

Primero debe considerar la definición de un error:

  1. El código como leído no coincide con lo que percibes que es correcto
  2. El software no realiza correctamente sus tareas.

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.

John Fisher
fuente
2

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ó:

  1. El código que está viendo es un código muerto. Posiblemente porque, como dijo ysolik: los clientes siempre encuentran errores. Si no lo hicieron, tal vez el código nunca se ejecute.
  2. Hubo una situación de WTF donde el error obvio tuvo su propósito. (Estamos hablando del código de producción, cualquier cosa podría haber sucedido, ¿verdad?)
  3. Las empresas / clientes ya sabían sobre el problema pero no sienten la necesidad de solucionarlo.
  4. Quizás más...

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.

Codismo
fuente
1
Si solo desea contratar desarrolladores que no usen su propio criterio, hay muchos realmente mediocres para usted. Tendrá problemas para contratar a los buenos, que tienen cierta confianza en su capacidad.
David Thornley
1
@David: no extiendas mi opinión en un grado inapropiado. Los desarrolladores definitivamente necesitan su juicio, pero debe haber un límite. En este caso, los desarrolladores utilizan su criterio para detectar un error potencial y toman más medidas para solucionarlo.
Codismo
2

¿Yo:

  • arreglar el código y ser culpado por romperlo? o
  • dejar el error y ser culpado cuando el cliente lo encuentra?

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).

sbi
fuente
1
O si usa un check-in cerrado, configúrelo, de modo que realmente no registre el código roto.
Adam Lear
3
Tomar mucho tiempo no es excusa para cometer un código de mala calidad.
Toby
@Toby: ¿Quién estaba hablando de excusas? Actualmente estoy trabajando en un equipo pequeño, ni siquiera media docena de desarrolladores. Las pruebas unitarias para el proyecto toman 1 hora. Nuestra política es ejecutar las pruebas que parecen estar relacionadas con lo que sea que haga, y luego registrarse y dejar que CI descubra si rompió algo que aparentemente no está relacionado. Esto no funcionaría en un equipo grande, pero en uno pequeño ahorra mucho tiempo.
sbi
1

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.

Michael Stum
fuente
1

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.

usuario281377
fuente
0

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
0

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.

cmaster
fuente