[Madrid-pm] [RFC] Gestión de errores
Victor Moral
victor en taquiones.net
Vie Mar 16 08:40:28 PDT 2007
El Viernes, 16 de Marzo de 2007 12:48, DervishD escribió:
> He estado ojeando el libro y probablemente me lo compre en cuanto
> esté seguro de que mi mujer no me emasculará por comprar otro libro más
> de chorradas de ordenadores XDDD
No es barato, desde luego, pero creo que merece la pena.
> En general, coincido bastante con la política de Conway de "ya sé
> que jode, pero las cosas hay que hacerlas bien". Lo que no quiere decir
> que esté de acuerdo con todo lo que dice en su libro, pero en lineas
> generales pensamos parecido.
Pues a mí me ha tenido que demostrar mucho que tenía razón, y al final se la
he dado cuando he tenido que afrontar aplicaciones grandes :-)
> Bueno, lo del "isa()" se pasa un poco por el forro la encapsulación
> y no es buena práctica para un diseño orientado a objetos, en mi
> opinión, pero entiendo el mecanismo y personalmente también usaría isa()
> para gestionar, en lugar de hacer un framework que obligase al llamante
> a usar una implementación y diseños orientados a objeto. Es un buen
> compromiso usar "isa()".
En realidad es fundamental para ello y no toca para nada la encapsulación. Si
defines un conjunto de clases como estas:
use Exception::Class (
'Impresor::X' => {
isa => 'Basicos::Exceptions'
},
'Impresor::X::Config' => {
isa => 'Impresor::X',
description => 'Error in config file'
},
'Impresor::X::Config::File' => {
isa => 'Impresor::X::Config',
description => 'Config file not found or bad perms',
fields => [ qw(errno file) ]
},
'Impresor::X::Config::Template' => {
isa => 'Impresor::X::Config',
description => 'Template file not found or bad perms',
fields => [ qw(errno file) ]
},
'Impresor::X::Config::Template::Format' => {
isa => 'Impresor::X::Config::Template',
description => 'Invalid template format',
fields => [ qw(where) ]
},
'Impresor::X::Config::Content' => {
isa => 'Impresor::X::Config',
description => 'Malformed config file',
fields => [ qw(line) ]
},
'Impresor::X::Work::Queue' => {
isa => 'Impresor::X::Work',
description => 'Could not alloc new spool item',
fields => [ qw( queue ) ]
},
'Impresor::X::Work::Job' => {
isa => 'Impresor::X::Work',
description => 'Missing job parameters in work definition'
},
'Impresor::X::Work::Job::Fields' => {
isa => 'Impresor::X::Work::Job',
description => 'Missing essential component in job definition',
fields => [ qw( component ) ]
},
);
Puedes de un vistazo comprobar si el error tiene que ver con la configuración
my $ex = $@;
if ($ex->isa('Impresor::X::Config')) {
if ($ex->isa('Impresor::X::Config::File')) {
# no existe el archivo de configuración, no importa, utilizamos
# los valores por defecto
1;
}
else {
# cualquier otra cosa es fatal: lanzamos hacia atrás
$ex->rethrow();
}
...
ó con la gestión de trabajos
if ($@->isa('Impresor::X::Work')) {
...
Exceptions::Class utiliza una función llamada caught() que simplifica un poco
las cosas, porque si la excepción la ha provocado die() o croak() la
convierte en un objeto Exception::Class antes de retornar.
> Nunca he usado Exception::Class, pero le echaré un ojo. Soy bastante
> reacio a usar módulos que no vengan en el core, así que (como soy un
> capullo y lo sé y no me importa) igual me escribo algo similar para
> colocarlo en mi Common.pm. Me gusta la abstracción de usar "throw" en
> lugar de "die", que me parece mucho más intuitivo aunque sea sólo un
> cambio de nombre. Y sí, ciertamente facilita la gestión de excepciones.
Eso me pasaba a mí antes, que no quería utilizar nada que no viniese dentro
de Perl, pero al final me he dado cuenta de que es un tanto absurdo no usar
herramientas buenas y probadas. Lo que sí puede pasarte es que algo como "ví
todo lo que había y nada me satisfizo" y, como dices, lo termines haciendo
tú. :-)
> Estoy acostumbrado a no usar depuradores paso a paso, suelo usar
> otras técnicas y sólo recurro al debugger cuando no puedo evitarlo.
> Además, se supone que gestionando los errores así deberías ahorrarte
> bugs...
Bueno, más que ahorrarte errores los aislas y los tratas en zonas mucho más
definidas que antes, que debías pasar hacia atrás un valor por ocho ó nueve
capas de funciones.
Por cierto, ¿ has utilizado Smart::Comments ? Tengo unas notas sobre ello y
es otro mecanismo que empiezo a usar mucho:
http://taquiones.net/perl/cpan/smartcomments.html
> Supongo que ningún código del que maneja excepciones de tu trabajo
> está bajo licencia GPL o similar ¿me equivoco? Es que estaría muy bien
> ver la propagación de excepciones en acción.
Sí, te equivocas, lo único que no es público es el repositorio de subversion,
pero los paquetes Debian están disponibles:
http://www.venexma.net/debian/pool/main/i/impresor/
Eso sí, éste tuvimos que hacerlo durante una emergencia y le falta muchísima
documentación; tanta que estuve a punto de saltarme un ojo el otro día
añadiéndole un listado.
> Por cierto que hace un tiempo escribí un código de prueba para hacer
> excepciones en C, usando setjmp y longjmp, pero lo dejé porque aunque
Uf, tiempo hace de eso. Era un mecanismo muy divertido para trabajar con él.
> funcionaba, había demasiados cabos sueltos, y es que intentar añadir
> semántica try/throw/catch al C es una locura. Al final lo hice a la
> forma C, con una librería de gestión de excepciones... que nunca terminé
> (¿he hablado ya del vicio que tengo de procastinar?, pues eso).
¡ Qué me vas a contar ! Y antes todavía, pero ahora con la niña no hay
manera :-)
Saludos
--
--------
Víctor Moral <victor en taquiones.net>
http://taquiones.net/victor.html
Usuario Linux nº 139246
------------ próxima parte ------------
Se ha borrado un mensaje que no está en formato texto plano...
Nombre : no disponible
Tipo : application/pgp-signature
Tamaño : 189 bytes
Descripción: no disponible
Url : http://mail.pm.org/pipermail/madrid-pm/attachments/20070316/7b47c44c/attachment.bin
Más información sobre la lista de distribución Madrid-pm