¿Está interesado en una excelente lista de verificación de revisión de código para poder dejar de producir errores?
Has venido al lugar correcto.
Una buena lista de verificación de revisión de código le permitirá crear un excelente producto sin errores que genere mucho dinero. En esta publicación de blog, dirigida a CTO y profesionales de desarrollo de software, analizamos lo que puede hacer para reducir la cantidad de errores en sus productos de software.
He sido desarrollador, tanto por contrato como permanente, tanto tiempo que desearía poder pronunciar una frase mágica y terminar con los errores de desarrollo para siempre. No es tan fácil, por desgracia; tampoco es ciencia espacial.
Si me hubieras preguntado acerca de cómo reducir los errores cuando comencé a programar, habría levantado los brazos en el aire exasperado por la tarea imposible que me acabas de pedir que logre.
Pasando unos años (bueno, tal vez casi unas pocas décadas), tenemos una integración de control de fuente real incorporada que no es segura para la fuente visual (probablemente el peor sistema de control de fuentes de la historia); pruebas automatizadas de unidad, integración e interfaz de usuario; análisis de código; la lista continua.
Hay muchas herramientas de revisión de código automatizadas gratuitas, de código abierto y con licencia comercial. La elección es suya. Sin embargo, una palabra para los sabios, puede gastar una fortuna absoluta en las últimas herramientas, pero si sus prácticas y procesos no se sostienen, ¡todo lo que logrará serán dolores de cabeza!
Entonces, ¿cómo se asegura de que sus prácticas y procesos resistan el escrutinio? Revisas el código. Una lista de verificación de revisión de código es imprescindible para cualquier proyecto si desea que tenga éxito.
Creación de una lista de verificación de revisión de código
Cuando ejecuto una revisión de código, trato de asegurarme de que todos sean tratados por igual; para hacerlo, construí una lista de verificación para recordarme a mí y a los equipos con los que trabajo, lo que debe verificarse (a continuación se muestra una muestra aproximada y lista)
Alcance
Imagine que el código que estamos revisando es una hoja de papel, y un posible error/problema o mala interpretación es un grano de arena. ¿Sería más fácil encontrar ese grano de arena en un papel del tamaño de una postal o en un papel del tamaño de una casa?
Cuando esté realizando una revisión, debe preguntarse “¿Este cambio tiene un solo propósito?” si puede responder que sí, continúe con la revisión.
De lo contrario, eso lleva a una pregunta más importante: «¿Se ha diseñado correctamente la solución?» o peor «¿La solución ha malinterpretado los requisitos?»
Como revisor, debe ser objetivo sobre el código que está revisando; si tiene dificultades para realizar un seguimiento de dónde se encuentra, entonces no puede dedicar toda su atención a la revisión.
¿Porque es esto importante? A todos nos gusta pensar que somos inteligentes y capaces de realizar múltiples tareas; después de todo, programamos computadoras para ganarnos la vida. Los estudios han demostrado las personas son intrínsecamente malas en la multitarea.
Cada vez que cambias a una nueva tarea, disminuyes tu productividad, tanto la carga cognitiva de aprender la nueva tarea, como la incapacidad de abandonar por completo la tarea anterior, ocupan tus pensamientos.
Mantener su envío y revisión enfocados en un solo propósito ayuda a mantener el enfoque en la tarea en cuestión: verificar que el código haga lo que debe hacer.
Escala
¿Recuerdas ese pedazo de papel con el grano de arena del que acabo de hablar? ¿Qué pasaría si en lugar de una hoja de papel la ampliáramos de modo que tuvieras que revisar 50 piezas para encontrar ese grano de arena? Encontrar ese grano de arena (el insecto) sería mucho más difícil.
La escala es otro aspecto importante tanto de la presentación como de la revisión. Asegúrese de que solo se incluyan los objetos requeridos en la revisión; es posible que tenga que lidiar con 500 clases debido a un importante ejercicio de refactorización o un rediseño drástico, pero a menudo esto se puede dividir en partes más razonables.
Como revisor, es su deber asegurarse de que la colección específica de objetos que se le pide que revise estén juntos. ¡La carga cognitiva que discutí en la sección anterior empeora a medida que aumenta la complejidad!
Criterios de diseño
Un factor clave de la revisión, que va de la mano con el Alcance y la Escala de las secciones anteriores, es la Arquitectura. ¿La solución está bien diseñada? ¿Hace uso de los diversos principios que su idioma preferido tiene como clave para su implementación? En mi experiencia estos son:
Separación de preocupaciones: cada módulo o clase debe ser responsable de una sola parte de la funcionalidad de la aplicación.
Esto NO significa que necesite una clase para cada función. La intención es asegurarse de que no tenga objetos «dioses», es decir, una sola clase que hace absolutamente todo y, por lo tanto, es muy probable que sea bastante sensible al cambio.
Pregúntese «¿los objetos auxiliares están estrechamente acoplados?», «¿Las clases manipulan instancias de otra clase?» si la respuesta es sí, puede haber un problema aquí.
¡Mantenlo simple, estúpido! (KISS) – Mantenga la solución, sus módulos/clases y funciones simples. El código demasiado complejo es más difícil de depurar y más difícil de garantizar que toda la lógica de bifurcación se pueda probar lo suficiente.
No se repita (SECO): si se encuentra leyendo esencialmente el mismo código una y otra vez, piense si el código podría reestructurarse para que los métodos puedan REUTILIZARSE. La reutilización de código reduce la complejidad (normalmente) y ayuda en la capacidad de prueba.
Arquitectura: si la solución es una solución MVC, ¿se adhiere a esos principios? ¿Hay alguna desviación? Si los hay, ¿por qué? La respuesta aquí no es que un desarrollador deba apegarse obstinadamente a una arquitectura dada, sino que cualquier desviación es pensada y razonada.
Sintaxis y Estructura
La mayoría de las organizaciones tienen algún tipo de estándar de codificación; si esto es informal o formal puede depender de toda una gama de factores. Sin embargo, normalmente, el estándar de codificación ha evolucionado a lo largo del tiempo en función de las modas y los gustos cambiantes de los desarrolladores involucrados en la creación y el mantenimiento del código.
¿Por qué es importante un estándar de codificación? Permite que todos los desarrolladores involucrados en el proceso trabajen con un conjunto estándar de reglas. Si todos trabajamos en igualdad de condiciones, podemos asegurarnos de que el proceso de revisión del código para encontrar errores y garantizar la calidad del código sea más simple.
Entonces, ¿cómo es una guía estándar de codificación? Echemos un vistazo a lo que Microsoft cree que debería entrar en uno.
En su forma más simple, debería haber algunas reglas sobre cómo se deben nombrar las cosas y cómo se deben escribir las estructuras de código.
foreach (Cliente CUST en Clientes)
HacerAlgo(CLIENTE);
hacer algo más();
En el fragmento de código anterior hay algunas cosas que pueden no cumplir con los estándares normales y aceptados:
- Variables locales: normalmente en minúsculas o el caso de Carmel
- Variables tipificadas explícitamente: use tipificación implícita, esto hace que su código sea más flexible. En este caso, imagine que cambiamos la colección Cliente de Lista a Lista para que pueda usarse contra individuos u organizaciones. Ahora necesita refactorizar todo su código, usar var en su lugar significaría que solo necesita refactorizar el código que se rompe (consulte Pruebas unitarias).
- Bucles con un inicio y un final definidos: los bucles siempre deben encerrar su cuerpo en un inicio y un final (llaves en el caso de C# o JavaScript). Esto garantiza que todos sepan qué está incluido en el bucle y qué no. En el ejemplo anterior, una mirada superficial lo lleva a creer que se deben ejecutar dos declaraciones en el ciclo; una inspección más cercana solo DoSomething (CUST) está dentro del ciclo.
- Nomenclatura consistente: puede ver mayúsculas y minúsculas mixtas para los métodos que se llaman. muestra Siempre que los métodos en las clases y objetos relevantes se nombren de la misma manera, su código se compilará pero agregará desorden visual.
La legibilidad del código anterior sería mucho mejor si se representara así
foreach(var cliente en Clientes)
{
HacerAlgo(cliente);
}
Hacer algo más();
Ahora es mucho más claro lo que está en el bucle y lo que está fuera del bucle. Visualmente, el código está más equilibrado e incluye sugerencias sobre qué es un método y qué es una variable o propiedad.
Su inspección debe incluir verificar que el código revisado cumpla con los estándares que estableció en su organización, pero no se preocupe, no será un experto en formato de código glorificado, ¡existen herramientas que pueden ayudar!
he usado poliestilo desde hace muchos años, tanto en entornos de IC como en aquellos que no lo tienen. Viene en varias formas, puede integrarse en Visual Studio si así lo desea; También puedes integrarlo con Reafilado y tu Construcciones automatizadas si quieres.
Advertencias y errores del compilador
Genial, ahora tenemos un código limpio y ordenado, que está dividido en fragmentos simples y fáciles de entender. ¿Ahora que? ¿El código incluso compila?
Si hay algún error en la compilación, entonces algo anda mal; el código obviamente está roto. Todos somos diferentes; todos tenemos nuestras propias idiosincrasias y preferencias de herramientas, ubicaciones de archivos y estructuras.
Por lo tanto, es lógico que lo que puede compilarse en mi máquina no pueda compilarse en la computadora de otro desarrollador. ¿Por qué sin embargo? ¿Es una referencia perdida?
¿Un problema ambiental o una dependencia que no existe? ¿Qué sucedería si un cliente intentara ejecutar el código compilado en mi entorno de desarrollo en su propio dispositivo?
Esta es la razón por la cual un entorno de construcción limpio y automatizado es clave. Ayuda a eliminar los factores ambientales; asegurándose de que todas las compilaciones tengan todos los componentes que necesitan incluidos en ellas.
Si el código no se compila, a menos que esté revisando específicamente el motivo del error de compilación; falle la revisión allí y luego, continúe con la revisión del resto del código, ya que no tiene sentido darse por vencido y dejar otros posibles problemas al acecho.
Ok, ¿entonces nos deshicimos de los errores de compilación? ¿Qué pasa con las advertencias? Las advertencias están ahí por una razón, indican dónde se puede codificar un error en su aplicación en el futuro.
Arréglalo o ignóralo: esa decisión depende de ti y de tus estándares de codificación; si lo ignoras, al menos asegúrate de que esté documentado en alguna parte por qué lo estás ignorando y elimina las advertencias.
Personalmente, creo que suprimir las advertencias es una mala idea, pero recomendaría la supresión de las advertencias basada en el código, ya que de esa manera está controlada por la versión y no depende de su entorno de desarrollo específico.
Microsoft tiene documentación detallada en la supresión de advertencias en el código (otros IDE tienen su propia forma de hacer las cosas); esencialmente, debe prefijar el método o la clase que contiene la infracción con un atributo como este
[System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Usage”, “CA1801:ReviewUnusedParameters”, MessageId = “args”)]
¡Buena suerte y recuerda no esconder demasiadas advertencias debajo de la alfombra!
Pruebas unitarias
Pruebas: ¿quién las necesita, verdad? “Soy un desarrollador, tengo experiencia en escribir código, las pruebas toman demasiado tiempo y tengo mucho más con lo que continuar”.
He estado allí; Leer el libro; y tengo la camiseta varias veces ahora. Supongamos que todos somos codificadores perfectos y que nuestro código no contiene ningún error. ¿Realmente hace lo que se pretendía? ¿Cómo probamos eso?
Las pruebas unitarias le dirían que lo que codificó y cómo se comporta coincide con lo que el diseño dice que debe hacer su código. Debería probar el comportamiento esperado y los casos extremos.
Si ha escrito una rutina de validación de edad, debe probar los límites superior e inferior, los valores medios y los valores que nunca deberían permitirse. Esto garantizará que su código cumpla con los requisitos y sea lo suficientemente robusto como para usarse en producción.
Si puede automatizar esas pruebas aún mejor, puede probar más escenarios en menos tiempo de esa manera y asegurarse de que cada vez que realice un cambio no haya roto su propio código nuevo o el código existente que fue escrito por un equipo. miembro.
No todo el código necesita una unidad de prueba; solo necesita probar las caras públicas de su código: clases públicas, métodos y propiedades. Normalmente, no necesita preocuparse por los métodos privados, ya que no debería existir ningún código a menos que esté en uso (lo discutiremos más adelante).
Su revisión debe incluir la verificación para ver que la prueba unitaria sea lo suficientemente rigurosa; no tenga miedo de señalar dónde una prueba unitaria puede ser débil o podría extenderse agregando más escenarios.
Cobertura de código
Como revisor de código, debe asegurarse de que haya suficientes pruebas escritas para garantizar que la funcionalidad del código se pruebe en los casos de uso habituales; a menos que sea un algoritmo muy simple, no hay forma de que pueda probar todas las eventualidades posibles. Entonces, al revisar el código, establezca una barra lo suficientemente alta para la aceptación. Una cobertura de código del 100 % no significa que se prueben todas las rutas/ramas/estados posibles. Simplemente significa que cada método o clase pública se prueba al menos una vez.
Si bien nada le impide lograr una cobertura del 100 %, es más importante asegurarse de que las pruebas unitarias sean lo suficientemente rigurosas para aprobar más que solo el escenario ideal. Es por eso que clasifico la cobertura del código de verificación por debajo de las pruebas unitarias en sí mismas.
Cobertura de código de medición
Visual Studio tiene herramientas integradas de cobertura de código: pero solo si usa la Enterprise Edition;
Personalmente, prefiero DotCover de JetBrains como parte del paquete Resharper Ultimate. Con DotCover, obtiene una visualización en línea de lo que cubre una prueba de unidad y lo que no, así como una indicación temprana de cuándo se rompe una prueba.
Si su presupuesto no se extiende a VS Enterprise o Resharper, existen herramientas gratuitas si está dispuesto a realizar un poco de trabajo adicional que le dará algo como esto como resultado:
AbrirCubierta es una herramienta de código abierto, pero deberá instalarla y Generador de informes para sacarle el máximo partido
Paquete de instalación OpenCover -Versión 4.6.519.
Install-Package ReportGenerator -Versión 3.0.1.
Puede averiguar cómo utilizar Abrir portada aquí y Generador de informes aquí – su uso está un poco más allá del alcance de este blog, pero si está interesado, siempre puede sugerirlo como tema para el futuro.
Herramientas
He resaltado varias herramientas que uso a diario en mi línea de trabajo; si no ha oído hablar de ellas o desea leer más sobre ellas, le proporcioné enlaces a continuación para que las use.
Reseñas del código TFS: https://docs.microsoft.com/en-us/vsts/tfvc/get-code-reviewed-vs
Marcos de pruebas unitarias
Pruebas unitarias de Microsoft Visual Studio: https://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.aspx
Pruebas unitarias de JavaScript usando QUnit: https://qunitjs.com/
Reafilador: https://www.jetbrains.com/resharper/
policía de estilo: https://github.com/StyleCop/StyleCop
Propiedad del código y despersonalización
Finalmente, un pequeño aparte tanto para el Revisor como para el Revisado. Una revisión de código no debe ser un ataque personal a uno u otro; no debe causar ira o animosidad entre los miembros del equipo.
Es una herramienta, como muchas otras que usamos en nuestra vida laboral, para ayudar a elevar el estándar de producción de una buena solución a una solución brillante.
Dicho esto, tampoco hay nada de malo en señalar o apreciar buenas soluciones de código: me enorgullezco de mis soluciones, especialmente cuando siento que son elegantes o simplifican un problema complejo. Creo que la mayoría de los desarrolladores lo hacen.
El beneficio adicional de una revisión de código es que presenta una oportunidad formal para compartir conocimientos: no puedo decirle cuántas veces en el pasado me entregaron una lista de errores y me dijeron que los arreglara sin haber visto nunca el código o los requisitos antes.
En última instancia, su trabajo será más fácil al tener revisiones de código formalizadas.
Reflexiones finales sobre el uso de una lista de verificación de revisión de código
El proceso que he discutido; el uso de herramientas, técnicas y medidas ayuda a crear una imagen más completa de lo que se requiere en una lista de verificación de revisión de código. Ahora que tenemos una mejor comprensión, es un proceso realmente simple poner todo junto en una lista de verificación para ayudarlo a guiarlo a través de la próxima revisión que realice.
Esto no está diseñado para ser una lista completa, sino más bien un punto de partida para que usted la personalice de modo que se adapte a su equipo, proyectos y organización.
He resaltado algunas de las cosas que creo que son clave para una revisión de código exitosa. No es la única forma de llevar a cabo una revisión de código, puede haber algunas cosas que desee agregar o eliminar de su propia lista de verificación de revisión de código.
Lo importante es revisar el código: revise su propio código y revise otros. El hecho de que lo esté revisando mejorará la base del código, así como también difundirá el conocimiento en el equipo. Háganos saber si ha implementado estos o si cree que me he perdido algo.
Preguntas frecuentes sobre la lista de verificación de revisión de código
Una lista de verificación de revisión de código es una lista de pasos que deben seguirse para garantizar que una pieza de código sea adecuada para su propósito. Implica una revisión completa línea por línea de todo el código escrito.
El marco de tiempo para una revisión de código realmente depende de la complejidad del producto. Cuanto más código, más tiempo lleva una revisión de código. Las revisiones de código para aplicaciones basadas en blockchain tardan aún más, ya que una vez que el código se envía a blockchain, no se puede cambiar.
Un gran comienzo sería leer este artículo para tener una idea completa de lo que es una revisión de código y lo que implica una lista de verificación típica de revisión de código. A continuación, puede adaptar estos pasos a sus propios requisitos.