The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

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.

: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.