¿Por qué utilizar advertencias estrictas?

104

Me parece que muchas de las preguntas en la etiqueta Perl podrían resolverse si la gente usara:

use strict;
use warnings;

Creo que algunas personas consideran que esto es similar a ruedas de entrenamiento o complicaciones innecesarias, lo que claramente no es cierto, ya que incluso los programadores de Perl muy hábiles los usan.

Parece que la mayoría de las personas que dominan Perl siempre usan estos dos pragmas, mientras que aquellos que se beneficiarían más de usarlos rara vez lo hacen. Entonces, pensé que sería una buena idea tener una pregunta a la que vincular cuando se anime a la gente a use stricty warnings.

Entonces, ¿por qué debería hacerlo un desarrollador de Perl use stricty warnings?

TLP
fuente
14
Siempre me pregunto por cosas como esta por qué no lo convierten en el predeterminado y hacen que el desarrollador tenga que aflojar cosas activamente, ¿dónde está el?use loose;
Paul Tyng
12
Como muchas cosas interesantes y útiles, Perl comenzó como un truco, como una herramienta para el tipo que lo inventa. Más tarde se hizo más popular y un número creciente de personas no calificadas comenzó a usarlo. Aquí es cuando empiezas a pensar que algo como que use strictera una buena idea, pero la compatibilidad con versiones anteriores ya se ha convertido en un problema real para ti :-(
Daniel Böhmer
14
@JB Nizet, @Paul T., en realidad, use strict;está activado de forma predeterminada cuando solicita el idioma Perl 5.12 (o superior). Prueba perl -e"use v5.012; $x=123;". no strict;en realidad lo apaga.
ikegami
1
Aunque al final tu punto es cierto, cuantas más veces lo digamos, tal vez más gente escuche. Últimamente ha habido algunos rumores de intentar hacer disponibles más / mejores / modernos tutoriales de Perl y, ciertamente, las advertencias estrictas estarán en la parte superior de cada uno de ellos. Para el mío, planeo tener s / w en la parte superior de cada fragmento, solo para que todos los novatos lo vean siempre
Joel Berger
5
@JoelBerger No, en realidad no se parece en nada. Como dije, solo tiene palabras similares en el título. Es por compatibilidad con versiones anteriores. es la primera oración en la respuesta aceptada, ¿cómo proponen que se aplique a mi pregunta?
TLP

Respuestas:

83

Para empezar, use strict;(y en menor medida use warnings;) ayuda a encontrar errores tipográficos en los nombres de las variables. Incluso los programadores experimentados cometen tales errores. Un caso común es olvidar cambiar el nombre de una instancia de una variable al limpiar o refactorizar el código.

El uso use strict; use warnings;detecta muchos errores antes de lo que se detectarían de otro modo, lo que facilita la búsqueda de las causas fundamentales de los errores. La causa raíz puede ser la necesidad de un error o verificación de validación, y eso puede suceder independientemente de la habilidad del programador.

Lo bueno de las advertencias de Perl es que rara vez son falsas, por lo que su uso es prácticamente gratuito.


Lectura relacionada: ¿Por qué usar my?

ikegami
fuente
2
@TLP, no voy a hacer un estudio para cuantificar cuánto ayuda. Baste decir que ayudan incondicionalmente.
ikegami
1
¿Por qué se hace opcional entonces si tiene tantos beneficios? ¿Por qué no habilitarlo de forma predeterminada (como alguien comentó anteriormente)? ¿Es por razones de compatibilidad?
Jean
4
@Jean, compatibilidad con versiones anteriores. Tenga en cuenta que use strict;está habilitado de forma predeterminada si usa la versión 5.12 o más reciente del idioma ( use 5.012;).
ikegami
@Jean, si está escribiendo un script simple, realmente no desea recibir alertas sobre los nombres de los controladores de archivos o por no declarar la variable antes de usarlos :-)
user2676847
28

Aparentemente, use strictdebería (debe) usarse cuando desee forzar a perl a codificar correctamente, lo que podría ser forzar una declaración, ser explícito en cadenas y subs, es decir, palabras simples o usar referencias con precaución. Nota: si hay errores, use estricto abortará la ejecución si se usa.

Si bien use warnings;lo ayudará a encontrar errores de escritura en el programa, como si omitió un punto y coma, usó 'elseif' y no 'elsif', está usando una sintaxis o función obsoleta, lo que sea. Nota: las advertencias de uso solo proporcionarán advertencias y continuarán la ejecución, es decir, no abortarán la ejecución.

De todos modos, sería mejor si entramos en detalles, que estoy especificando a continuación.

De perl.com (mi favorito):

use 'vars' estrictas;

lo que significa que siempre debes declarar variables antes de usarlas.

Si no declara, probablemente obtendrá un mensaje de error para la variable no declarada

El símbolo global "$ variablename" requiere un nombre de paquete explícito en la línea 3 scriptname.pl

Esta advertencia significa que Perl no tiene exactamente claro cuál es el alcance de la variable. Por lo tanto, debe ser explícito sobre sus variables, lo que significa declararlas con mypara que estén restringidas al bloque actual, o hacer referencia a ellas con su nombre completo (por ejemplo: $ MAIN :: nombre de la variable).

Por lo tanto, se activa un error en tiempo de compilación si intenta acceder a una variable que no ha cumplido al menos uno de los siguientes criterios:

  • Predefinido por el propio Perl, como @ARGV,% ENV y todas las variables de puntuación globales como $. o $ _.

  • Declarado con nuestro (para un global) o my (para un léxico).

  • Importado de otro paquete. (El uso de vars pragma simula una importación, pero usa nuestro en su lugar).

  • Completamente calificado usando su nombre de paquete y el separador de paquetes de dos puntos.

use 'subs' estrictos;

Considere dos programas

# prog 1
   $a = test_value;
   print "First program: ", $a, "\n";
   sub test_value { return "test passed"; }
 Output: First program's result: test_value

# prog 2
   sub test_value { return "test passed"; }
   $a = test_value;
   print "Second program: ", $a, "\n";
 Output: Second program's result: test passed

En ambos casos tenemos un sub test_value () y queremos poner su resultado en $ a. Y, sin embargo, cuando ejecutamos los dos programas, obtenemos dos resultados diferentes:

En el primer programa, en el punto al que llegamos $a = test_value;, Perl no conoce ningún subtest_value (), y test_value se interpreta como cadena 'test_value'. En el segundo programa, la definición de test_value () viene antes de la $a = test_value;línea. Perl piensa test_value como una sub-llamada.

El término técnico para palabras aisladas como test_value que podrían ser subs y podrían ser cadenas dependiendo del contexto, por cierto, es bareword . El manejo de Perl de barewords puede ser confuso y puede causar errores en el programa.

El error es lo que encontramos en nuestro primer programa. Recuerde que Perl no esperará encontrarlo test_value(), así que como aún no ha visto test_value (), asume que quiere una cadena. Entonces, si usted use strict subs;, causará que este programa muera con un error:

No se permite la palabra clave "test_value" mientras se utilizan "subs estrictos" en ./a6-strictsubs.pl línea 3.

La solución a este error sería
1. Utilice paréntesis para dejar en claro que está llamando a un sub. Si Perl ve $ a = test_value () ;,
2. Declare su sub antes de usarlo por primera vez

use strict;
sub test_value;  # Declares that there's a test_value() coming later ...
my $a = test_value;  # ...so Perl will know this line is okay.
.......
sub test_value { return "test_passed"; }

3. Y si quiere usarlo como una cadena, cítelo.

Entonces, esta restricción hace que Perl trate todas las palabras desnudas como errores de sintaxis. * Una palabra simple es cualquier nombre o identificador desnudo que no tiene otra interpretación forzada por el contexto. (El contexto a menudo es forzado por una palabra clave o token cercano, o por la predeclaración de la palabra en cuestión). * Entonces, si desea usarlo como una cadena, cítelo y si desea usarlo como una llamada de función, preclarelo o use paréntesis.

Las palabras desnudas son peligrosas debido a este comportamiento impredecible. use strict; (or use strict 'subs';)los hace predecibles, porque las palabras simples que podrían causar un comportamiento extraño en el futuro harán que su programa muera antes de que puedan causar estragos

Hay un lugar donde está bien usar barewords incluso cuando ha activado subs estrictos: cuando está asignando claves hash.

$hash{sample} = 6;   # Same as $hash{'sample'} = 6
%other_hash = ( pie => 'apple' );

Las palabras desnudas en las claves hash siempre se interpretan como cadenas, por lo que no hay ambigüedad.

use 'refs' estrictos;

Esto genera un error en tiempo de ejecución si usa referencias simbólicas, intencionalmente o de otra manera. Un valor que no es una referencia estricta se trata como una referencia simbólica. . Es decir, la referencia se interpreta como una cadena que representa el nombre de una variable global.

use strict 'refs';

$ref = \$foo;       # Store "real" (hard) reference.
print $$ref;        # Dereferencing is ok.

$ref = "foo";       # Store name of global (package) variable.
print $$ref;        # WRONG, run-time error under strict refs.

use advertencias;

Este pragma de ámbito léxico permite un control flexible sobre las advertencias integradas de Perl, tanto las emitidas por el compilador como las del sistema de tiempo de ejecución.

De perldiag :

Por tanto, la mayoría de los mensajes de advertencia de las clasificaciones siguientes, es decir, W, D & S, se pueden controlar mediante warningspragma.

(W) Una advertencia (opcional)
(D) Una desaprobación (habilitada de forma predeterminada)
(S) Una advertencia severa (habilitada de manera predeterminada)

He enumerado algunos de los mensajes de advertencia que aparecen a continuación por clasificaciones. Para obtener información detallada sobre ellos y otros mensajes, consulte perldiag

(W) Una advertencia (opcional):

Falta un argumento en% s
Falta un argumento para -% c
(¿Quisiste decir &% s en su lugar?)
(¿Quisiste decir "local" en lugar de "nuestro"?)
(¿Quisiste decir $ o @ en lugar de%?)
'% S 'no es una
longitud de referencia de código () usada en% s fuera de lugar
_ en número

(D) Una desaprobación (habilitada de forma predeterminada):

definido (@array) está en desuso
definido (% hash) está en desuso
Uso en desuso de my () en condicional falso
$ # ya no es compatible

(S) Una advertencia severa (habilitada por defecto)

elseif debería ser elsif
% s donde se esperaba el operador
(¿Falta el operador antes de% s?)
(¿Falta el punto y coma en la línea anterior?)
% s nunca introducido El
operador o el punto y coma falta antes de% s
Problema de precedencia: abierto% s debería estar abierto (% s)
Desajuste del prototipo:% s vs% s
Advertencia: El uso de "% s" sin paréntesis es ambiguo
No se puede abrir% s:% s

ikegami
fuente
10

Estos dos pragmas pueden identificar automáticamente errores en su código.

Siempre uso esto en mi código:

use strict;
use warnings FATAL => 'all';

FATALhace que el código muera en advertencias, al igual que lo stricthace.

Para obtener información adicional, consulte: Sea más estricto con las advertencias de uso FATAL => 'all';

Además ... Las restricciones, según Seuss

herramienta
fuente
En realidad, tienes que retrasar el FATAL => "all"tiempo de ejecución de la caja, asignando a $SIG{__WARN__} = sub { croak "fatalized warning @_" };o de lo contrario arruinas el compilador tratando de decirte lo que necesita.
tchrist
6
@tchrist: Esto siempre me ha funcionado tal como está y como está documentado. Si ha encontrado un caso en el que no funciona como está documentado, parchee la documentación usando perlbug.
toolic
9

Hay un buen hilo sobre perlmonks sobre esta cuestión.

La razón básica, obviamente, es que las advertencias estrictas y masivas lo ayudan a detectar errores y ayudan a la depuración.

malhumorado
fuente
3

Fuente :: Diferentes blogs

Use exportará funciones y nombres de variables al espacio de nombres principal llamando a la función de importación () de los módulos.

Un pragma es un módulo que influye en algún aspecto del tiempo de compilación o el comportamiento del tiempo de ejecución de perl. Los pragmas dan pistas al compilador.

Usar advertencias: quejas de Perl sobre variables que se usan solo una vez, conversiones incorrectas de cadenas en números. Intentar escribir en archivos que no están abiertos. Ocurre en tiempo de compilación. Se usa para controlar advertencias.

Use estricto: declare el alcance de las variables. Se usa para establecer algún tipo de disciplina en el script, si se usan barewords en el código se interpretan, se debe dar alcance a todas las variables, como my, our o local.

Rahul Reddy
fuente
1

La directiva "use estricto" le dice a Perl que realice comprobaciones adicionales durante la compilación de su código. El uso de esta directiva le ahorrará tiempo al depurar su código Perl porque encuentra errores de codificación comunes que de otra manera podría pasar por alto.

MikasaAckerman
fuente
0

Las advertencias estrictas y aseguran que sus variables no sean globales.

Es mucho más ordenado poder tener variables únicas para métodos individuales en lugar de tener que realizar un seguimiento de todos y cada uno de los nombres de las variables.

$ _, o ninguna variable para ciertas funciones, también puede ser útil para escribir código más compacto más rápido.

Sin embargo, si no utiliza advertencias estrictas, $ _ se vuelve global.

Andreas Ährlund
fuente
0
use strict;
use warnings;

Las advertencias estrictas y son el modo para el programa perl. Le permite al usuario ingresar el código de manera más liberal y más que eso, que el código de Perl se verá formal y su estándar de codificación será efectivo.

advertencias significa lo mismo que -wen la línea perl shebang, por lo que le proporcionará las advertencias generadas por el programa perl, se mostrarán en la terminal

dhana govindarajan
fuente