Вячеслав Тихановский > Attribute-Contract-0.02 > Attribute::Contract

Download:
Attribute-Contract-0.02.tar.gz

Dependencies

Annotate this POD

CPAN RT

New  1
Open  0
View/Report Bugs
Module Version: 0.02   Source  

NAME ^

Attribute::Contract - Design by contract via Perl attributes

SYNOPSIS ^

    package Interface;
    use AttributeContract;

    sub do_smth :ContractRequires(VALUE, @ANY?) :ContractEnsures(VALUE) {
        ...;
    }

    package Implementation;
    use base 'Interface';
    use AttributeContract;

    sub do_smth {
        my $self = shift;
        my ($foo, @rest) = @_;

        return 1;
    }

    Implementaion->do_smth('hi', 'there'); # works

    Implementaion->do_smth();              # croaks!
    Implementaion->do_smth(sub {});        # croaks!

DESCRIPTION ^

Attribute::Contract by using Perl attributes allows you to specify contract (Design by Contract) for every method in your class. You can check incoming and outgoing values by specifying ContractRequires and ContractEnsures attributes.

It's the most useful for interfaces or abstract classes when you want to control whether your implementation follows the same interface and respects the Liskov substitution principle.

This module does not check the actual types like Str, Int etc, but the Perl data types like scalars, arrays, hashes, references and so on. When the type does not match a Carp's confess function will be called with detailed information like:

    0 param(s) passed, at least 1 param(s) is required

Why attributes? They feel and look natural and are applied during compile time.

TYPES

Scalar types

Greedy types

Types that eat all the elements. Can be specified at the end of the elements list for manual unpacking. @ stands for arrays and % stands for hashes. All the scalar types can be used to specify the types of the elements.

MULTIPLE VALUES

Use , when specifying several arguments.

    VALUE,ANY,REF(CODE),@VALUE

Which could mean something like:

    $object->method($foo, \@array, sub { ... }, 1, 2, 3);

ALTERNATIVES

Use | when specifying an alternative type.

    VALUE|REF(VALUE)

Which could mean something like:

    $object->method($foo);

or

    $object->method(\$foo);

Alternatives can be really deep, like this one:

    @(REF(HASH|CODE)|VALUE)

Which is an array of references to hash or code or simple value.

OPTIONAL VALUES

Use ? when specifying an optional value.

    VALUE,VALUE?

Which could mean something like:

    $object->method('foo');

or

    $object->method('foo', 'bar');

IMPLEMENTATION

Inheritance

By default all the contracts are inherited. Just don't forget to use Attribute::Contract in the derived class. But if no methods are override then even using this module is not needed.

Caching

During the compile time for every contract a Perl subroutine is built and evaled. If the methods share the same contract they use the same checking code reference. This speeds up the checking and saves some memory.

Error reporting

Errors are as specific as possible. On error you will get a meaningful message and a stack trace.

SWITCHING OFF

You can switch off contract checking by specifying an environment variable NO_ATTRIBUTE_CONTRACT.

DEVELOPMENT ^

Repository

    http://github.com/vti/attribute-contract

AUTHOR ^

Viacheslav Tykhanovskyi, vti@cpan.org.

COPYRIGHT AND LICENSE ^

Copyright (C) 2012, Viacheslav Tykhanovskyi

This program is free software, you can redistribute it and/or modify it under the terms of the Artistic License version 2.0.

syntax highlighting: