¿Qué hace que el código Perl sea mantenible?
maintainability (8)
¿Qué hace que el código Perl sea mantenible?
Por lo menos
use strict;
use warnings;
Vea perldoc perlstyle para conocer algunas pautas generales que harán que sus programas sean más fáciles de leer, comprender y mantener.
He estado escribiendo Perl desde hace varios años y es mi lenguaje preferido para el procesamiento de textos (muchos de los problemas genéticos / genómicos en los que trabajo se reducen fácilmente a problemas de procesamiento de textos). Perl como lenguaje puede ser muy indulgente, y es posible escribir código muy pobre pero funcional en Perl. Justo el otro día, mi amigo dijo que llama a Perl un lenguaje de solo escritura: escríbalo una vez, entiéndalo una vez, y nunca intente volver y arreglarlo después de que haya terminado.
Aunque definitivamente he sido culpable de escribir malos scripts a veces, siento que también he escrito un código muy claro y mantenible en Perl. Sin embargo, si alguien me preguntara qué hace que el código sea claro y fácil de mantener, no podría dar una respuesta segura.
¿Qué hace que el código Perl sea mantenible? O tal vez una mejor pregunta es: ¿qué hace que el código Perl sea difícil de mantener? Supongamos que no soy el único que mantendrá el código, y que los otros colaboradores, como yo, no son programadores profesionales de Perl sino científicos con experiencia en programación.
¿Qué hace que el código Perl no se pueda mantener? Prácticamente todo lo que hace que cualquier otro programa no se pueda mantener. Suponiendo que no sea un script corto destinado a realizar una tarea bien definida, estos son:
- Variables globales
- Falta de separación de preocupaciones: guiones monolíticos
- NO usar identificadores de auto-documentación (nombres de variables y nombres de métodos). Por ejemplo, debes saber cuál es el propósito de una variable a partir de su nombre.
$c
mal.$count
mejor.$token_count
bueno.- Los identificadores de hechizos a cabo. El tamaño del programa ya no es una preocupación primordial.
- Una subrutina o método llamado
doWork
no dice nada. - Facilite encontrar la fuente de los símbolos de otro paquete.
use MyModule qw(list of imports)
prefijo de paquete explícito, o importe explícitamente todos los símbolos utilizados mediante eluse MyModule qw(list of imports)
.
- Perl-específico:
- Dependencia excesiva de atajos y oscuras variables incorporadas
- Abuso de prototipos de subrutinas.
- no usar
strict
y no usarwarnings
- Reinventar la rueda en lugar de utilizar bibliotecas establecidas.
- No usar un estilo de sangría consistente
- No utilizar espacios en blanco horizontales y verticales para guiar al lector.
etc. etc. etc.
Básicamente, si crees que Perl es -f>@+?*<.-&''_:$#/%!
, y usted aspira a escribir cosas como esa en el código de producción, entonces, sí, tendrá problemas.
La gente tiende a confundir las cosas que los programadores de Perl hacen para divertirse (por ejemplo, JAPHs, golf, etc.) con lo que se supone que deben ser los buenos programas de Perl.
Todavía no estoy seguro de cómo pueden separar en sus mentes el code escrito para IOCCC de la C. mantenible.
Hablaré algunas cosas positivas para que Perl pueda mantenerse.
Es cierto que, por lo general, no debería ser demasiado inteligente con declaraciones realmente densas a la return !$@;#%
Y similares, pero sí una buena cantidad de operadores inteligentes de procesamiento de listas, como map
and grep
y list-context return from Los gustos de operadores split
y similares, para escribir código en un estilo funcional pueden hacer una contribución positiva a la capacidad de mantenimiento. En mi último empleador también teníamos algunas funciones elegantes de manipulación de hash que funcionaban de manera similar ( hashmap
y hashgrep
, aunque técnicamente solo las alimentábamos con listas de tamaño uniforme). Por ejemplo:
# Look for all the servers, and return them in a pipe-separated string
# (because we want this for some lame reason or another)
return join ''|'',
sort
hashmap {$a =~ /^server_/ ? $b : +()}
%configuration_hash;
Consulte también Perl de orden superior , http://hop.perl.plover.com : el buen uso de la metaprogramación puede hacer que las tareas de definición sean más coherentes y legibles, si puede evitar que la metaprogramación en sí misma se interponga.
No uso todas las Mejores Prácticas de Perl , pero para eso lo escribió Damian. Independientemente de si utilizo todas las sugerencias, vale la pena considerarlas al menos.
Un factor muy importante para la legibilidad del código que no he visto mencionado en otras respuestas es la importancia del espacio en blanco, que es a la vez Perl-agnóstico y en algunos aspectos es específico de Perl.
Perl le permite escribir código MUY conciso, pero los fragmentos de información no significan que deben estar agrupados.
El espacio en blanco tiene muchos significados / usos cuando hablamos de legibilidad, no todos ellos son ampliamente utilizados, pero sí más útiles:
Espacios alrededor de fichas para separarlos visualmente más fácilmente.
Este espacio es doblemente importante en Perl debido a la prevalencia de caracteres de ruido de línea incluso en el código Perl de mejor estilo.
Encuentro que
$myHashRef->{$keys1[$i]}{$keys3{$k}}
es menos legible a las 2 am en el medio de la producción de emergencia en comparación con el espaciado:$myHashRef->{ $keys1[$i] }->{ $keys3{$k} }
.Como nota al margen, si encuentra que su código está haciendo muchas expresiones de referencia anidadas profundas, todas comenzando con la misma raíz, debería considerar la posibilidad de asignar esa raíz a un puntero temporal (vea el comentario / respuesta de Sinan).
Un caso especial parcial pero MUY importante de esto es, por supuesto, expresiones regulares. La diferencia se ilustró hasta la muerte en todos los materiales principales que recuerdo (PBP, libro RegEx O''Reilly, etc.), así que no alargaré aún más esta publicación a menos que alguien solicite ejemplos en los comentarios.
Indentación correcta y uniforme. D''oh. Obviamente. Sin embargo, veo demasiado código 100% ilegible debido a una sangría horrible, e incluso menos legible cuando la mitad del código fue sangrada con TAB por una persona cuyo editor usó 4 pestañas de caracteres y otra por una persona cuyo editor usó 8 TAB de caracteres. Solo configura tu editor sangriento para que haga TABs suaves (por ejemplo, con espacio de emulación) y no hagas que los demás sean miserables.
Líneas vacías alrededor de unidades de código lógicamente separadas (ambos bloques y solo conjuntos de líneas). Puede escribir un programa Java de 10000 líneas en 1000 líneas de Perl bueno. Ahora no se sienta como Benedict Arnold si agrega 100-200 líneas vacías a esas 1000 para hacer las cosas más legibles.
Dividir expresiones súper largas en múltiples líneas, seguidas de cerca por ...
Corregir la alineación vertical. Sea testigo de la diferencia entre:
if ($some_variable > 11 && ($some_other_bigexpression < $another_variable || $my_flag eq "Y") && $this_is_too_bloody_wide == 1 && $ace > my_func() && $another_answer == 42 && $pi == 3) {
y
if ($some_variable > 11 && ($some_other_bigexpression < $another_variable || $my_flag eq "Y") && $this_is_too_bloody_wide == 1 && $ace > my_func() && $another_answer == 42 && $pi == 3) {
y
if ( $some_variable > 11 && ($some_other_bigexpression < $another_variable || $my_flag eq "Y") && $this_is_too_bloody_wide == 1 && $ace > my_func() && $another_answer == 42 && $pi == 3) {
Personalmente, prefiero arreglar la alineación vertical un paso más alineando LHS y RHS (esto es especialmente legible en el caso de consultas SQL largas, pero también en el propio código Perl, tanto los condicionales largos como este, así como muchas líneas de asignaciones y Inicializaciones de hash / array):
if ( $some_variable > 11 && ($some_other_bigexpression < $another_variable || $my_flag eq "Y") && $this_is_too_bloody_wide == 1 && $ace > my_func() && $another_answer == 42 && $pi == 3 ) {
Como nota al margen, en algunos casos, el código se podría hacer aún más legible / mantenible al no tener expresiones tan largas en primer lugar. Por ejemplo, si el contenido del bloque
if(){}
es unreturn
, entonces hacer varias declaracionesif/unless
cada una de las cuales tiene un bloque de retorno puede ser mejor.
Veo esto como una cuestión de personas a las que se les dice que Perl es ilegible, y comienzan a hacer suposiciones acerca de la capacidad de mantenimiento de su propio código. Si eres lo suficientemente consciente como para considerar la legibilidad como un sello distintivo de un código de calidad, es probable que esta crítica no se aplique a ti.
la mayoría de las personas citarán expresiones regulares cuando discutan la legibilidad. las expresiones regulares son un dsl incrustado en perl y puede leerlas o no. Si alguien no puede tomarse el tiempo para entender algo tan básico y esencial para muchos idiomas, no me preocupa tratar de salvar un poco de brecha cognitiva inferida ... solo deben formar parte del personal, leer los perldocs y hacer preguntas cuando sea necesario. .
otros citarán el uso de perl de variables de formato corto como @_, $! Todos estos son fácilmente desambiguados ... No estoy interesado en hacer que Perl se vea como Java.
La ventaja de todas estas peculiaridades y perlismos es que las bases de código escritas en el lenguaje a menudo son concisas y concisas. Prefiero leer diez líneas de perl que cien líneas de Java.
para mí, hay mucho más en cuanto a la "capacidad de mantenimiento" que el simple hecho de tener un código fácil de leer. escriba pruebas, haga afirmaciones ... haga todo lo que pueda hacer para apoyarse en perl y su ecosistema para mantener el código correcto.
En resumen: escriba los programas para que sean correctos primero, luego seguros, luego de buen desempeño ... una vez que se hayan cumplido estos objetivos, luego preocuparse por hacer que sea agradable acurrucarse cerca de un incendio.
Yo diría que los modelos de empaquetado / objeto, que se reflejan en la estructura del directorio para los archivos .pm. Para mi doctorado, escribí una gran cantidad de código Perl que reutilizo después. Fue para el generador automático de diagramas LaTeX.
Yo sugiero:
- No te pongas demasiado listo con el Perl. Si comienzas a jugar golf con el código, esto resultará en un código más difícil de leer. El código que escribe debe ser legible y claro más de lo que necesita para ser inteligente.
- Documentar el código. Si es un módulo, agregue un POD que describa el uso y los métodos típicos. Si es un programa, agregue POD para describir las opciones de la línea de comandos y el uso típico. Si hay un algoritmo de pelos, documéntelo y proporcione referencias (URL) si es posible.
- Utilice la forma /.../x de las expresiones regulares y documéntelas. No todos comprenden bien las expresiones regulares.
- Sepa qué es el acoplamiento, y los pros / contras del acoplamiento alto / bajo.
- Sepa qué es la cohesión y los pros / contras de la cohesión alta / baja.
- Use los módulos apropiadamente. Un buen concepto bien definido y bien contenido constituye un gran módulo. La reutilización de tales módulos es el objetivo. No utilice módulos simplemente para reducir el tamaño de un programa monolítico.
- Escribe pruebas unitarias para tu código. Un buen conjunto de pruebas no solo le permitirá probar que su código funciona hoy, sino también mañana. También le permitirá realizar cambios más audaces en el futuro, con la confianza de que no está rompiendo aplicaciones antiguas. Si rompes cosas, entonces, bueno, tu conjunto de pruebas no fue lo suficientemente amplio.
Pero en general, el hecho de que te preocupes lo suficiente por la capacidad de mantenimiento para hacer una pregunta al respecto, me dice que ya estás en un buen lugar y que estás pensando de la manera correcta.