Even for a curmudgeon like me who doesn’t make much use of object orientation, Moose offers something which supports my programming with types style: a degree of run-time type checking and the ability to create a range of convenience functions with very little code.
Say I have a person who makes a bunch of orders consisting of a bunch of items. My hashref might look something like this:
my $data = {
fred => {
orders => [
{
order_id => 'fred1',
items => [
{ description => 'roses' },
],
},
{
order_id => 'fred1',
items => [
{ description => 'one true ring' },
],
},
],
},
};
Then I’ll probably need a bunch of convenience functions to make sure I’m adding items to orders rather than people.
In Moose, including the type checking, that looks like:
Item
package Item;
use Moose;
has description => (
is => 'ro',
isa => 'Str',
);
no Moose;
__PACKAGE__->meta->make_immutable;
Order
package Order;
use Moose;
has order_id => (
is => 'ro',
isa => 'Str',
required => 1,
);
has items => (
is => 'rw',
isa => 'ArrayRef[Item]',
default => sub { [] },
traits => ['Array'],
handles => {
add_item => 'push',
get_items => 'elements',
},
);
no Moose;
__PACKAGE__->meta->make_immutable;
Person
package Person;
use Moose;
has name => (
is => 'ro',
isa => 'Str',
required => 1,
);
has orders =>
is => 'rw',
isa => 'ArrayRef[Order]',
default => sub { [] },
traits => ['Array'],
handles => {
add_order => 'push',
get_orders => 'elements',
},
no Moose;
__PACKAGE__->meta->make_immutable;
Adding an item as an order gives a nice error message:
my $fred = Person->new(name => 'fred');
my $item = Item->new(description => 'One true ring');
$fred->add_order($item);
$ perl moose-arrays.pl
A new member value for orders does not pass its type constraint because:
Validation failed for 'Order' with value Item=HASH(0x9ad3ec8)
(not isa Order) at moose-arrays.pl line 63
Moose ensures you pass an order to add_order(…).
my $order1 = Order->new(order_id => 'fred1');
my $item = Item->new(description => 'One true ring');
$order1->add_item($item);
$fred->add_order($order1);
my $order2 = Order->new(order_id => 'fred2');
$fred->add_order($order2);
use Data::Dumper;
print Dumper($fred);
$VAR1 = bless( {
'orders' => [
bless( {
'order_id' => 'fred1',
'items' => [
bless( {
'description' => 'One true ring'
}, 'Item' )
]
}, 'Order' ),
bless( {
'order_id' => 'fred2',
'items' => []
}, 'Order' )
],
'name' => 'fred'
}, 'Person' );
I like it when someone else has already written the code I would otherwise need to write myself.