Soy un gran creyente en el código limpio y la artesanía del código, aunque actualmente estoy en un trabajo donde esto no se considera una prioridad. A veces me encuentro en una situación en la que el código de un compañero está plagado de un diseño desordenado y muy poca preocupación por el mantenimiento futuro, aunque es funcional y contiene poco o ningún error.
¿Cómo sugieres mejoras en una revisión de código cuando crees que hay tanto que hay que cambiar y se acerca una fecha límite? Tenga en cuenta que sugerir que las mejoras se realicen después de la fecha límite puede significar que se les quitará la prioridad por completo a medida que entren nuevas funciones y arreglen errores.
Respuestas:
Comprueba tu motivación. Si cree que el código debería cambiarse, debería ser capaz de articular alguna razón por la que cree que debería cambiarse. Y esa razón debería ser más concreta que "lo hubiera hecho de manera diferente" o "es feo". Si no puede señalar algún beneficio que provenga de su cambio propuesto, entonces no tiene mucho sentido gastar tiempo (también conocido como dinero) para cambiarlo.
Cada línea de código en el proyecto es una línea que debe mantenerse. El código debe ser tan largo como sea necesario para hacer el trabajo y ser fácil de entender, y no más. Si puede acortar el código sin sacrificar la claridad, está bien. Si puede hacerlo mientras aumenta la claridad, eso es mucho mejor.
El código es como el hormigón: es más difícil cambiarlo después de haber estado sentado un tiempo. Sugiera sus cambios lo antes posible si puede, de modo que el costo y el riesgo de los cambios se minimicen.
Cada cambio cuesta dinero. Reescribir el código que funciona y es poco probable que deba modificarse podría ser un esfuerzo inútil. Concentre su atención en las secciones que están más sujetas a cambios o que son más importantes para el proyecto.
La forma sigue a la función, y a veces viceversa. Si el código es desordenado, existe una mayor probabilidad de que también contenga errores. Busque esos errores y critique la funcionalidad defectuosa en lugar del atractivo estético del código. Sugiera mejoras que hagan que el código funcione mejor y que la operación del código sea más fácil de verificar.
Diferenciar entre diseño e implementación. Una clase importante con una interfaz deficiente puede propagarse a través de un proyecto como el cáncer. No solo disminuirá la calidad del resto del proyecto, sino que también aumentará la dificultad de reparar el daño. Por otro lado, una clase con una interfaz bien diseñada pero una implementación pésima no debería ser un gran problema. Siempre puede volver a implementar la clase para un mejor rendimiento o confiabilidad. O, si funciona correctamente y es lo suficientemente rápido, puede dejarlo solo y sentirse seguro sabiendo que su ruft está bien encapsulado.
Para resumir todos los puntos anteriores: Asegúrese de que los cambios propuestos agreguen valor.
fuente
Hay un punto óptimo para agregar valor a través de la refactorización. Los cambios deben lograr tres cosas:
Consideraciones:
fuente
Si el código funciona sin errores graves y es inminente una fecha límite importante (como en los efectos P&L o PR corporativo), es demasiado tarde para sugerir mejoras que requieran cambios importantes. Incluso las mejoras en el código pueden crear riesgos para la implementación del proyecto. El tiempo para las mejoras fue más temprano en el proyecto, cuando había más tiempo para invertir en la solidez futura de la base del código.
fuente
La revisión del código tiene 3 propósitos:
Comprobación de errores
Comprobando para ver dónde se puede mejorar el código
Herramienta de enseñanza para quien escribió el código.
La evaluación de la calidad del diseño / código es, por supuesto, sobre los puntos 2 y 3.
En cuanto al # 2:
Deje MUY claro cuáles son los beneficios de los cambios propuestos frente a los costos para arreglar. Como cualquier decisión comercial, esto debería ser sobre análisis de costo / beneficio.
Por ejemplo, "el enfoque X del diseño reduciría significativamente la probabilidad de que ocurra el error Y al hacer el cambio Z, y sabemos que este código sufre cambios de tipo Z cada 2 semanas. El costo de manejar la interrupción de producción del error Y + al encontrar el error + arreglar y liberar el arreglo + el costo de oportunidad de no entregar el siguiente conjunto de hazañas es
$A
; mientras que el costo de limpiar el código ahora y el costo de oportunidad (por ejemplo, el precio del envío tardío o con menos funciones) es$B
. Ahora, evalúe, o más bien tener su jefe de equipo / gerente - evaluar$A
vs$B
y decidir.Esto ayudará al equipo inteligente a gestionarlo de manera efectiva. Por ejemplo, tomarán una decisión racional utilizando información COMPLETA
Esto (especialmente si lo dice bien) elevará SU estado; por ejemplo, es alguien lo suficientemente inteligente como para ver los beneficios de un mejor diseño, Y lo suficientemente inteligente como para no exigirlo religiosamente sin sopesar las consideraciones comerciales.
Y, en el caso probable de que ocurra el error Z, obtendrá mucha más influencia en el próximo conjunto de sugerencias.
En cuanto al # 3:
fuente
Elige tus batallas, si se acerca una fecha límite, no hagas nada. La próxima vez que alguien más esté revisando o manteniendo el código y sigan teniendo problemas con él, entonces acérquese a ellos con la idea de que, como equipo, debería centrarse más en la calidad del código al revisar el código para que no tenga tantos problemas más adelante.
Deberían ver el valor antes de hacer el trabajo extra.
fuente
Siempre comienzo mi comentario con "I would", lo que indica que el mío es simplemente uno de los muchos puntos de vista.
También siempre incluyo una razón.
" Me gustaría extraer este bloque en un método debido a la legibilidad."
Yo comento sobre todo; grande y pequeño. A veces hago más de cien comentarios sobre un cambio, en cuyo caso también recomiendo la programación de pares y me ofrezco como wingman.
Estoy tratando de establecer un lenguaje común por razones; legibilidad, SECO, SRP, etc.
También he creado una presentación sobre Clean Code y Refactoring explicando por qué y mostrando cómo, que sostuve a mis colegas. Lo he sostenido tres veces hasta ahora, y una consultoría que estamos usando me pidió que lo retuviera nuevamente para ellos.
Pero algunas personas no escucharán de todos modos. Entonces me quedo con rango de atracción. Soy el líder del diseño. La calidad del código es mi responsabilidad. Este cambio no se realizará en mi reloj en su estado actual.
Tenga en cuenta que estoy más que dispuesto a dar marcha atrás en cualquier comentario que haga; por razones técnicas, fechas límite, prototipos, etc. Todavía tengo mucho que aprender sobre codificación y siempre escucharé la razón.
Ah, y recientemente me ofrecí a comprar almuerzo para el primero en mi equipo que presentó un cambio no trivial sobre el que no tenía ningún comentario. (Oye, tienes que divertirte también. :-)
fuente
Este código está hecho. En cierto punto, los rediseños se vuelven demasiado costosos para justificar. Si el código ya funciona con pocos o ningún error, será una venta imposible. Sugiera algunas maneras de limpiar esto en el futuro y seguir adelante. Si / cuando el código se rompe en el futuro, vuelva a evaluar el valor de un rediseño. Puede que nunca se rompa, lo que sería genial. De cualquier manera, está en el punto en el que tiene sentido apostar que no se romperá, ya que el costo será el mismo ahora o más tarde: prolongado, terrible rediseño.
Lo que debe hacer en el futuro es tener iteraciones de desarrollo más estrictas. Si hubiera podido revisar este código antes de haber invertido todo el trabajo de eliminar errores, habría tenido sentido sugerir un rediseño. Hacia el final, nunca tiene sentido hacer una refactorización importante a menos que el código esté escrito de una manera fundamentalmente imposible de mantener y usted sepa con certeza que el código deberá cambiarse poco después del lanzamiento.
Dada la elección entre las dos opciones (refactor o no refactor), piense qué suena como la venta más inteligente:
o
Si dijera cualquiera de las dos, su jefe probablemente diría:
La conclusión es que a veces un poco de deuda técnica tiene sentido, si no pudo corregir ciertas fallas cuando era barato (iteraciones iniciales). Tener un diseño de código de calidad tiene rendimientos decrecientes a medida que se acerca a una función completada y a la fecha límite.
fuente
[Esta respuesta es un poco más amplia que la pregunta planteada originalmente, ya que esta es la redirección para muchas otras preguntas sobre revisiones de código.]
Aquí hay algunos principios que encuentro útiles:
Criticar en privado, alabar en público. Deje que alguien sepa sobre un error en su código uno a uno. Si hicieron algo brillante o asumieron una tarea que nadie quería, felicítelos en una reunión de grupo o en un correo electrónico enviado al equipo.
Comparte tus propios errores. Comparto la historia de mi desastrosa primera revisión de código (recibida) con estudiantes y colegas junior. También les hice saber a los estudiantes que pillé su error tan rápido porque lo hice antes que yo. En una revisión de código, esto podría aparecer como: "Creo que aquí se equivocaron las variables de índice. Siempre verifico eso debido al tiempo en que mis índices se equivocaron y derribé un centro de datos". [Sí, esta es una historia real.]
Recuerda hacer comentarios positivos. Un breve "bien!" o "buen truco" puede hacer el día de un programador junior o inseguro.
Suponga que la otra persona es inteligente pero a veces descuidada. No diga: "¿Cómo espera que la persona que llama obtenga el valor de retorno si realmente no lo devuelve?" Diga: "Parece que olvidó la declaración de devolución". Recuerda que escribiste un código horrible en tus primeros días. Como alguien dijo una vez: "Si no te avergüenzas de tu código de hace un año, no estás aprendiendo".
Guarde el sarcasmo / ridículo para amigos que no están en su lugar de trabajo. Si el código es épico horrible, bromea sobre eso en otro lado. (Me parece conveniente casarme con un compañero programador). Por ejemplo, no compartiría las siguientes caricaturas (o esta ) con mis colegas.
fuente
Cuando una cucharada de azúcar ayuda a que la medicina baje, y lo que está mal se puede expresar de manera sucinta, no hay 20 cosas mal, dirijo con una forma que sugiere que no tengo ningún interés, ningún ego invertido en lo que quiero ser escuchado. Por lo general, es algo como:
o
Si las razones son bastante obvias, no las menciono. Esto le da a otras personas la oportunidad de asumir cierta propiedad intelectual de la sugerencia, como en:
"Sí, es una buena idea, porque < tu razón obvia aquí >".
Si la mejora es bastante obvia, pero no tanto como para hacerme parecer un idiota por no pensar en ello, y la razón para hacerlo refleja un valor compartido con el oyente, entonces en algún momento ni siquiera lo sugiero:
Me pregunto si hay una manera de ... <declaración de valor compartido aquí>
Esto es solo para tratar con personas realmente delicadas: con la mayoría de mis compañeros, ¡solo les dejo tenerlo!
fuente
Las revisiones de código no siempre tienen como objetivo hacer mejoras.
Una revisión cerca del final de un proyecto, como parece ser el caso aquí, es solo para que todos sepan dónde comenzar a buscar cuando entran errores (o para un proyecto mejor diseñado, lo que puede estar disponible para su posterior reutilización). Cualquiera sea el resultado de la revisión, simplemente no hay tiempo para cambiar nada.
Para realizar cambios, realmente es necesario debatir el código y el diseño mucho antes en el proyecto: el código es mucho más fácil de cambiar cuando solo existe cuando se habla de posibles enfoques.
fuente
Su pregunta es "¿Cómo codificar la revisión de código mal diseñado?":
La respuesta IMO es simple. Hable sobre el DISEÑO del código y cómo el diseño es defectuoso o no cumple con los requisitos. Si señala un diseño defectuoso o "no cumple con los requisitos", entonces el desarrollador se verá obligado a cambiar su código porque no hace lo que debe hacer.
Si el código es "funcionalmente suficiente" y / o "cumple con las especificaciones" y / o "cumple con los requisitos":
Si eres un compañero de este desarrollador, no tienes ningún poder directo que te permita "decirle" que haga cambios.
Hay un par de opciones que te quedan:
Me parece que no hay bala de plata. Tienes que usar los tres y debes ser creativo en el uso de los tres.
fuente
En el caso de un diseño paralizante, su enfoque debe ser maximizar la encapsulación . De esa manera, se hace más fácil reemplazar las clases / archivos / subrutinas individuales con clases mejor diseñadas.
Concéntrese en garantizar que las interfaces públicas de los componentes estén bien diseñadas y que el funcionamiento interno se oculte cuidadosamente. Además, los contenedores de almacenamiento de datos son esenciales. (Las grandes cantidades de datos almacenados pueden ser muy difíciles de cambiar, por lo que si obtiene un "sangrado de implementación" en otras áreas del sistema, está en problemas).
Una vez que haya levantado las barreras entre los componentes, concéntrese en los componentes con mayor probabilidad de causar problemas importantes.
Repita hasta la fecha límite o hasta que el sistema sea "perfecto".
fuente
En lugar de una crítica directa directa del código de alguien, siempre es mejor ser constructivo en nuestros comentarios durante la revisión del código.
Una forma que sigo es
Dichos comentarios se tomarán en serio a pesar de que se acerca su fecha límite. Y probablemente se implementará en el próximo ciclo de desarrollo.
fuente
La revisión del código debe integrarse con el ciclo de cultura y desarrollo para funcionar. No es probable que la programación de una revisión de código grande al final del desarrollo de la función X funcione. En primer lugar, hacer los cambios será más difícil y es probable que alguien se sienta avergonzado, creando resistencia a la actividad.
Debe tener confirmaciones tempranas y frecuentes, junto con revisiones a nivel de confirmación. Con las herramientas de análisis de código, la mayoría de las revisiones serán rápidas. Las herramientas automatizadas de análisis / revisión de código, como FindBugs y PMD, lo ayudarán a obtener una gran clase de errores de diseño. Sin embargo, no lo ayudarán a resolver problemas de nivel arquitectónico, por lo que debe tener un diseño sólido en su lugar y juzgar el sistema general en contra de ese diseño.
fuente
Aumentar la calidad de las revisiones de código.
Además de la calidad del código que se está revisando, existe una cualidad de la revisión del código en sí:
Es mucho más fácil aceptar una revisión de código de buena calidad que algunos arreglos de ego en su mayoría cuestionables.
fuente
Hay dos cuestiones notables en la pregunta, la parte con tacto y la fecha límite próxima . Estos son asuntos distintos: el primero es una cuestión de comunicación y dinámica de equipo, el segundo es una cuestión de planificación y priorización.
Con mucho tacto . Supongo que desea evitar los egos cepillados y el retroceso negativo contra las críticas. Algunas sugerencias:
La segunda parte es la priorización . Tiene muchas sugerencias para mejoras, pero como se acerca la fecha límite, solo hay tiempo para aplicar algunas.
Bueno, ¡primero debes evitar que esto suceda en primer lugar! Para ello, realiza revisiones continuas e incrementales. No permita que un desarrollador trabaje durante semanas en una función y luego revísela en el último momento. En segundo lugar, las revisiones de código y el tiempo para implementar sugerencias de revisión deberían ser parte de la planificación y las estimaciones regulares para cualquier tarea. Si no hay suficiente tiempo para revisar adecuadamente, algo ha salido mal en la planificación.
Pero supongamos que algo ha salido mal en el proceso, y ahora se enfrenta a una serie de comentarios de revisión y no tiene tiempo para implementarlos todos. Tienes que priorizar. Luego, vaya a los cambios que serán más difíciles y riesgosos de cambiar más adelante si lo pospone.
El nombramiento de identificadores en el código fuente es increíblemente importante para la legibilidad y la mantenibilidad, pero también es bastante fácil y de bajo riesgo cambiar en el futuro. Lo mismo con el formato de código. Así que no te concentres en esas cosas. Por otro lado, la cordura de las interfaces expuestas públicamente debería ser la máxima prioridad, ya que son realmente difíciles de cambiar en el futuro. Los datos persistentes son difíciles de cambiar: si primero comienza a almacenar datos inconsistentes o incompletos en una base de datos, es realmente difícil de solucionar en el futuro.
Las áreas que están cubiertas por pruebas unitarias son de bajo riesgo. Siempre puedes arreglarlos más tarde. Las áreas que no lo son, pero que podrían someterse a pruebas unitarias, son de menor riesgo que las áreas que no pueden someterse a pruebas unitarias.
Supongamos que tiene una gran porción de código sin pruebas unitarias y todo tipo de problemas de calidad de código, incluida una dependencia codificada de un servicio externo. Al inyectar esta dependencia, haces que el fragmento de código sea comprobable. Esto significa que en el futuro puede agregar pruebas y luego trabajar en solucionar el resto de los problemas. Con la dependencia codificada, ni siquiera puede agregar pruebas. Así que primero ve por esta solución.
¡Pero, en primer lugar, intenta evitar terminar en este escenario!
fuente