Globales
¿ Qué entiendo por un global ? Desde mi punto de vista es una entidad que debe cumplir una serie de condiciones:
- Estar accesible desde cualquier parte de la aplicación, tanto en partes ya escritas como en partes por escribir.
- Crear la dependencia más débil posible entre los componentes de una aplicación.
- Ser fácilmente identificable y cómodo de usar.
Todos estos puntos los cumple la creación de un paquete especial dentro de la aplicación que utilice una técnica conocida como Instancia única.
Para ello empleo a veces el módulo --cs-- de Andy Wardley por su sencillez y fiabilidad.
Un ejemplo es:
1 package MyGlobal; 2 use base qw(Class::Singleton); 3 4 ... 5 6 package main; 7 8 my $glob = MyGlobal->instance(); 9 10 ... 11 12 my $same_glob = MyGlobal->instance();
Aunque dicho módulo es sólo un pilar en el que basar el resto; para mis aplicaciones prefiero algo un poco más completo.
Un módulo más completo ...
... sería aquél que cumple las siguientes condiciones:
- Proporciona métodos de acceso para todos los valores globales de la aplicación.
- Permite emplear un archivo de configuración.
- Dispone de un mecanismo sencillo y agradable de usar.
Los métodos de acceso pueden suplirse fácilmente si basamos la clase en un hash, como de hecho es --cs--, y empleamos el módulo --ac-- para ello.
La sencillez de uso viene dada por una parte por el propio --cs--, con su casi
único método instance()
, y por otra por incluir un mecanismo extra de
importación de símbolos, para que pueda emplearse de la siguiente forma:
1 use MyGlobal qw($Config); 2 3 my $email = $Config->email() || 'root@localhost';
es decir, imitando el estilo de vars, declaramos una variable a importar automáticamente con una referencia al objeto global. Después es muy sencillo utilizarla para recuperar valores concretos, sin pereza alguna.
Por último el tema del archivo de configuración, que también tiene que cumplir algunas condiciones:
- Debe estar escrito en un formato estándar como YAML ó el formato del servidor Apache.
- Su estructura interna debe tener una relación muy directa con los métodos y valores para los que el módulo global tiene acceso directo, de tal manera que no sea necesario efectuar demasiadas conversiones entre valores y se deba recurrir menos a la documentación.
- Su localización puede variar, incluso estar en múltiples sitios, y no siempre debe ser obligatoria su presencia.
Declarando variables para importar
El siguiente código está robado del módulo vars, versión 1.01, y ligeramente retocado para simplificarlo.
1 package MyGlobal; 2 3 use warnings; 4 use strict qw(subs vars); 5 6 sub import { 7 my $callpack = caller; 8 my ($pack, @imports) = @_; 9 10 # extraemos el símbolo y el prefijo de tipo de variable 11 my ($ch, $sym) = ($imports[0] =~ m{^([\$\@\%\*\&])(.+)}xms); 12 13 # ajustamos el nombre del símbolo si es relativo 14 if ($sym !~ m{::}) { 15 $sym = "${callpack}::${sym}"; 16 } 17 18 # y lo insertamos por las bravas en su tabla de símbolos 19 *$sym = \$$sym; 20 21 return; 22 }