What 'Modern Perl' Means
Modern Perl refers to a set of community-established conventions for writing Perl 5 code that avoids the pitfalls of the language's more permissive early defaults. It is not a different language version; it is a discipline. The foundation is always the same two pragmas at the top of every file: use strict and use warnings. strict forbids implicit global variables and requires every variable to be declared with my, catching typos like $counter versus $couner at compile time instead of letting them silently create a new global. warnings surfaces suspicious behavior such as using an undefined value in a numeric comparison. Beyond these pragmas, modern Perl also means preferring lexical scoping, using Perl::Critic for static analysis, and reaching for well-maintained CPAN modules like Moose, Moo, or Path::Tiny instead of reinventing object systems or file-path handling by hand.
Cricket analogy: use strict and use warnings are like a batter always wearing a helmet and pads before facing a fast bowler like Jasprit Bumrah, mandatory safety gear that catches dangerous mistakes before they become match-ending.
Lexical Scoping and Subroutine Design
Modern Perl code avoids package-global variables in favor of lexically scoped variables declared with my, which are visible only within the enclosing block. This dramatically reduces action-at-a-distance bugs where one part of a large script accidentally mutates state used elsewhere. Subroutines should validate their arguments explicitly rather than relying on the historical @_ array implicitly; a common idiom is my ($self, $args) = @_; at the top of a method, or using named-argument hashes for functions with more than two or three parameters. Return values should be explicit -- relying on the value of the last evaluated expression is legal Perl but reduces clarity, so an explicit return statement is preferred in anything beyond a trivial one-liner. Modules should also declare a clear public interface using Exporter or, in object-oriented code, by keeping internal helper methods prefixed with an underscore convention to signal they are private.
Cricket analogy: Lexical scoping is like a fielding captain assigning specific catching zones so cover and mid-wicket never both chase the same ball, avoiding the confusion of shared responsibility.
Modern Object Systems: Moo and Moose
Perl's built-in object system, bless-based hash references, is powerful but low-level: you must hand-write accessors, type checking, and constructors. Modern Perl code almost always reaches for Moose (feature-rich but heavier) or Moo (a lighter-weight subset with faster startup) to get declarative attributes, automatic accessor generation, type constraints, and role-based composition (similar to mixins/interfaces) for free. A Moo class declares attributes with the has keyword, specifying options like is => 'ro' for read-only or is => 'rw' for read-write, and isa => 'Int' for basic type checking. This eliminates entire categories of boilerplate bugs, such as forgetting to write an accessor or mismatching a constructor argument name, and it makes intent immediately visible to anyone reading the class definition, which is a major win for long-term maintainability.
Cricket analogy: Hand-writing bless-based accessors is like a groundskeeper manually rolling and marking the pitch by hand, while Moo/Moose is like modern drop-in curator equipment that produces a consistent, error-free surface every time.
Static Analysis and Style
Perl::Critic, based on Damian Conway's book Perl Best Practices, statically analyzes source code against a configurable rule set (organized into severity levels 1 through 5) and flags issues like using the two-argument form of open, missing use strict, or overly complex regular expressions. Teams typically run it as part of continuous integration alongside perltidy, a formatter that enforces consistent indentation, brace placement, and line wrapping so that diffs in code review stay focused on logic changes rather than whitespace noise. Combined with a .perlcriticrc configuration file checked into the repository, this gives a team the same kind of automated style enforcement that black provides for Python or gofmt provides for Go, removing bikeshedding from code review entirely.
Cricket analogy: Perl::Critic is like the third umpire reviewing every delivery against a fixed rulebook, catching no-balls and overstepping that the on-field umpire might miss in real time.
The single highest-leverage habit in modern Perl is simply starting every script and module with 'use strict; use warnings;' -- studies of legacy Perl codebases consistently show that the vast majority of runtime surprises trace back to code written without these two pragmas enabled.
Avoid indirect object syntax (e.g., 'my $obj = new ClassName;') -- it is ambiguous to the parser and can silently call the wrong function if a subroutine named 'new' exists elsewhere in scope. Always use the explicit form: 'my $obj = ClassName->new;'.
package User;
use Moo;
use Types::Standard qw(Str Int);
has name => (is => 'ro', isa => Str, required => 1);
has email => (is => 'rw', isa => Str, required => 1);
has age => (is => 'rw', isa => Int, default => 0);
sub greet {
my ($self) = @_;
return sprintf("Hello, %s! You are %d years old.", $self->name, $self->age);
}
1;
# usage
# my $user = User->new(name => 'Asha', email => 'asha\@example.com', age => 29);
# print $user->greet, "\n";- Always start files with use strict and use warnings to catch typos and unsafe behavior at compile time.
- Prefer lexically scoped variables (my) over package globals to avoid action-at-a-distance bugs.
- Validate subroutine arguments explicitly and use named-argument hashes for functions with several parameters.
- Use Moo or Moose instead of hand-rolled bless-based objects for declarative attributes and type constraints.
- Avoid indirect object syntax; always call constructors as ClassName->new.
- Enforce consistent style with perltidy and catch anti-patterns with Perl::Critic in CI.
- Use explicit return statements in subroutines beyond trivial one-liners for clarity.
Practice what you learned
1. What is the primary purpose of 'use strict' in Perl?
2. Which keyword is used in Moo to declare a class attribute?
3. What does Perl::Critic use as its foundational rule reference?
4. Why is indirect object syntax like 'new ClassName' discouraged?
5. What tool is commonly paired with Perl::Critic to enforce consistent code formatting?
Was this page helpful?
You May Also Like
Perl vs Python
A practical comparison of Perl and Python covering syntax philosophy, text processing, and ecosystem tooling to help you choose the right tool for a scripting task.
Perl Quick Reference
A condensed reference covering Perl's core syntax, data structures, regular expressions, and common idioms for fast lookup while coding.
Building a Log Parser in Perl
A hands-on walkthrough of building a robust Perl log parser that reads, matches, aggregates, and reports on structured log data using core Perl idioms.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics