package Object; sub new { my $class = shift; my $self = { 'ERRSTR' => undef }; bless $self, $class; return $self; } sub _errstr { return $_[0]->{'ERRSTR'}; } sub _login { my $self = shift; eval { ... $self->{'CONNECTION'} = .... }; if($@) { $self->{'ERRSTR'} = $@; return 1; } return 1; } sub _ping { my $self = shift; eval { if(not $self->{'CONNECTION'}) { $self->login() or die $self->errstr(); } .... }; if($@) { $Self->{'ERRSTR'} = $@; return 0; } return 1; } # This allows me to control nesting so that debug statements are indented by 1 space so that # I can easily see the flow if I call Object->set_debug(1) from the application. AUTOLOAD { our $AUTOLOAD; my $request = undef; my $funcs = { 'ping' => sub { _ping(@_); }, .. }; if($AUTOLOAD =~ m/^Object::(.+?)$/) { $request = $1; foreach my $ref (keys %{ $funcs }) { next unless $ref eq $request; ... increment debug indention ... my $val = $funcs->{$ref}->($@); ... decrement debug indention .... return $val; } } die "Method ${AUTOLOAD} does not exist." } #### use Object. sub main { eval { my $service = Object->new("127.0.0.1", .....); $service->ping() or die $service->errstr(); }; if($@) { warn "$@"; return 1; } return 0; } exit main;