2010-02-11 7 views
12

considerar esta clase simple:¿Cómo puedo obtener excepciones estructuradas de Moose?

package Foo; 
use Moose; 
has foo => (is => 'rw', isa => 'Int'); 

Y entonces este código:

use Try::Tiny; 
use Foo; 
my $f = try { 
    Foo->new(foo => 'Not an Int'); 
} 
catch { 
    warn $_; 
}; 

El código muere con un mensaje de error grande y bonita sobre restricciones de tipo defecto.

Quisiera poder extraer qué atributo falló (foo), cuál fue la razón (restricción de tipo fallida) y cuál fue el valor pasado (Not an Int) sin tener que analizar una cadena de error para obtener la información.

Algo como esto:

catch { 
    if($_->isa('MooseX::Exception::TypeConstraint')) { 
     my $attrib = $_->attribute; 
     my $type = $_->type; 
     my $value = $_->bad_value; 

     warn "'$value' is an illegal value for '$attrib'. It should be a $type\n"; 
    } 
    else { 
     warn $_; 
    } 
}; 

Es esto posible? ¿Hay una distribución de MooseX que pueda hacer que esto suceda? Mejor aún, ¿hay alguna característica de Moose que eché de menos que hará esto posible?

Actualización: Estoy particularmente interesado en las limitaciones de tipo, pero otros errores de Moose también serían muy buenos. También soy consciente de que puedo lanzar objetos con die. Entonces, estructurar excepciones en el código que escribo es relativamente fácil.

Respuesta

4

No lo he probado, pero creo que MooseX::Error::Exception::Class podría ser lo que estás buscando.

+0

Esto es muy interesante.Funciona como MooseX :: Throwable pero se basa en Exception :: Class y define los inicios de una jerarquía de clases de excepción. Internamente, analiza el mensaje de error para determinar qué tipo de excepción arrojar. – daotoad

+0

Desafortunadamente no se ha actualizado por un tiempo, y falla sus pruebas prácticamente en todas partes. –

3

Consulte MooseX::Throwable, que reemplaza el valor error_class en la metaclase. Sin embargo, el código parece un poco viejo (los metaleros ahora admiten roles de clase de error), pero el método actual parece que funcionará.

+0

Esto se veía realmente prometedor, pero los únicos atributos que tiene son: stack (el seguimiento de pila), previous_exception (en caso de que tengamos excepciones anidadas) y message (el "Atributo (foo) no ...") . Todavía pegado analizar el mensaje. – daotoad

+1

Sí, sospecho que alguien va a tener que hacer una clase de excepción real y construirla explícitamente en casos de error (en el código central), en lugar de simplemente construir una clase alrededor de los mensajes sin procesar que se crean ahora. Sería un buen trabajo revisar todo el código central para cambiarlo y utilizarlo, ¡pero estoy seguro de que muchas personas se lo agradecerán! – Ether

+0

Vaya, no quise ser voluntario. :) Realmente estaba esperando obtener una buena respuesta RTFM. Así es la vida. – daotoad

1

Tuve la misma pregunta hace un año y me preguntaron en el canal #moose IRC. La respuesta fue que Moose en realidad no admite excepciones estructuradas ... todavía.

Existe un acuerdo general de que es una deficiencia de Moose que debe corregirse, pero la tarea de introducir excepciones en todas partes es tediosa y no se ha llevado a cabo (afaik) todavía.

El enfoque en MooseX :: Error :: Exception :: Class es muy frágil, ya que se basa en el análisis de los mensajes de Moose.

Dado que en realidad no se pueden obtener excepciones estructuradas confiables de Moose, considere usar la introspección para probar cada una de las restricciones de tipo una por una al establecer un nuevo valor. Algunas veces este es un enfoque factible.

Por cierto: tenga en cuenta que hay a nasty bug in the way Moose handles composite constraints.

+0

¡Yeouch! Ese es un error heckuva. Aunque Exception :: Class parece interesante, me parece ** incorrecto ** utilizar dos bibliotecas de creación de objetos diferentes en un proyecto. Throwable es interesante, pero creo que las excepciones son uno de los lugares donde la herencia tiene sentido. Cualquier cosa que arrojes, debe ** ser una ** excepción, en lugar de "no arrojable" (lo que sea que eso signifique ...). No estoy 100% vendido porque la herencia es * la * solución correcta. Tal vez la respuesta sea una sola clase de excepción con atributos apropiados. Aun no estoy seguro. – daotoad

+0

Ese error ya se ha cerrado, parece. –

Cuestiones relacionadas