App-Info
view release on metacpan or search on metacpan
lib/App/Info.pm view on Meta::CPAN
This section describes the facilities App::Info provides for subclassing. The
goal of the App::Info design has been to make subclassing straight-forward, so
that developers can focus on gathering the data they need for their
application and minimize the work necessary to handle unknown values or to
confirm values. As a result, there are essentially three concepts that
developers need to understand when subclassing App::Info: organization,
utility methods, and events.
=head2 Organization
The organizational idea behind App::Info is to name subclasses by broad
software categories. This approach allows the categories themselves to
function as abstract base classes that extend App::Info, so that they can
specify more methods for all of their base classes to implement. For example,
App::Info::HTTPD has specified the C<httpd_root()> abstract method that its
subclasses must implement. So as you get ready to implement your own subclass,
think about what category of software you're gathering information about.
New categories can be added as necessary.
=head2 Utility Methods
Once you've decided on the proper category, you can start implementing your
App::Info concrete subclass. As you do so, take advantage of App::Info::Util,
wherein I've tried to encapsulate common functionality to make subclassing
easier. I found that most of what I was doing repetitively was looking for
files and directories, and searching through files. Thus, App::Info::Util
subclasses L<File::Spec|File::Spec> in order to offer easy access to
commonly-used methods from that class, e.g., C<path()>. Plus, it has several
of its own methods to assist you in finding files and directories in lists of
files and directories, as well as methods for searching through files and
returning the values found in those files. See
L<App::Info::Util|App::Info::Util> for more information, and the App::Info
subclasses in this distribution for usage examples.
I recommend the use of a package-scoped lexical App::Info::Util object. That
way it's nice and handy when you need to carry out common tasks. If you find
you're doing something over and over that's not already addressed by an
App::Info::Util method, consider submitting a patch to App::Info::Util to add
the functionality you need.
=head2 Events
Use the methods described below to trigger events. Events are designed to
provide a simple way for App::Info subclass developers to send status messages
and errors, to confirm data values, and to request a value when the class
cannot determine a value itself. Events may optionally be handled by module
users who assign App::Info::Handler subclass objects to your App::Info
subclass object using the event handling methods described in the L<"Event
Handler Object Methods"> section.
=cut
##############################################################################
# This code reference is used by the event methods to manage the stack of
# event handlers that may be available to handle each of the events.
my $handler = sub {
my ($self, $meth, $params) = @_;
# Sanity check. We really want to keep control over this.
Carp::croak("Cannot call protected method $meth()")
unless UNIVERSAL::isa($self, scalar caller(1));
# Create the request object.
$params->{type} ||= $meth;
my $req = App::Info::Request->new(%$params);
# Do the deed. The ultimate handling handler may die.
foreach my $eh (@{$self->{"on_$meth"}}) {
last if $eh->handler($req);
}
# Return the request.
return $req;
};
##############################################################################
=head3 info
$self->info(@message);
Use this method to display status messages for the user. You may wish to use
it to inform users that you're searching for a particular file, or attempting
to parse a file or some other resource for the data you need. For example, a
common use might be in the object constructor: generally, when an App::Info
object is created, some important initial piece of information is being
sought, such as an executable file. That file may be in one of many locations,
so it makes sense to let the user know that you're looking for it:
$self->info("Searching for executable");
Note that, due to the nature of App::Info event handlers, your informational
message may be used or displayed any number of ways, or indeed not at all (as
is the default behavior).
The C<@message> will be joined into a single string and stored in the
C<message> attribute of the App::Info::Request object passed to info event
handlers.
=cut
sub info {
my $self = shift;
# Execute the handler sequence.
my $req = $handler->($self, 'info', { message => join '', @_ });
}
##############################################################################
=head3 error
$self->error(@error);
Use this method to inform the user that something unexpected has happened. An
example might be when you invoke another program to parse its output, but it's
output isn't what you expected:
$self->error("Unable to parse version from `/bin/myapp -c`");
As with all events, keep in mind that error events may be handled in any
number of ways, or not at all.
( run in 1.249 second using v1.01-cache-2.11-cpan-fe3c2283af0 )