2010-02-11 18 views
12

considerare questo semplice classe:Come posso ottenere eccezioni strutturate da Moose?

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

E poi questo codice:

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

Il codice muore con un bel messaggio di errore grande sul tipo di vincoli fallimento.

mi piacerebbe essere in grado di estrarre ciò che attributo fallito (foo), ciò che la ragione era (vincolo fallito tipo) e che il valore passato era (Not an Int) senza dover analizzare una stringa di errore per avere le informazioni.

Qualcosa di simile a questo:

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 $_; 
    } 
}; 

è possibile? Esiste una distribuzione MooseX in grado di farlo accadere? Meglio ancora, c'è qualche caratteristica di Alce che mi è sfuggita che renderà tutto ciò possibile?

Aggiornamento: Sono particolarmente interessato ai vincoli di tipo, ma altri errori Moose sarebbero molto buoni. Sono anche consapevole del fatto che posso lanciare oggetti con die. Quindi, strutturare le eccezioni nel codice che scrivo è relativamente facile.

risposta

4

Non ho provato da solo, ma penso che MooseX::Error::Exception::Class potrebbe essere quello che stai cercando.

+0

Questo è molto interessante.Funziona come MooseX :: Throwable ma è costruito su Exception :: Class e definisce l'inizio di una gerarchia di classi di eccezioni. Internamente, analizza il messaggio di errore per determinare quale tipo di eccezione da lanciare. – daotoad

+0

Sfortunatamente non è stato aggiornato per un po 'e fallisce praticamente ovunque. –

3

Verificare MooseX::Throwable, che sostituisce il valore error_class nel metaclass. Tuttavia, il codice sembra un po 'obsoleto (le metarole supportano ora i ruoli delle classi di errore), ma il metodo attuale sembra funzionare ancora.

+0

Questo sembrava davvero promettente, ma gli unici attributi che ha sono: stack (la traccia stack), previous_exception (nel caso in cui abbiamo eccezioni nidificate) e messaggio ("Attribute (foo) non ....") . Ancora bloccato ad analizzare il messaggio. – daotoad

+1

Sì, ho il sospetto che qualcuno debba creare una vera classe di eccezione e costruirla esplicitamente in caso di errore (nel codice principale), piuttosto che semplicemente costruire una classe attorno ai messaggi non elaborati che vengono creati ora. Sarebbe un bel lavoro passare tutto il codice di base per cambiarlo per usarli, ma sono sicuro che molte persone ti ringrazieranno! – Ether

+0

oops, non volevo fare volontariato. :) Speravo davvero di ottenere una bella risposta RTFM. È la vita. – daotoad

1

Ho avuto la stessa domanda circa un anno fa e ho chiesto al canale IRC#moose. La risposta è stata che Moose in realtà non supporta eccezioni strutturate .... ancora.

C'è un accordo generale sul fatto che si tratta di un difetto di Moose che dovrebbe essere corretto, ma il compito di introdurre eccezioni ovunque è noioso e non è stato ancora eseguito.

L'approccio in MooseX :: Error :: Exception :: Class è molto fragile, poiché si basa sull'analisi dei messaggi da Moose.

Poiché non è possibile ottenere eccezioni strutturate affidabili da Moose, è consigliabile utilizzare l'introspezione per verificare singolarmente i vincoli di tipo quando si imposta un nuovo valore. Alcune volte questo è un approccio fattibile.

Btw: notare che c'è a nasty bug in the way Moose handles composite constraints.

+0

Yeouch! Questo è un bug heckuva. Mentre Exception :: Class sembra interessante, mi sembra ** sbagliato ** usare due diverse librerie di oggetti in un unico progetto. Throwable è interessante, ma penso che le eccezioni siano uno dei luoghi in cui l'ereditarietà ha un senso. Qualsiasi cosa tu lanci, dovrebbe ** essere un'eccezione **, piuttosto che "fare Lanciagranate" (qualunque cosa significhi ...). Non sono al 100% venduto che l'ereditarietà sia * la * soluzione corretta. Forse la risposta è una singola classe di eccezione con attributi appropriati. Non sono ancora sicuro. – daotoad

+0

Quel bug è stato chiuso, sembrerebbe. –

Problemi correlati