¿Cómo debo comunicar fallas graves de programación a alguien para que no lo tome como algo personal?

Soy un desarrollador con solo un par de años de experiencia, trabajo en una pequeña empresa de ocho desarrolladores, en un proyecto Java. Nuestro líder de equipo, también uno de los gerentes, es mayor y muy productivo, y dice que tiene unos quince años de experiencia en Java.

El mes pasado, mientras discutíamos algunos módulos de código fuente que escribió, noté en el código fuente que una de las clases anulaba el método equals(), pero no el método hashCode(); me refiero a los dos métodos declarados en la clase muy básica de Java Object. Cuando le señalé esto al líder del equipo, de una manera muy tranquila y cortés, negó que una clase deba anular ambos métodos. El tema terminaría ahí, pero me pareció inmoral dejar que tal falla (error) dañara el producto más tarde.

Unos días después, me acerqué a él en persona y en privado y tranquilamente, sin faltarle el respeto, le expliqué el problema y usé referencias externas (como el libro de Joshua Bloch 'Effective Java'). Bueno, dijo que lo miraría, y finalmente lo hizo. Sin embargo, desde entonces, me da la espalda.

Peor aún, recientemente vi un problema grave en el código fuente. Algunas clases que ha escrito implementan la Serializableinterfaz, pero el campo serialVersionUIDno es un número fijo (constante). En cambio, varía. Quiero decir, obtenemos un número diferente cada vez que ejecutamos la aplicación.

Nuevamente con la motivación de entregar un producto sensato, me gustaría comunicar esto adecuadamente. Pero no sé cómo hacerlo correctamente, sin que él lo tome como algo personal. Verá, mis enfoques anteriores fallaron. ¿Cómo podría hacerlo?

Cualquier consejo sería bienvenido.

Editar: El propósito de esta pregunta es encontrar formas efectivas, productivas, educadas, respetuosas y colaborativas para comunicar mejoras sobre problemas graves de código, y no cuestionar la autoridad o las decisiones de gestión, hechas por compañeros o incluso superiores.

¿Qué problemas reales, en lugar de teóricos, están causando estos problemas en su código?
Si este tipo basa su información en un solo libro, entonces eso es malo. Haga la pregunta con respecto al código Java en SO. Al menos allí obtienes una garantía de los expertos en java para lo que está bien y lo que está mal.
@Philip Los problemas descritos son aquellos que a menudo no resultan en errores reales, pero si resultan en errores, generalmente son difíciles de solucionar. Incluso si ese no fuera el caso aquí, la pregunta se aplica igualmente bien a cuestiones de estilo y limpieza del código; si se han identificado errores reales o no, no es relevante.
¿Durante cuánto tiempo su colega le ha dado la espalda? Parece que pudiste convencerlo, por lo que es posible que no hayas tenido tanto éxito como crees; es posible que su orgullo tarde un poco en recuperarse.
@PhilipKendall Estoy más interesado en comunicar de manera efectiva algunas inquietudes sin causarle ningún daño a él (o al equipo y al producto). Sin embargo, el plan futuro es que algunos de los objetos se comuniquen a través de JMS a través de diferentes computadoras/JVM.
@Rob Gracias por su aporte: esta situación ha durado dos meses. Nuevamente, tal vez debería esperar un poco, como sugieres.
"Noté en el código fuente que una de las clases anuló el método equals, pero no el método hashCode". -- si desea comunicar de manera efectiva a un programador por qué algo como esto es malo, busque instancias de errores reales en el código que se puedan rastrear directamente hasta esta mala práctica. Entonces definitivamente puede decir "si adoptamos la práctica X, no ocurrirán errores de este tipo".
No tiene que sobrescribir la función hash, siempre que los objetos que se comparan tengan el mismo código hash. Si la clase A compara nombres y hashes de nombres, y la subclase B compara nombres y nombres de pila, el antiguo método de hash funcionará bien. Tampoco tiene que sobrescribir la función hash si nunca se usa.
@Brandin Entonces, estoy pensando en crear un caso de prueba, o incluso un mini programa, para probar este problema. Esto sería increíble, si se me permite tomar el tiempo en el reloj y eso (pero está bien, siempre podría hacerlo durante las horas extra, si es necesario). Sin embargo, realmente no quiero que estos problemas aparezcan después de la entrega y que los clientes los descubran. Gracias.
@pek Lo mejor sería encontrar un error demostrable real, archivarlo en el rastreador de errores, corregirlo y luego señalarlo. Oye, arreglé el error #1234. Si nos aseguramos de hacer siempre X, errores como este no volverán a ocurrir. Recomiendo que lo hagamos parte del estándar de codificación a partir de ahora. El resto depende realmente del líder del equipo.
@gnasher729 Gracias por responder. La herencia no está involucrada en nuestro caso. Cada una de nuestras clases solo heredaría de la clase Objeto (como siempre). Sin embargo, tenemos un conjunto de instancias de estas clases.
@Brandin [Para: Lo mejor sería... ] Cierto, cierto. Tienes toda la razón en que un error demostrable real es una mejor prueba. Muchas gracias
¿Usas TDD? Si puede crear un caso de prueba que falla, tiene el único error que necesita, y mueve el debate de su código a su caso de prueba. Suena más como que estás interesado en la minuciosidad, y los programadores muy productivos a menudo (no siempre) carecen de esa minuciosidad. Un proceso TDD, o al menos casos de prueba, aprovechará el proceso para reemplazar (potencialmente) malos hábitos.
@gnat Creo que no lo es y, sinceramente, gracias por señalar el otro tema: ayuda a evitar malentendidos. Acabo de hacer una edición, también. Muchas gracias
@ jimm101 Gracias por traer TDD al tema. Desafortunadamente, no lo hacemos. Pero creo que su comentario complementa muy bien los comentarios de Brandin anteriores. Gracias
@pek: Interesante, porque un conjunto no debería funcionar tan pronto como tenga dos punteros de objeto diferentes donde los objetos se comparan iguales.
¿Hay algo que hayas notado durante los últimos 2 años que te dé alguna idea o áreas de preocupación? ¿Alguna vez has visto a alguien contradecir a esta persona? ¿Te sientes cómodo preguntando?
Tener un serialVersionID diferente para cada ejecución está bien, siempre y cuando los objetos serializados solo se reutilicen dentro de esa ejecución. Si ese es el caso, puede ser mejor si las versiones cambian con cada ejecución.
hashCode solo es útil para fines de rendimiento cuando se usa hashSet/HashMap y este tipo de objetos, si el código hash es el mismo, se ejecutan iguales (). Para serialNumber: no lo pongo, solo agrego Serializable para permitir la serialización en JSON y JSON no usa esa variable, es solo para la serialización de Java sin formato, que bloquea la comunicación para que sea solo entre la aplicación Java. Si el senior está haciendo algo malo, no debería ser que no haya utilizado hashCode/serialNumberId al explicarle por qué no los necesita.

Respuestas (12)

Recordatorio general: siempre es mejor evitar un tono crítico o sermoneador. Conviértalo en una simple observación ("parece que se olvidó de implementar el código hash aquí") o conviértalo en una pregunta ("¿hay alguna razón por la que no implementó el código hash?"). Deje que su impulso de respuesta impulse la discusión de por qué es importante, si es necesario, pero comience asumiendo que conocen los principios y que la rareza fue un simple descuido/error tipográfico o tenía alguna razón racional detrás de ella que puede ser discutida en lugar de golpeado

La gente escucha mejor si los tratas con respeto.

Y recuerda, a veces el malentendido será tuyo. Te avergonzarás mucho menos de esta manera que si haces una declaración más absoluta o didáctica.

¡El enfoque de la pregunta es muy bueno!
@keshlam Cierto, tiene razón en los tres temas que cubrió en su respuesta detallada. Especialmente, el primer párrafo, la idea de seguir un "enfoque basado en preguntas", abre una perspectiva totalmente nueva sobre el tema y los métodos de comunicación en general. Muchas gracias de verdad
Preguntas como "¿hay alguna razón por la que no implementaste hashcode?" funcionan muy bien cuando se trata de holgazanes intencionales; pero tienden a ser contraproducentes cuando se trata de personas que se sienten sobrecargadas (ya sea porque luchan o porque tienen demasiado en su plato). Los pondrá a la defensiva y es probable que cause fricciones. La pregunta inherentemente señala su error y les pide que lo justifiquen. Está redactado amablemente pero la respuesta requerida no es simple e implica culpabilidad atribuida.

Tal vez mirar esto desde la otra perspectiva podría darle una mejor vista.

Soy líder de equipo y también gerente en una pequeña empresa de ocho desarrolladores. Tengo 15 años de experiencia programando en Java. Tengo una nueva persona en mi equipo que es mucho más joven que yo y solo tiene un par de años de experiencia.

El mes pasado, mientras discutíamos sobre algunos módulos de código fuente que escribí, comenzó a menospreciar mi código. A pesar de que tiene mucha menos experiencia que yo, afirmó haber visto errores en el código que funcionaba completamente bien. Después de una breve discusión, parecía que podía explicárselo.

Pero desafortunadamente él simplemente no puede dejar de lado ese asunto. Sigue socavando mi autoridad al exigir que hagamos todo según los libros de texto (como el libro 'Effective Java' de Joshua Bloch), incluso en aquellos casos en los que sería una pérdida de tiempo y no daría como resultado un beneficio tangible para nuestro producto. ¿Cómo puedo hacer que este desarrollador junior confíe en mi experiencia?

Es difícil como junior convencer a un senior para que cambie sus prácticas. Además, como gerente tiene que mantener un aura de superioridad para poder liderar con eficacia.

Entonces, cuando desee mejorar los estándares de calidad en su lugar de trabajo sin la autoridad para hacerlo, dé el ejemplo. Haz bien lo que otros hacen mal y demuestra que tu manera es mejor porque da como resultado un mejor producto en menos tiempo. Cuando señale errores en el código de otras personas, no lo haga minuciosamente en los archivos de código fuente. Hágalo presentando un defecto reproducible en el producto mismo y una forma de solucionarlo siguiendo las mejores prácticas.

Por cierto, una de las enfermedades profesionales más comunes para los programadores es un ego inflado. Es posible que ya tenga uno, pero usted también está comenzando a mostrar síntomas de las primeras etapas.

Gracias por su respuesta, es genial en la forma en que intenta ponerme en su lugar. Acerca de la parte narrativa: Realmente espero que la primera discusión realmente no se percibiera como un argumento, y que las preocupaciones sobre la calidad no se percibieran realmente como "socavar la autoridad de uno". Si no, ha habido un gran malentendido. Por lo demás, creo que su enfoque de "mostrar con un buen ejemplo" y "mostrar con casos de prueba" es muy práctico, científico y eventualmente puede ayudar a construir un mejor producto y quizás relaciones... así que sí, me gusta. De verdad muchas gracias
Guau. Predícalo, hermano.
No soy un desarrollador de Java, pero parece muy posible que el desarrollador senior aquí presente pueda tener buenas razones para hacer las cosas de la forma en que se hicieron. Como (según mi propia experiencia) no hacer algo de la manera en que lo hizo en la escuela da un aumento de velocidad de orden de magnitud (o más) en una aplicación crítica en el tiempo ... Entonces, ¿por qué no comenzar simplemente preguntando por qué se hizo? ¿Por aquí? Es posible que puedas aprender algo.
@jamesqf Las mismas interfaces se usan en C# y aunque el código funcionará en la mayoría de los casos (dependiendo de la implementación), no anular Hashcode() hará que las estructuras de datos hash fallen (aunque todo lo demás debería funcionar) y lo mismo con serialVersionUID con causando algunos problemas no deseados difíciles de depurar. Es fácil pasar por alto la anulación de estos métodos si no comprende completamente el alcance; algo que pek espera que su desarrollador senior entienda.
"Además, como gerente tiene que mantener un aura de superioridad para poder liderar con eficacia" Nop. No necesita ser superior para liderar: necesita ser un buen comunicador que dé buenos ejemplos a seguir para los demás, demostrando compromiso, pasión, empatía, honestidad e integridad.
Este. Esta es una manera perfecta de plantear el problema. Este comentario me indicó que se trataba de un problema de perspectiva: "Me pareció inmoral dejar que una falla (error) dañara el producto más tarde". La palabra 'inmoral' implica que le estás dando demasiada importancia a este tipo de asuntos.
@JoeBradley ¿Demasiada importancia? No sabemos en qué tipo de software funciona OP, pero si es mi banco, prefiero que le dé "demasiada importancia" a esos temas que terminar con unos miles de dólares menos en la cuenta, porque alguna operación no No encontré ninguna reserva que me transfirió dinero y, por lo tanto, se lo saltó. Esas son cuestiones importantes, la construcción adecuada del software es tan importante como la construcción adecuada del puente (posiblemente, a veces más, a veces menos). Sin embargo, estoy de acuerdo en que verlo psicológicamente desde el otro lado podría ayudar a lograr el tono correcto en la conversación.
Dicho esto, sí, el problema de serialVersionUID suele tener menos impacto, pero siempre alentaría a un desarrollador junior o a cualquier desarrollador a discutir el código hasta que entiendan por qué es así, por eso también hay revisiones de código y por qué se consideran importante: hacer que todo el equipo participe y detectar problemas que, de lo contrario, podrían generar problemas más adelante.

Una forma de mitigar este tipo de problema es "dar y recibir". He tenido éxito con esta estrategia muchas veces. Las personas están más dispuestas a sus sugerencias y críticas cuando es de dos vías. Así que hacía preguntas y consejos cuando tenía la oportunidad y me tomaba en serio sus respuestas. (Para ser honesto, a veces ya sabía la respuesta, pero nunca se sabe, también aprendí algunas cosas interesantes de esa manera).

Eventualmente, construyen una relación en la que se apoyan mutuamente y las cosas van mucho mejor en muchos sentidos. Y si tiene 15 años de experiencia, apuesto a que podría contarte muchas cosas que vale la pena conocer.

No me preocuparía por él y su frialdad, eso es bastante normal después de lo que pasó. Lo más probable es que haya tenido en cuenta tu opinión y esté siendo cuidadoso contigo, y probablemente lo hayas molestado un poco. Pero no es un concurso de popularidad, así que, a menos que pierda el control, dale algo de espacio. Manténgase amigable y comprensivo y él aceptará.

¡Buen punto, buena estrategia! Esto puede conducir a un vínculo más fuerte (relación) de hecho. ¡Gracias!

Sea cortés y profesional. Envíe un ticket para el error, en su ticket, detalle el problema y una posible solución, y deje una oportunidad para que lo contactemos para obtener más información o una explicación del problema. Dejarlo así. Cuando se examinen sus tickets, se le asignará a usted mismo para corregir el error que encontró o al desarrollador original. Con suerte, el otro desarrollador comprenderá y solucionará el problema, o se comunicará con usted para obtener más información. Si no sucede nada, entonces es un problema de gestión ahora.

Este método no llama a ningún desarrollador específico por errores y permite tener en cuenta el tiempo de reparación y posiblemente incluso incluirlo en un scrum (si lo hace).

Encontrar errores en el código de otras personas es una práctica común. Cada vez que un nuevo desarrollador ingresa a un proyecto, encuentra problemas. Asignar culpas no es importante. Simplemente haga un ticket y deje que los procesos de la empresa lo manejen. Los desarrolladores experimentados no deben ofenderse si otros encuentran problemas en su código. Y si lo hacen, probablemente no deberían ser desarrolladores.

Si bien creo que Keshlam tiene un buen punto. También es importante recordar que el código es propiedad del equipo, no de un individuo, por lo que evitaría el uso de "usted" cuando pregunte sobre posibles problemas con el código. En su lugar, podría preguntar

"Hola, noté que no hemos implementado el código hash aquí, ¿hay alguna razón para eso?"

Está abordando el problema potencial con el código, pero también preguntando sobre una posible razón del problema y dando al líder del equipo la oportunidad de convertirlo en una experiencia de aprendizaje para usted.

En lugar de hacer de esto una discusión de "Creo que deberías", que ahora está claro que no te llevará a ninguna parte, entonces conviértela en una discusión técnica.

Después de revisar el código encontré un problema y escribí la prueba X que lo demuestra.

(Puede escribir varios si es necesario). Luego, depende del equipo discutir cómo solucionarlo correctamente para que su prueba tenga éxito.

¿Tienes reuniones matutinas? o algunas otras reuniones de equipo donde puede mencionarlo informalmente.

Planteándolos a todos de una manera completamente impersonal: "Oh, molestia, encontré que este problema que esta clase ha implementado es igual a código hash, que realmente puede causar problemas si la clase se usa alguna vez en un mapa hash, ya que solo la identidad del objeto se usa como clave" y luego discutiendo cuando se puede arreglar.

No ha acusado a nadie de escribir un código incorrecto, ahora todos saben por qué esto es un problema, el código se soluciona.

Algunos consejos generales, aunque a partir de esta información, creo que los puntos 4 y 5 podrían ser los más apropiados:

  1. Separe el código de su autor. Está aquí para evaluar lo primero, no lo segundo. 'Este código es [X]' es mejor que 'Tú creaste este código [X]'.
  2. Se específico. No proporcione descripciones vagas de todo el código base. 'Se agradecerían comentarios descriptivos en X, Y y Z con respecto a la redacción de esta función' es infinitamente más apreciado que 'Todo es griego para mí'.
  3. ¡Sé positivo también! el término para este proceso es 'revisión de código', no 'descomposición verbal de código' por una razón. En la mayoría de las revisiones publicadas, un revisor hablará sobre los aspectos buenos y malos de un producto. Deberías hacer lo mismo.
  4. Escoge tus batallas. No trates todo como un factor decisivo. Si es un poco extraño pero funciona perfectamente bien, déle una nota al pie de página como mucho y trátelo como un "problema menor" o "pregunta rápida". En términos generales, si tiene que abrir un depurador/descompilador para crear un escenario de rotura, no cuenta como nada grave.
  5. Asegúrate de que las cosas de las que hablas no sean solo 'en teoría'. Pruebe la aplicación usted mismo o hable con el equipo de pruebas sobre algo que crea que podría ser un problema.

Escriba un caso de prueba, describa el comportamiento que espera y muestre que el problema rompe la prueba.

(Oh chico, qué locuras descubrimos cuando empezamos a probar hashCode y equals sistemáticamente en nuestro proyecto...)

Escoge tus batallas

Como desarrolladores, puede ser difícil dejar pasar pequeños detalles. muy duro Y como desarrollador junior, a menudo aún no tiene la experiencia para distinguir entre problemas importantes y problemas menores. Parece que OP tiene razón en los dos ejemplos dados, PERO, ¿son problemas importantes? Para ser honesto, no lo parece a menos que esté causando que algo se rompa. No todos los olores a código son una colina para morir, especialmente...

Ande con cuidado con los diferenciales de superioridad

...cuando eres junior y ellos son senior. Por tres razones:

  1. A los jefes (suponiendo que el desarrollador senior tenga autoridad sobre OP) generalmente no les gusta que sus informes directos los corrijan. No digo que deba ser así, pero es la naturaleza humana.
  2. Los desarrolladores senior (incluido yo mismo) se dan cuenta de que tienen que trabajar más duro para seguir el ritmo de los desarrolladores más jóvenes en lo que respecta a sus conocimientos y habilidades tecnológicas. Pueden ser muy sensibles a cualquier cosa que les refuerce ese hecho, como que los desarrolladores junior los muestren (especialmente de manera accidentalmente condescendiente). Una vez más, no digo que deba ser así, pero las personas son personas.
  3. Los desarrolladores senior a menudo están acostumbrados a tratar con desarrolladores junior que tienen un chip en el hombro: que piensan que son brillantes y que los desarrolladores senior son tontos y farsantes, y que siempre están buscando oportunidades para dejar esto muy claro. Entonces, incluso si no es uno de estos desarrolladores junior, si parece estar haciendo lo que ellos hacen, es posible que obtenga la misma reacción que ellos: actitud defensiva y desagrado extremo. Nuevamente, esto no es lo ideal, pero póngase en el lugar del desarrollador senior.

O posiblemente el desarrollador senior podría ser simplemente un idiota. O ha tenido un mal día. O algo mas.

que hacer la proxima vez

  1. Recuerde que el desarrollador senior es senior, así que elija sus batallas y acepte que, como quien toma las decisiones, el desarrollador senior tiene derecho a cometer (¡y poseer!) errores.
  2. Enmarque sus desafíos como "Tengo una pregunta para poder entender", no "hiciste mal esta cosa obvia" para que el desarrollador senior pueda salvar las apariencias. Esto les permitirá (con suerte) ver su error y corregirlo mientras se preserva la relación. Si no ven y corrigen su error, consulte el n.º 1.

Súper buena pregunta. Me encanta aprender, pero cuando alguien me molesta, siento que debo renunciar. Recomiendo revisar el "estilo de codificación" de sus compañeros de trabajo e identificar sus fortalezas para que no sienta que todo el tiempo que pasó aprendiendo fue en vano. LUEGO identifique OPORTUNIDADES. De esa manera, muestra fortalezas en el futuro que están ayudando a la empresa y también trabajando en esas "oportunidades" que ya ha identificado. Dirijo equipos dando un cronograma de 30-60-90 días y luego elogio los ajustes en los que capitalizamos las "oportunidades". Funciona muy bien y es una forma justa de identificar líderes frente a personas que no son ni deberían ser líderes.

Bueno, gracias por contestar, pero no estoy seguro de haberte entendido. Solo por dejarlo claro de mi parte: no estoy cuestionando el liderazgo de uno. Tampoco desea asumir el papel de líder.
Alguien tiene que liderar. Hablo por experiencia personal. No quise confundirte.
Me compadezco del tonto que “agrede tu dulzura”.

Arréglalo tú mismo. Cree una rama, arréglela, pruébela y, si necesita aprobación, simplemente revise el código. Te cambia la carga, pero eres tú quien piensa que es importante, por lo que la carga realmente recae sobre ti, aunque sea el código de otra persona.

El único problema con este enfoque es que si el producto se rompe y se remonta a esta solución, entonces el OP pierde credibilidad ya que su solución podría ser una "mejor práctica" teórica y no una solución real.
@Dan, de acuerdo. Será mejor que se asegure de que tiene razón. Es por eso que incluí una prueba de desarrollo en los pasos. Si cree que debe hacerse, debe asumir la responsabilidad no solo de probarlo, sino también si su sugerencia rompe algo, ¿no? ¿Estás sugiriendo que pase la responsabilidad a otra persona por su sugerencia?
@Dan, en el último comentario, debería haber dicho: "De lo contrario, estaría pasando la responsabilidad a otra persona por su sugerencia". No me deja editar comentarios después de 5 minutos.
Esto sigue siendo bastante incómodo para el desarrollador senior, lo que se traduce en una relación incómoda entre el desarrollador senior y el desarrollador junior. Si ya tienen una buena relación de trabajo, esto podría estar bien. De lo contrario, podría ser gasolina en el fuego.