Well, I was going to convert your code into a moose BUILDARGS method, but decided that I think the best approach along this line would be simply lazy-building. Of course, the advantage of the OP's approach is re-usability. The re-usability can be mostly recovered by moving the attributes to a role:
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->gende
+r;
return "Jane Doe" if $self->has_gender and "F" eq $self->gende
+r;
}
# ... 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.
+..
}
Though, hopefully you intend to use these methods only to provide (semi-sane) defaults when first/last/full are needed but not known - names are too complex for the above to be reliable generally.