package HumanName; use Moose::Role; use re 'taint'; # Can use isa => first_name_type ... if you prefer for (qw/ first last full /) { has $_."_name => isa => "Str", lazy_build => 1, predicate => "has_${_}_name"; } sub _build_full_name { my $self = shift; if ($self->has_last_name and $self->has_first_name) { return join " ", $self->first_name, $self->last_name; } if ($self->does("Gender")) { return "John Doe" if $self->has_gender and "M" eq $self->gender; return "Jane Doe" if $self->has_gender and "F" eq $self->gender; } # ... whatever complex constructions we like die "Can not build full name"; } sub _build_first_name { my $self = shift; return (split /\s+/, $self->full_name)[0];# or more complex chain... } sub _build_last_name { my $self = shift; return (split /\s+/, $self->full_name)[1];# or more complex chain... }