#... at the start of your code ... # notice how exception definition and message format # string constant are in two different places and need # to be manually coordinated by the programmer. use Exception::Class { 'Exception::Copy::Mine' { fields => [qw(from to)]; } # ... lots of other exceptions here ... } my $MSG_COPY='Could not copy A.txt to B.txt"; ... later on when you throw the exception ... # notice the repetition in the use of exception # properties; the repetition is error prone and adds # unnecessary extra typing my $sMsg = sprintf($MSG_COPY, 'A.txt', 'B.txt'); Exception::Copy::Mine->throw(error => $sMsg , from => 'A.txt' , to => 'B.txt'); #### # the declaration puts the message format string and the # class declaration together for the programmer, thus # resulting in less maintenence work declareExceptionClass("Exception::Mine::Copy" , "Could not copy %s to %s", [ qw(from, to) ]); .... some where else in your code ... # there is no need to explicitly call sprintf or # repetitively type variable names, nor even remember # the order of parameters in the format string or check # for undefined values. Both of these will produce # the same error message: # "Could not copy A.txt to B.txt" die "Exception::Mine:Copy"->new(from =>'A.txt', to=>'B.txt'); die "Exception::Mine:Copy"->new(to =>'B.txt', from=>'A.txt'); # and this will politely fill in 'undef' for the # property you leave out: # "Could not copy A.txt to " die "Exception::Mine::Copy"->new(from=>'A.txt');