2016-11-28 11:58 GMT+01:00 Joaquin Ferrero <explo...@joaquinferrero.com>:
> Buenos días. > > En la charla que nos dio dayer, vimos cómo seleccionar un > comportamiento u otro según el S.O. en donde nos encontremos. Incluido la > carga de módulos distintos para Linux/Windows. > > Comenté que había visto en CPAN diversas opciones para hacer eso > mismo, sobre todo evitar tener que repetir el código > > if ($^O eq 'Win32') { > > una y otra vez. La idea es tener una API común, y luego cada módulo, > tendrá su interfaz propia de cada S.O. > > > He encontrado varios ejemplos, y todos ellos muestran formas muy distintas > de solventar la cuestión. Al final del mensaje pongo un listado con las > líneas interesantes. > > > Aquí explicaré la solución de Audio::Beep <https://metacpan.org/release/ > Audio-Beep>, que me parece el más corto y claro donde se puede ver esta > técnica. > > > En Beep.pm, dentro de new(), hay una línea que busca por el mejor > reproductor que exista en nuestro sistema: > > $h{player} = _best_player(); > > > Dentro de _best_player() vemos cómo cargar el módulo correspondiente a > nuestro S.O.: > > |sub| |_best_player {| > |||my| |%os_modules| |= (| > |||linux| |=> [| > |||'Audio::Beep::Linux::beep'||,| > |||'Audio::Beep::Linux::PP'||,| > |||],| > |||MSWin32| |=> [| > |||'Audio::Beep::Win32::API'||,| > |||],| > |||freebsd| |=> [| > |||'Audio::Beep::BSD::beep'||,| > |||],| > |||);| > || > |||for| |my| |$mod| |( @{ ||$os_modules||{$^O} } ) {| > |||if| |(||eval| |"require $mod"||) {| > |||my| |$player| |= ||$mod||->new();| > |||return| |$player| |if| |defined| |$player||;| > |||}| > |||}| > |||return||;| > |}| > > Primero carga un hash con todos los módulos de la distribución. > > Luego, en el bucle for(), extrae los módulos correspondientes al > S.O. en que se está ejecutando. > > Hace un eval "requiere ...", y regresa si la inicialización ha sido > correcta. > > Y dentro de los módulos Audio::Beep::Linux::beep, Audio::Beep::Linux::PP, > Audio::Beep::Win32::API y Audio::Beep::BSD::beep, lo único que hay son tres > funciones básicas: > > new(), para la inicialización, > play(), para tocar una nota, y > rest(), para hacer una pausa > > El programa principal solo tiene que hacer llamadas basadas en esa API: > > $self->player->play( _pitch(\%p), _duration(\%p) ); > > > > Resto de distribuciones que he encontrado extrayendo las líneas > interesantes: > > Net::Routing <https://metacpan.org/release/Net-Routing> - manage route > entries on Operating Systems > > BEGIN { > if ($^O eq 'linux') { > return $_routing_module = "Net::Routing::Linux"; > } > elsif ($^O eq 'freebsd') { > return $_routing_module = "Net::Routing::FreeBSD"; > } > elsif ($^O eq 'netbsd') { > return $_routing_module = "Net::Routing::NetBSD"; > } > elsif ($^O eq 'darwin') { > return $_routing_module = "Net::Routing::Darwin"; > } > #elsif ($^O eq 'MSWin32') { > # return $_routing_module = "Net::Routing::MSWin32"; > #} > #elsif ($^O eq 'openbsd') { > # return $_routing_module = "Net::Routing::OpenBSD"; > #} > die("[-] Net::Routing: Operating System not supported: $^O\n"); > } > sub new { > my $self = shift->SUPER::new( > path => [ qw(/bin /sbin /usr/bin /usr/sbin /usr/local/bin > /usr/local/sbin) ], > lc_all => 'en_GB.UTF-8', > target => NR_TARGET_ALL(), > family => NR_FAMILY_INET4(), > @_, > ); > $self->path([ @{$self->path}, split(':', $ENV{PATH}) ]); > eval("use $_routing_module;"); > if ($@) { > chomp($@); > $Error = "unable to load routing module [$_routing_module]: $@"; > return; > } > > Sys::Ramdisk <https://metacpan.org/release/Sys-Ramdisk> - Create and nuke > RAM disks on various systems > > Unix::Uptime <https://metacpan.org/release/Unix-Uptime> - Determine the > current uptime, in seconds, and load averages, across different *NIX > architectures > > my $module = $modules{$^O} > or die "Operating system type $^O is currently unsupported"; > require "Unix/Uptime/$module.pm"; > our @ISA = ("Unix::Uptime::$module"); > > IO::Async <https://metacpan.org/release/IO-Async> - Asynchronous > event-driven programming > > if( eval { require "IO/Async/OS/$^O.pm" } ) { > @ISA = "IO::Async::OS::$^O"; > } > > System::Info <https://metacpan.org/release/System-Info> - Factory for > system specific information objects > > sub new { > my $factory = shift; > $^O =~ m/aix/i and return > System::Info::AIX->new; > $^O =~ m/bsd/i and return System::Info::BSD->new; > $^O =~ m/cygwin/i and return System::Info::Cygwin->new; > $^O =~ m/darwin/i and return System::Info::Darwin->new; > $^O =~ m/haiku/ and return System::Info::Haiku->new; > $^O =~ m/hp-?ux/i and return System::Info::HPUX->new; > $^O =~ m/irix/i and return System::Info::Irix->new; > $^O =~ m/linux/i and return System::Info::Linux->new; > $^O =~ m/solaris|sunos|osf/i and return System::Info::Solaris->new; > $^O =~ m/VMS/ and return System::Info::VMS->new; > $^O =~ m/mswin32|windows/i and return System::Info::Windows->new; > return System::Info::Generic->new; > } > > App::Slaughter <https://metacpan.org/release/App-Slaughter> - Perl > Automation Tool Helper > > Parse::Netstat <https://metacpan.org/release/Parse-Netstat> - Parse the > output of "netstat" command > > if ($flavor eq 'linux') { > require Parse::Netstat::linux; > Parse::Netstat::linux::parse_netstat( > output=>$output, tcp=>$tcp, udp=>$udp, unix=>$unix); > } elsif ($flavor eq 'freebsd') { > require Parse::Netstat::freebsd; > Parse::Netstat::freebsd::parse_netstat( > output=>$output, tcp=>$tcp, udp=>$udp, unix=>$unix); > } elsif ($flavor eq 'solaris') { > require Parse::Netstat::solaris; > Parse::Netstat::solaris::parse_netstat( > output=>$output, tcp=>$tcp, udp=>$udp, unix=>$unix); > } elsif ($flavor eq 'win32') { > require Parse::Netstat::win32; > Parse::Netstat::win32::parse_netstat( > output=>$output, tcp=>$tcp, udp=>$udp); > } else { > return [400, "Unknown flavor '$flavor', please see --help"]; > } > > Sys::Filesystem <https://metacpan.org/release/Sys-Filesystem> - Retrieve > list of filesystems and their properties > > [ @query_order = map { __PACKAGE__ . '::' . $_ } ( ucfirst( lc $^O ), > $^O =~ m/Win32/i ? 'Win32' : 'Unix', 'Dummy' ) ] > > En esta última distribución, se usa Module::Pluggable, para cargar el > módulo como si fuera un "plugin" o complemento de la propia distribución. > > Saludos, > > Muchas gracias Joaquín. Voy a experimentar con estas sugerencias y actualizaré mi ejemplo :-) Un saludo,
_______________________________________________ Madrid-pm mailing list Madrid-pm@pm.org http://mail.pm.org/mailman/listinfo/madrid-pm