NAME
Role::Declare - declarative parameter and return type checking
SYNOPSIS
In the interface Role:
package My::Class::interface;
use Role::Declare;
use Types::Standard qw/:all/;
class_method create_object ( Str $name, Int $age ) : Return( InstanceOf['My::Class'] ) {
die "Age cannot be negative: $age" if $age < 0;
};
In the interface implementation:
package My::Class;
use Role::Declare::StrictWith;
with_strict 'My::Class::interface';
sub create_object { ... }
or:
package My::Class;
use Role::Tiny::With;
with 'My::Class::interface';
sub create_object { ... }
DESCRIPTION
Perl doesn't provide a way to describe an interface, much less validate its implementation. This module aims to fill that gap by providing an easy way to build a validation layer with subroutine attributes and Function::Parameters syntax.
How it works
Any package which uses Role::Declare becomes a role and receives a few keywords and attributes that generate method modifiers. This means any class which composes it will need to implement the listed methods (this will be enforced on composition). Method implementations will be affected by Class::MethodModifiers modifiers, which provide argument and return value type checking, as well as arbitrary assertions defined in the interface.
Having that validation layer on at all times introduces a performance penalty. It makes sense to keep it on during development and testing to catch bugs and remove it in production. Role::Declare::StrictWith provides a specialized version of Role::Tiny's with
function, which works only in test environments as defined by Devel::StrictMode.
A note about void context
Return type validation will never be triggered in void context. Even if a method unconditionally returns a value and a :Return attribute is used, void context calls will not be validated.
Lax mode
Role::Declare can be imported in lax mode:
use Role::Declare -lax;
this will disable argument count checks, similar to Function::Parameters :lax
tag. It will affect all exported keywords.
WARNING: This functionality is experimental and subject to abrupt changes.
EXPORTS
The following are exported into the callers namespace:
method
method $method ( $Type $foo, $Type $bar ) { ... }
A method declaration following the syntax of Function::Parameters - a list of parameters that can have type constraints, like those from Type::Tiny. $self
will be automatically provided.
The body can contain any checks that need to be done on the arguments before the method is executed, it will not overwrite the method itself.
class_method
class_method $method ( $Type $foo, $Type $bar ) { ... }
Like method, but instead of $self
generates a $class
variable, which must be of the type ClassName
, from Types::Standard.
instance_method
instance_method $method ( $Type $foo, $Type $bar ) { ... }
Like method, but requries $self
to be an Object
from Types::Standard.
:Return
This attribute can be used along with method, instance_method or class_method to add return value validation in scalar context (see :ReturnList for list context). It takes a single Type::Tiny constraint as an argument.
class_method $method ( $Type $foo, $Type $bar ) : Return( $Type ) { ... }
:ReturnMaybe
Same as :Return but allows undef
.
:ReturnList
Similar to :Return but gets triggered by list context returns. It's arguments are the same as for ArrayRef constraint from Type::Tiny.
class_method $method ( $Type $foo, $Type $bar ) : ReturnList( $Type ) { ... }
:ReturnMaybeList
Same as :ReturnList but will always allow an empty list.
:ReturnTuple
Takes the same arguments as Tuple from Type::Tiny and checks list context return value in a similar fashion to :ReturnList.
:ReturnCycleTyple
Analogically to :ReturnTuple, applies the CycleTyple constraint to the returned list.
:ReturnHash
Requires a list of key-value pairs to be returned in list context. Takes a single argument, similar to :Return, which specifies the value type (key type is always Str
). For example, to require hash with Int
values:
class_method $method () : ReturnHash(Int) { ... }
Note: A hash reference is not an accepted return value in this case, use :Return(HashRef)
or :ReturnList(HashRef)
to check for it.
:ReturnSelf
Require the method to return its invocant.
:ReturnMaybeSelf
Same as :ReturnSelf but allow undef
.
:ReturnObject
Shorthand for :Return(Object)
.
:ReturnMaybeObject
Same as :ReturnObject but allows undef
.
:ReturnInstanceOf
Require the method to return an instance of the specified class. :ReturnInstanceOf($class)
is equivalent to :Return(InstanceOf[$class])
.
:ReturnMaybeInstanceOf
Same as :ReturnInstanceOf but allows undef
.
DIAGNOSTICS
A [list|scalar] hook for $method already exists
For each method at most two return validations can be set up - one for list and one for scalar context. This means, you can specify both :Return(...)
and :ReturnList(...)
for a method but you can't use :ReturnMaybeList
and :ReturnList
at the same time.
Only a single constraint is supported
A :Return
attribute should have a single argument - a Types::Standard constraint. If you want to test a method for multiple different types, see Type::Tiny::Union.
List constraint not defined
A :ReturnList
or :ReturnMaybeList
was used without arguments, see ArrayRef
in Types::Standard for supported arguments.
AUTHOR
Szymon Nieznański <snieznanski@perceptyx.com>
LICENSE
'Role::Declare' is Copyright (C) 2020, Perceptyx Inc
This library is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0.
This package is distributed in the hope that it will be useful, but it is provided "as is" and without any express or implied warranties.
For details, see the full text of the license in the file LICENSE.