10 principios del código autodocumentado

Hola Hoy quiero compartir consejos sobre cómo escribir un código perfecto y comprensible, tomado del libro de Peter Goodlif, "The Craft of a Programmer // The Practice of Writing Good Code".

Por supuesto, sería bueno leer este libro entretenido para todos los que escriben el código, pero para aquellos que son especialmente perezosos, pero que quieren dejar de atormentar menos y engañar a sus colegas ( tienen conciencia ), les presento 10 principios de código autodocumentado en cat :

1. Escribir código simple con buen formato


El formato de presentación tiene un gran impacto en la facilidad de comprensión del código. Una representación razonable transmite la estructura del código: las funciones, los bucles y las declaraciones condicionales se vuelven más claras.

int fibonacci(int position) { if (position < 2) { return 1; } int previousButOne = 1; int previous = 1; int answer = 2; for (int n = 2; n < position; ++n) { previousButOne = previous; previous = answer; answer = previous + previousButOne; } return answer; } 

  • Asegúrese de que la ejecución normal de su código sea obvia. El manejo de errores no debe restar valor a la secuencia de ejecución normal. Las construcciones condicionales if-then-else deben tener un orden de ramificación uniforme (por ejemplo, coloque siempre la ramificación de código "regular" antes de la ramificación de "manejo de errores", o viceversa).
  • Evite muchos niveles de declaraciones anidadas. De lo contrario, el código se vuelve complicado y requiere una amplia explicación. En general, se acepta que cada función debe tener solo un punto de salida; Esto se conoce como código de entrada única, salida única (SESE, una entrada, una salida) . Pero, por lo general, esta restricción dificulta la lectura del código y aumenta el número de niveles de anidamiento. Prefiero la opción de función de Fibonacci anterior que la siguiente opción de estilo SESE :

     int fibonacci(int position) { int answer = 1; if (position >= 2) { int previousButOne = 1; int previous = 1; for (int n = 2; n < position; ++n) { previousButOne = previous; previous = answer; answer = previous + previousButOne; } } return answer; } 

    Rechazaría tal anidamiento excesivo a favor de la declaración de devolución adicional: se ha vuelto mucho más difícil leer la función. La conveniencia de ocultar el retorno en algún lugar profundo de la función es muy dudosa, pero los cálculos abreviados simples al principio hacen que la lectura sea muy fácil.
  • Tenga cuidado con las optimizaciones de código que causan claridad en el algoritmo subyacente. Optimice su código solo cuando quede claro que interfiere con el rendimiento aceptable del programa. Al optimizar, haga comentarios claros sobre el funcionamiento de esta sección del código.

2. Elija nombres significativos


Los nombres de todas las variables, tipos, archivos y funciones deben ser significativos y no engañosos. El nombre debe describir correctamente lo que es. Si no puede encontrar un nombre significativo, entonces hay una duda sobre si comprende el funcionamiento de su código.

El sistema de nombres debe ser consistente y no causar sorpresas desagradables. Asegúrese de que la variable siempre se use solo para el propósito que sugiere su nombre.

Una buena elección de nombres es probablemente la mejor manera de evitar comentarios innecesarios. Los nombres son la mejor manera de acercar el código a la expresividad de los lenguajes naturales.

3. Divida el código en funciones independientes.


Cómo divide el código en funciones y qué nombres les da puede hacer que el código sea comprensible o completamente incomprensible.

  • Una función, una acción.

Minimice los efectos secundarios inesperados, sin importar cuán útiles puedan parecer. Requerirán documentación adicional.
Escribe funciones cortas. Son más fáciles de entender. Puede navegar en un algoritmo complejo si está dividido en pequeños fragmentos con nombres significativos, pero esto no se puede hacer en la masa de código sin forma.

4. Elija nombres de tipo significativos


En la medida de lo posible, describa las limitaciones o el comportamiento utilizando las funciones de idioma disponibles. Por ejemplo:

  • Al determinar un valor que no cambiará, asígnele un tipo constante (use const en C).
  • Si la variable no debe tomar valores negativos, use un tipo sin signo (si existe en el idioma).
  • Use enumeraciones para describir el conjunto de datos asociado.
  • Elija el tipo de variables correctamente. En C / C ++, escriba el tamaño en variables de tipo size_t , y los resultados de operaciones aritméticas con punteros a variables de tipo ptrdiff_t .

5. Use constantes con nombre


Código como si (contador == 76) es desconcertante. ¿Cuál es el significado mágico de 76? ¿Cuál es el significado de este cheque? La práctica de los números mágicos es viciosa. Oscurecen el significado del código. Es mucho mejor escribir así:

 const size_t bananas_per_cake = 76; ... if (count == bananas_per_cake) { //    } 

Si el código constante 76 a menudo se encuentra en el código (disculpe, bananas_per_cake ), se logra una ventaja adicional: cuando es necesario cambiar el contenido de los plátanos en el pastel, es suficiente modificar el código en un lugar, en lugar de realizar una búsqueda / cambio global del número 76, que está lleno de errores.

Esto se aplica no solo a los números, sino también a las cadenas constantes. Eche un vistazo a los literales en su código, especialmente si ocurren repetidamente. ¿No sería mejor usar constantes con nombre en su lugar?

6. Destacar piezas importantes de código


Intente resaltar código importante en el contexto de material ordinario. En el lugar correcto, debe llamar la atención del lector. Hay una serie de trucos para esto. Por ejemplo:

  • Coloque anuncios en el aula sabiamente. Primero, la información sobre los objetos abiertos debe ir, porque es el usuario de la clase quien la necesita. Los detalles de implementación cerrados deben colocarse al final, ya que son menos interesantes para la mayoría de los lectores.
  • Si es posible, oculte toda la información no esencial. No deje basura innecesaria en el espacio de nombres global. C ++ tiene el idioma pimpl, que le permite ocultar los detalles de la implementación de la clase. (Meyers 97)
  • No escondas código importante. No escriba más de una declaración en una línea y simplifique esta declaración. El lenguaje le permite escribir operadores muy creativos del bucle for, en el que toda la lógica cabe en una línea con la ayuda de muchas comas, pero estos operadores son difíciles de leer. Evítalos.
  • Limite la profundidad de anidamiento de las declaraciones condicionales. De lo contrario, es difícil notar el manejo de casos realmente importantes detrás de un montón de ifs y paréntesis.

7. Combina datos relacionados


Toda la información relacionada debe estar en un solo lugar. De lo contrario, hará que el lector no solo salte los aros, sino que también los busque con ESP. La API para cada componente debe estar representada por un solo archivo. Si hay demasiada información interconectada para ser presentada en un lugar, vale la pena revisar la arquitectura del código.

Si es posible, combine objetos usando construcciones de lenguaje. En C ++ y C #, puede combinar elementos dentro del mismo espacio de nombres . En Java, el mecanismo de agrupación es el motor del paquete. Las constantes relacionadas se pueden definir en una enumeración.

8. Archivos de etiquetas


Coloque un bloque de comentarios al comienzo del archivo con una descripción del contenido del archivo y del proyecto con el que se relaciona. Esto no requiere mucho trabajo, pero es de gran beneficio. Cualquiera que tenga que acompañar este archivo tendrá una buena idea de lo que está tratando. Este título puede tener un significado especial: la mayoría de las compañías de software, por razones legales, requieren que cada archivo fuente tenga una declaración de derechos de autor. Por lo general, los encabezados de archivo se ven así:

 /********************************************************* * File: Foo.java * Purpose: Foo class implementation * Notice: (c) 1066 Foo industries. All rights reserved. ********************************************************/ 

9. Manejar los errores correctamente


Ponga el manejo de todos los errores en el contexto más adecuado. Si hay un problema de lectura / escritura en el disco, debe procesarse en el código que trata el acceso al disco. Para manejar este error, es posible que deba generar otro error (como una excepción "No puedo cargar el archivo") y pasarlo a un nivel superior. Esto significa que en cada nivel del programa, el error debe ser una descripción precisa del problema en su contexto . No tiene sentido manejar el error asociado con una falla de disco en el código de la interfaz de usuario.

El código autodocumentado ayuda al lector a comprender dónde se produjo el error, qué significa y cuáles son sus consecuencias para el programa en este momento.

10. Escribe comentarios significativos


Por lo tanto, tratamos de evitar escribir comentarios utilizando otros métodos indirectos de documentación de código. Pero después de haber hecho todo lo posible para escribir un código comprensible, todo lo demás debe recibir comentarios. Para que el código sea fácil de entender, debe complementarse con una cantidad adecuada de comentarios. Cual?

Prueba otros trucos primero. Por ejemplo, verifique si puede hacer que el código sea más claro cambiando el nombre o creando una función auxiliar, y así evitar comentarios.



Estoy seguro de que después de la introducción de varios de estos principios en el hábito, hará que un programador sea más feliz. Y serás este feliz programador. Cuando En el momento de volver a trabajar en su código hace seis meses.

Source: https://habr.com/ru/post/458264/


All Articles