Normas de Estilo en la Programación de Sistemas Embebidos 2020 ============================================================== Versión modificada del Estilo de codificación del núcleo Linux La Traducción original de NuLies: David Marín Carreño La versión original : https://www.kernel.org/doc/html/v4.10/_sources/process/coding-style.txt Este es un pequeño documento que describe el estilo de codificación preferido para el núcleo Linux. El estilo de codificación es muy personal, pero esta forma de programar es la que hará posible que podamos comprender facilmente el código de todos. Antes de nada, le sugiero que imprima una copia de los estándares de codificación GNU y que NO la lea. Quémela, es un gran gesto simbólico. Bueno, allá voy: Capítulo 1: Sangrías Las tabulaciones tienen 8 caracteres, y por lo tanto las sangrías también tienen 8 caracteres. Hay movimientos heréticos que intentan hacer sangrías de 4 caracteres (¡o incluso de 2!), y eso es como intentar redefinir el valor de PI para que sea 3. Razón: La única idea que hay detrás de las sangrías es definir claramente dónde empieza y acaba un bloque de control. Después de haber estado mirando a la pantalla durante 20 horas seguidas, se dará cuenta de que es mucho más fácil ver cómo funciona una sangría si usted tiene sangrías grandes. Ahora, alguna gente diría que tener sangrías de 8 caracteres hace que el código se mueva demasiado a la derecha, lo que hace que sea difícil de leer en un terminal de 80 caracteres de ancho. La respuesta para ello es que si se necesitan más de tres niveles de sangría, algo va mal y se debería reestructurar el programa. Abreviando, las sangrías de 8 caracteres hacen las cosas más fáciles de leer y tienen el beneficio añadido de señalar cuándo se están anidando demasiado las cosas. Y es una advertencia a tener en cuenta. Capítulo 2: Colocando llaves El otro aspecto a señalar cuando se habla de estilo de codificación en C es la colocación de las llaves. Al contrario que con el tamaño de las sangrías, hay unas cuantas razones técnicas para escoger la estrategia de poner las llaves una encima de la otra, pero el modo preferible, tal y como nos mostraron los profetas Kernighan y Ritchie, es poner la llave de apertura al final de la línea y poner la llave de cierre al principio, como en este ejemplo: if (x es verdad) { haremos y } Sin embargo, hay un caso especial, la definición de funciones: estas tienen la llave de apertura al principio de la línea siguiente, como aquí: int función(int x) { cuerpo de la función } Los herejes de todo el mundo siguen diciendo que esta inconsistencia es... bien... inconsistente, pero todos los que tenemo la cabeza sobre los hombros sabemos que (a) K&R _tienen_razón_ y (b) K&R tienen razón. Además, las funciones son siempre especiales (no se pueden anidar en C). Dése cuenta de que la llave de cierre es el único carácter en su línea, _excepto_ en los casos donde está seguida por una continuación de la misma función, como un "while" en una función do, o un "else" en una función if. Por ejemplo: do { cuerpo del bucle do } while (condición); and if (x == y) { .. } else if (x > y) { ... } else { .... } Razón: K&R. Además, esta colocación de llaves también minimiza el número de líneas vacías (o casi vacías), sin ninguna pérdida de legibilidad. Esto es, como el suministro de nuevas líneas en la pantalla no es infinito (solemos tener terminales de 25 líneas), de esta manera tendremos más líneas vacías en las que poner comentarios. Chapter 3: Política de nombres C es un lenguaje espartano, y así debería ser su política de nombres. Al contrario que los programadores de Java, C++, Modula-2 o Pascal, los programadores en C no utilizan nombres con MayúsculasMezcladas, la razón es sencilla. Observe las diferencias entre estas dos formas: 1) EstaVariableJrEsUnContadorTemporal 2) esta_variable_jr_es_un_contador_temporal ¿Cuál forma le pareció mas sencilla de leer? 1) o 2) En C tampoco llamaría a la variable esta_variable_jr_es_un_contador_temporal, sino que mas bien en C llamaría a esa variable "tmp", lo que es mucho más fácil de escribir y mucho más fácil de entender. SIN EMBARGO, aunque los nombres con mayúsculas mezcladas son mirados con desdén, el uso de nombres descriptivos para variables globales es una necesidad. Llamar a una función global "cosa" puede ser tomado como un Las variables GLOBALES (que deben usarse sólo si _realmente_ se necesitan) deben tener nombres descriptivos, al igual que las funciones globales. Si se tiene una función que cuente el número de usuarios activos, debería llamarse "contar_usuarios_activos()" o algo parecido. NO debería llamarse "cntusr()". Incluir el tipo de una función en el nombre (la llamada notación húngara) es para gente con el cerebro dañado - el compilador sabe los tipos siempre y puede comprobarlos, y lo único que se consigue es confundir al programador. No hay que preguntarse por qué Micro$oft hace programas con multitud de errores. Los nombres de variables LOCALES deberían ser cortos y concretos. Si se tiene un entero contador de un bucle, debería ser llamado "i". Llamarlo "contador_bucle" es algo no productivo, ya que no hay ninguna posibilidad de que sea mal interpretado. De manera similar "tmp" puede ser sólo cualquier tipo de variable que se utilice para tener un valor temporal. Si tiene miedo de mezclar todas los nombres de variables locales, usted tiene otro problema, que se llama síndrome de desestabilización hormonal de funciones crecientes. Lea el próximo capítulo. Chapter 4: Funciones Las funciones deberían ser cortas y fáciles, y deben hacer sólo una cosa. Deberían ajustarse a una o dos pantallas de texto (la pantalla de texto ISO/ANSI es 80x24, como todos sabemos), y hacer una cosa y hacerla bien. La longitud máxima de una función es inversamente proporcional a la complejidad y grado de sangría de esa función. Por lo que si se tiene una función conceptualmente simple que es sólo una larga (pero simple) función case, en la que se tienen que hacer muchas cositas para muchos casos distintos, será correcto tener una función más larga. Sin embargo, si se tiene una función compleja, y se sospecha que un estudiante poco hábil de primer curso de universidad no podría ni sospechar de qué trata la función, debería adherirse a los límites recomendados de manera más palpable. Use funciones de ayuda con nombres descriptivos (siempre se puede pedir al compilador que las inserte si cree que se requiere gran velocidad, y probablemente lo hará mejor que lo que se había hecho). Otra medida para la función es el número de variables locales. No deberían pasar de las 5-10, o si no se estará haciendo algo mal. Piense de nuevo la función y divídala en pequeños trozos. Un cerebro humano puede, generalmente, mantener la pista de 7 cosas distintas, pero si se le dan más suele confundirse. Sabemos que usted es un genio, pero quizá le gustaría comprender lo que hizo hace 2 semanas. Capítulo 5: Comentarios Los comentarios son buenos, pero también existe el peligro de comentar por exceso. NUNCA intente explicar COMO funciona su código en un comentario: es mucho mejor escribir el código de manera que su funcionamiento sea obvio, y es una pérdida de tiempo explicar código mal escrito. Generalmente, se pide que los comentarios expliquen _qué_ hace el código, no _cómo_ lo hace. Intente evitar poner comentarios dentro del cuerpo de una función: si la función es tan compleja que necesita comentar separadamente partes de la misma, será mejor que vuelva al capítulo 4 un momento. Puede hacer pequeños comentarios para denotar o advertir sobre algo particularmente raro, pero trate de evitar el exceso. En su lugar, ponga los comentarios al principio de la función, explicando lo que hace, y si es posible, _por_qué_ lo hace. Capítulo 6: Se ha hecho un lío Está bien, todos lo hacemos. Probablemente su amigo con amplísima experiencia en Unix le ha comentado que "GNU emacs" formatea automáticamente los códigos fuente de C en lugar de hacerlo usted mismo, y se ha dado cuenta de que, en efecto, lo hace, pero los valores por defecto que utiliza no son los deseables (de hecho, son peores que una escritura aleatoria - un número infinito de monos escribiendo en GNU emacs nunca escribirían un buen programa). Por lo tanto, puede dejar de usar GNU emacs, o cambiarlo para que utilice valores más recomendables. Para hacer lo último, puede pegar lo siguiente en su fichero .emacs: (defun linux-c-mode () "Modo C con configuración ajustada para su uso con el núcleo Linux." (interactive) (c-mode) (c-set-style "K&R") (setq c-basic-offset 8)) Esto definirá el comando M-x linux-c-mode. Cuando se encuentre trasteando en un módulo, si pone la cadena -*- linux-c -*- en algún lugar de las primeras dos líneas, se invocará automáticamente este modo. También, puede desear añadir (setq auto-mode-alist (cons '("/usr/src/linux.*/.*\\.[ch]$" . linux-c-mode) auto-mode-alist)) a su fichero .emacs si desea tener el modo linux-c conectado automágicamente cada vez que edite ficheros de fuente del directorio /usr/src/linux. Pero si incluso falla en conseguir de emacs un formato correcto, no todo está perdido: use "indent". Ahora, de nuevo, GNU indente tiene los mismos ajustes por defecto que tiene GNU emacs, por lo que será necesario darle unas cuantas opciones de línea de comandos. Sin embargo, esto no está demasiado mal, porque incluso los creadores de GNU indent reconocen la autoridad de K&R (la gente de GNU no son malvadas, simplemente están algo perdidas en esta materia), por lo que simplemente debe dar a indent las opciones "-kr -i8" (que significa "K&R, sangrías de 8 caracteres"). "indent" tiene muchas opciones, y a la hora de comentar el fichero reformateado puede desear echar un vistazo a la página de manual. Pero recuerde: "indent" no es la solución para una mala programación.