A small Perl project is easier to maintain when scripts, modules, and tests have clear homes.

project-layout Layout names communicate which files are entry points, reusable modules, and test files.

Project Layout

include_tests
project_layout.pl
Replay: real traced execution (multi-file project)
use strict;
use warnings;

my $include_tests = 1;
my @paths = ("bin/report", "lib/App/Report.pm", "README.md");
if ($include_tests) {
    push @paths, "t/report.t";
}

my $module_count = 0;
my $test_count = 0;
for my $path (@paths) {
    $module_count = $module_count + 1 if $path =~ /^lib\//;
    $test_count = $test_count + 1 if $path =~ /^t\//;
}

print "include_tests=$include_tests\n";
print "path_count=" . scalar(@paths) . "\n";
print "module_count=$module_count\n";
print "test_count=$test_count\n";
use strict;
use warnings;

my $include_tests = 0;
my @paths = ("bin/report", "lib/App/Report.pm", "README.md");
if ($include_tests) {
    push @paths, "t/report.t";
}

my $module_count = 0;
my $test_count = 0;
for my $path (@paths) {
    $module_count = $module_count + 1 if $path =~ /^lib\//;
    $test_count = $test_count + 1 if $path =~ /^t\//;
}

print "include_tests=$include_tests\n";
print "path_count=" . scalar(@paths) . "\n";
print "module_count=$module_count\n";
print "test_count=$test_count\n";
  1. $include_tests ← 1, @paths ← 3

    4my $include_tests→ 1 = 1; #@include_tests=05my @paths→ 3 = ("bin/report", "lib/App/Report.pm", "README.md");6if ($include_tests) {
  2. @paths ← 4

    5my @paths = ("bin/report", "lib/App/Report.pm", "README.md");6if ($include_tests1) {7    push @paths→ 4, "t/report.t";8}
  3. $module_count ← 0, $test_count ← 0

    10my $module_count→ 0 = 0;11my $test_count→ 0 = 0;12for my $path (@paths) {
  4. for my $path (@paths)

    pass 1 of 4
    11my $test_count = 0;12for my $pathbin/report (@paths4) {13    $module_count0 = $module_count + 1 if $pathbin/report =~ /^lib\//;14    $test_count0 = $test_count + 1 if $pathbin/report =~ /^t\//;15}
    All 4 passes — pass 1 is the card above
    pass$path$module_count$test_count
    1bin/report00
    2lib/App/Report.pm0 10
    3README.md10
    4t/report.t10 1
  5. print "include_tests=$include_tests ";

    17print "include_tests=$include_tests1\n";18print "path_count=" . scalar(@paths4) . "\n";19print "module_count=$module_count1\n";20print "test_count=$test_count1\n";
    outputinclude_tests=1
    path_count=4
    module_count=1
    test_count=1
  1. $include_tests ← 0, @paths ← 3, $module_count ← 0, $test_count ← 0

    4my $include_tests→ 0 = 0;5my @paths→ 3 = ("bin/report", "lib/App/Report.pm", "README.md");6if ($include_tests) {7    push @paths, "t/report.t";8}910my $module_count→ 0 = 0;11my $test_count→ 0 = 0;12for my $path (@paths) {
  2. for my $path (@paths)

    pass 1 of 3
    11my $test_count = 0;12for my $pathbin/report (@paths3) {13    $module_count0 = $module_count + 1 if $pathbin/report =~ /^lib\//;14    $test_count0 = $test_count + 1 if $pathbin/report =~ /^t\//;15}
    All 3 passes — pass 1 is the card above
    pass$path$module_count
    1bin/report0
    2lib/App/Report.pm0 1
    3README.md1
  3. print "include_tests=$include_tests ";

    17print "include_tests=$include_tests0\n";18print "path_count=" . scalar(@paths3) . "\n";19print "module_count=$module_count1\n";20print "test_count=$test_count0\n";
    outputinclude_tests=0
    path_count=3
    module_count=1
    test_count=0