A program, to my mind, is basically code which does something. A module or class on its own doesn't do anything. It's not a program. You need a program to use them and do something. However, the problem which I see all too often is programs which try to do too much. As a result, when I wrote grepl, I did not want any logic in there which belong in the App::Grepl class. Though grepl is powerful and does a lot, here's the entire program:
#!/usr/local/bin/perl use strict; use warnings; use App::Grepl; use Pod::Usage 1.12; use Getopt::Long; GetOptions( "pattern=s" => \my $pattern, "search=s" => \my $lookfor, "warnings" => \my $warnings, "l" => \my $filename_only, 'h|help|?' => sub { pod2usage( { -verbose => 1 } ); exit }, 'H|man' => sub { pod2usage( { -verbose => 2 } ); exit }, ); $lookfor = [ split ',' => ( $lookfor || '' ) ]; $pattern ||= ''; my @search_in; if ( !@ARGV ) { @search_in = ( dir => '.' ); } elsif ( 1 == @ARGV && -d $ARGV[0] ) { @search_in = ( dir => $ARGV[0] ); } else { @search_in = ( files => [ @ARGV ] ); } my $grepl = App::Grepl->new( { look_for => $lookfor, pattern => $pattern, warnings => $warnings, filename_only => $filename_only, @search_in, } ); $grepl->search;
Now that's how you write a program. The only logic is processing command line arguments and passing them to the application.
Yes, the constructor is doing a lot, but even that's fairly easy to manage. I have about 96% test coverage and I'm not worried about having code in my program which is difficult to test (unlike in, say, runtests).