oop intermediate

How to use MooseX::StrictConstructor to catch typos in Perl?

Question

How to use MooseX::StrictConstructor to catch typos in Perl?

MooseX::StrictConstructor is a Moose extension that helps catch bugs related to misspelled attributes during object construction in Perl's Moose-based classes. By default, Moose allows extra constructor arguments that do not correspond to declared attributes, which often results in silent typos or unexpected behavior. MooseX::StrictConstructor enforces strict checking and causes the constructor to die if unknown attributes are passed, helping you catch typos early.

What is MooseX::StrictConstructor?

MooseX::StrictConstructor is a Moose role that modifies the constructor behavior so it only accepts valid attributes declared in your class. If you try to construct an object with an attribute name that doesn’t exist, the constructor throws an exception immediately.

This fits nicely with Perl's "There's More Than One Way To Do It" (TMTOWTDI) philosophy, giving you an option to enforce stricter validation when working with Moose objects.

How to use MooseX::StrictConstructor

  • Install the module from CPAN if you don’t have it (cpanm MooseX::StrictConstructor or cpan MooseX::StrictConstructor).
  • In your Moose class, use the role MooseX::StrictConstructor.
  • Define your attributes as usual.
  • When creating an object, any typo in attribute names will cause the constructor to die with an error.

Example: Catching typos with MooseX::StrictConstructor

use strict;
use warnings;

{
    package Person;
    use Moose;
    use MooseX::StrictConstructor;

    has 'name' => (
        is  => 'ro',
        isa => 'Str',
        required => 1,
    );

    has 'age' => (
        is  => 'ro',
        isa => 'Int',
        required => 1,
    );
}

# Correct usage
my $person = Person->new(
    name => 'Alice',
    age  => 30,
);

print "Created person: ", $person->name, ", age ", $person->age, "\n";

# Typo in attribute name will cause error because of MooseX::StrictConstructor
eval {
    my $person2 = Person->new(
        name  => 'Bob',
        agee  => 25,    # typo here: should be 'age'
    );
};
if ($@) {
    print "Error caught: $@";
}

How It Works

  • The class Person consumes MooseX::StrictConstructor.
  • The constructor new strictly expects only name and age as keys.
  • When a typo like agee is present, the constructor dies with an error such as Found unknown attribute(s) passed to the constructor: agee.
  • The eval block demonstrates how you can catch this error and respond accordingly.

Version Notes and Pitfalls

  • MooseX::StrictConstructor works with Moose versions from around 2.00+ onwards (Perl 5.8+ generally).
  • If you override BUILDARGS in your class, be careful to support MooseX::StrictConstructor expectations to avoid false positives.
  • This extension only affects the new constructor, so other ways of object construction (like clone) are not checked.
  • Strict constructor checking improves code robustness, but for very large attribute sets, you might want to benchmark since the checks add a small overhead.

Summary

By using MooseX::StrictConstructor, you enforce strict attribute validation at object construction, catching misspelled or unexpected attributes early. This eliminates a common source of bugs in Moose-based object-oriented Perl code and improves maintainability, especially on large projects.

Verified Code

Executed in a sandbox to capture real output. • v5.34.1 • 184ms

Tip: edit code and use “Run (Browser)”. Server runs always execute the published, verified snippet.
STDOUT
Created person: Alice, age 30
Error caught: Attribute (age) is required at /System/Library/Perl/Extras/5.34/darwin-thread-multi-2level/Moose/Meta/Class.pm line 275
	Moose::Meta::Class::new_object('Moose::Meta::Class::__ANON__::SERIAL::1=HASH(0x12da20270)', 'HASH(0x138a9fba8)') called at /System/Library/Perl/Extras/5.34/MooseX/StrictConstructor/Trait/Class.pm line 17
	Class::MOP::Class:::around('CODE(0x12e9713a8)', 'Moose::Meta::Class::__ANON__::SERIAL::1=HASH(0x12da20270)', 'HASH(0x138a9fba8)') called at /System/Library/Perl/Extras/5.34/darwin-thread-multi-2level/Class/MOP/Method/Wrapped.pm line 164
	Moose::Meta::Class::__ANON__::SERIAL::1::_wrapped_new_object('Moose::Meta::Class::__ANON__::SERIAL::1=HASH(0x12da20270)', 'HASH(0x138a9fba8)') called at /System/Library/Perl/Extras/5.34/darwin-thread-multi-2level/Class/MOP/Method/Wrapped.pm line 95
	Moose::Meta::Class::__ANON__::SERIAL::1::new_object('Moose::Meta::Class::__ANON__::SERIAL::1=HASH(0x12da20270)', 'HASH(0x138a9fba8)') called at /System/Library/Perl/Extras/5.34/darwin-thread-multi-2level/Moose/Object.pm line 24
	Moose::Object::new('Person', 'name', 'Bob', 'agee', 25) called at - line 32
	eval {...} at - line 31
STDERR
(empty)

Was this helpful?

Related Questions