Perl is what's known as a weak typed language. Rather than having
separate data types for numbers, strings, and each types of object,
there's just one type - a scalar - that can be used to hold a number,
a string or a reference to an object. This has great advantages as
you can code your code to be a lot more flexible. For example in Java
you'd have to write a method for each of the possible arguments your
method can be passed. In Perl you could write one method that
automatically fills in default values for the majority of the arguments
and otherwise is complicit with the arguments - automatically converting
one type of object into another as needed.

It has a lot of disadvantages too. If you can't trust code to pass
your methods the right arguments (and if it's a public method then you
really shouldn't) then you have to check the data that was passed
though your parameters is valid - that you haven't been passed a string
where you expected a number, or an object of completely the wrong type.
Strongly typed languages of course will do all of this for you.

This kind of code is tedious for you to write, and it's the kind of
thing where you can make simple errors that introduce subtle bugs into
your code. This is where Params::Validate can be of use. It's an
automated tool that can be used to do a lot of checking for you - in
most cases enough.

One of the most common idioms for passing arguments to Perl methods is
the named parameter passing trick. This is where you shift off the
class or object, and then assign the rest of the arguments to a hash.

sub new
{
my $self = bless {}, shift;
my %args = @_

print STDERR "Creating '$args{age}' year old '$args{name}'\n"
if DEBUG;
...

return this;
}

sub stake
{
my $self = shift;
my %args = @_;

...
}

Okay, let's see what we can do with Params::Validate. For a start,
we want to ensure that our constructor always has a name, some skills,
and an age, and optionally they can pass in the hair colour they want.

We replace the @_ with a call to the subroutine validate that we
pass @_ and a hashref that contains the specification that we want
to validate @_ against. If validation fails, an exception will be
thrown. The above shows the most simple specification, where we
specify that our new slayer must have all three attributes. We can do
a little better than this by specifying a list of types that the data
must have by replacing the 1 with a specification hash for that
parameter. Pay attention to the fact that SCALAR and ARRAYREF
in the following example aren't strings - they're constants exported by
Params::Validate; Putting them in "" won't work.

But wait, what if we don't want to have to specify skills for every
new slayer? It's pretty much a given that each new slayer will have
the amazing ability to come up with crazy backchat during fights, so
we want to assign the skill of Bantering as standard if no skills
are passed. We can do that with the default option:

Now the skills are optional and the default will be used if no
argument is supplied. So now we can create a new slayer like so,
without having to specify any skills:

my $faith = Slayer->new(name => "Faith",
age => "17",);

Note that the default is only used when the parameters are omitted -
if you supply something that isn't up to spec the default won't be
used - an error will be thrown as usual. Now let's turn our attention
to the stake method. It takes two parameters, who our slayer is
staking, and what with.

But wait! We know Buffy can only stake Vampires. We'd better check
that $vampire was actually a Vampire object. And we'd better
check we're using a subclass of Stake (a Stake object, a
Stake::Broom, a Stake::Rake, etc) to do it with.

Hang on a moment though, Buffy can 'stake' Vampires with any old sharp
bit of wood. She can smash up chairs. So they don't really have to
be a subclass of Stake after all. Essentially all we want is an
object that supports the dust interface (i.e. any object that has a
dust method.) We can do that with the can test:

So you can see all these validations offer us the chance to check our
inputs with some inbuilt tests. But what happens if there's not a
test for our parameter? What happens if we want to make sure that
some fool hasn't written

my $slayer->new(name => "Kendra",
age => "seventeen");

Well, Param::Validate allows us to write extension tests with
callback facilities. This allows you to define subroutines that will
be called with the parameter that should return true if the parameter
passes.

And that's pretty much it. Of course, Params::Validate has a
whole section of code dedicated to dealing with positional rather than
named parameters that I haven't covered in this mini-tutorial. I'll leave
it as an exercise for the reader.