2010-04-07 23 views
5

Me resulta muy conveniente pasar la configuración y otros datos que se leen o calculan una vez, pero luego se usan muchas veces en un programa utilizando el mecanismo use de Perl. Estoy haciendo esto exportando un hash al espacio de nombres de la persona que llama. Por ejemplo:¿Es una buena práctica exportar variables en Perl?

package Myconfiguration; 

my %config; 

sub import { 
    my $callpkg = caller(0); 
    my $expsym = $_[1]; 

    configure() unless %config; 

    *{"$callpkg\::$expsym"} = \%config; 
} 

y luego en otros módulos:

use MyConfiguration (loc_config_sym); 

if ($loc_config_sym{paramater}) { 
    # ... do stuff ... 
} 

Sin embargo, no estoy seguro de esto como una buena práctica. ¿Es mejor agregar un método que devuelva una referencia hash con los datos? ¿Algo más?

Respuesta

5

Si sólo desea leer los valores de %config, entonces por qué no tienen una rutina que lo haga por ¿tú?

my %config; 
sub config_value 
{ 
     my ($value) = @_; 
     return $config{$value}; 
} 

puede exportar esto por defecto si se quería:

package Mypackage; 
require Exporter; 
@EXPORT = qw/config_value/; 

La razón por la que no iba a permitir el acceso al hash por todo el lugar en un montón de diferentes módulos es que iba a tener un momento difícil para hacer un seguimiento mental de todos los lugares donde se estaba utilizando. Prefiero realizar el tipo de acceso anterior de rutina para que, si ocurriera algún error, podría agregar una declaración de impresión a la rutina, o algo así, para averiguar cuándo se accedía al valor. No sé si eso está relacionado con las "mejores prácticas" o simplemente porque soy estúpido, pero el tipo de confusión creada por las variables globales me asusta.

No hay razón por la que no se puede tener una rutina demasiado:

sub set_value 
{ 
     my ($key, $value) = @_; 
     $config{$key} = $value; 
} 
+0

Esto es lo que el mono dentro de mi cabeza estaba tratando de decirme pero no pude salir (aunque prefiero usar Exporter qw (import); ':)). Realmente no pensé en esto como una variable global cuando en la práctica eso es exactamente lo que estoy haciendo aquí. El único inconveniente aquí es la sobrecarga de llamada al método, pero eso probablemente no sea importante, especialmente teniendo en cuenta el mantenimiento y la depuración. Además, es bastante fácil alias el sub si es conveniente tener un nombre localmente relevante (esto no es solo acerca de la configuración). – gvkv

+0

Estoy de acuerdo en que setters y getters son el camino a seguir. Te dan mucho más control. Por ejemplo, puede hacer comprobaciones en el conjunto de valores y hacer cálculos en el valor obtenido. – Bill

2

Creo que es mejor trabajar con una copia del config hash. De esta manera, si modifica algunos elementos, esto no afectará el resto de su código.

Normalmente uso un objeto simple (opcionalmente Singleton) para esto con un solo método como get_property().

+0

Este ejemplo particular fue uno de configuración, pero no necesariamente. Es decir, podría * querer * cambiar elementos. – gvkv

+0

Puede cambiar los valores en un singleton. –

0

En general, es mejor dejar que el usuario decida si importar o no símbolos. Exporter lo hace fácil. Escribir un método personalizado import para que el usuario decida qué nombre dar a los símbolos importados puede ser útil en raras ocasiones, pero no creo que este sea uno de ellos.

package MyConfiguration; 
require Exporter; 

our @ISA  = qw(Exporter); 
our @EXPORT_OK = qw(Config); 

our %Config; 

Y luego, en el script:

use MyConfiguration; 
print $MyConfiguration::Config{key}; 

o

use MyConfiguration qw(Config); 
print $Config{key}; 
+3

Excepto que los documentos del Exportador dicen específicamente: "Exportar variables no es una buena idea. Pueden cambiar bajo el capó, provocando efectos horribles a distancia, que son demasiado difíciles de rastrear y solucionar. Confía en mí: no valen la pena eso." Realmente, en este caso, solo porque puedes, no significa que sea una buena idea. –

2

Sugiero no exportar variables. Cree una clase que pueda devolver una referencia a una variable privada en su lugar. Las personas pueden almacenarlo en una variable con el nombre que quieran, y solo cuando decidan que quieren usarlo.

Cuestiones relacionadas