Role-Basic

INSTALLATION

To install this module, run the following commands:

   perl Build.PL
   ./Build
   ./Build test
   ./Build install

If you prefer a Makefile.PL:

   perl Makefile.PL
   make
   make test
   make install

SUPPORT AND DOCUMENTATION

After installing, you can find documentation for this module with the
perldoc command.

   perldoc Role::Basic

NAME
   Role::Basic - Just roles. Nothing else.

VERSION
   Version 0.01

SYNOPSIS
   In a role:

       package Does::Serialize::AsYAML;
       use Role::Basic;
       use YAML::Syck;
       requires 'as_hash';

       sub serialize {
           my $self = shift;
           return Dump( $self->as_hash );
       }

       1;

   In your class:

       package My::Class;
       use Role::Basic 'with';

       with qw(
           Does::Serialize::AsYAML
       );

       sub as_hash { ... } # because the role requires it

DESCRIPTION
   Sometimes you want roles. You're not sure about Moose, Mouse, Moo and
   what *was* that damned Squirrel thing anyway? Then there's Class::Trait,
   but it has a funky syntax and the maintainer's deprecated it in favor of
   Moose::Role and you really don't care that it handles overloading,
   instance application or has a workaround for the SUPER:: bug. You think
   a meta-object protocol sounds nifty, but you don't understand it. Maybe
   you're not sure you want the syntactic sugar for object declaration.
   Maybe you've convinced your colleagues that roles are a good idea but
   they're leery of dragging in Moose (your author has had this happen more
   than once and heard of others making the same complaint). Sometimes you
   just want good old-fashioned roles which let you separate class
   responsibility from code reuse.

   Whatever your reasons, this is the module you're looking for. It only
   provides roles and its major design goals are safety and simplicity. It
   also aims to be a *subset* of Moose::Role behavior so that when/if
   you're ready to upgrade, there will be minimal pain.

DECLARING A ROLE
   To declare the current package as a role, simply add the following line
   to the package:

       use Role::Basic;

   You can then use "with" to consume other roles and "requires" to list
   the methods this role requires. Note that the *only* methods the role
   will provide are methods declared directly in the role or consumed from
   other roles. Thus:

       package My::Role;
       use Role::Basic;
       use List::Util 'sum'; # this will not be provided by the role
       with 'Some::Other::Role'; # any methods from this role will be provided

       sub some_method {...} # this will be provided by the role

CONSUMING ROLES
   To declare the current package as a class that will use roles, simply
   add the following line to the package:

       use Role::Basic 'with';

   Just as with Moose, you can have "-aliases" and list "-excludes".

EXPORT
   Both roles and classes will receive the following methods:

   * "with"
       "with" accepts a list and may only be called once per role or class.
       This is because calling it multiple times removes composition
       safety. Just as with Moose::Role, any class may also have "-aliases"
       or "-excludes".

           package My::Class;
           use Role::Basic 'with';

           with 'Does::Serialize::AsYAML' => { -aliases => { serialize => 'as_yaml' } };

       And later:

           print $object->as_yaml;

   * "DOES"
       Returns true if the class or role consumes a role of the given name:

        if ( $class->DOES('Does::Serialize::AsYAML') ) {
           ...
        }

   Further, if you're a role, you can also specify methods you require:

   * "requires"
           package Some::Role;
           use Role::Basic;

           # roles can consume other roles
           with 'Another::Role';

           requires qw(
               first_method
               second_method
               another_method
           );

       In the example above, if "Another::Role" has methods it requires,
       they will be added to the requirements of "Some::Role".

DESIGN GOALS AND LIMITATIONS
   There are two overriding design goals for "Role::Basic": simplicity and
   safety. We make it a bit harder to shoot yourself in the foot and we aim
   to keep the code as simple as possible. Feature requests are welcomed,
   but will not be acted upon if they violate either of these two design
   goals.

   Thus, if you need something which "Role::Basic" does not support, you're
   strongly encouraged to consider Moose or Mouse.

   The following list details the outcomes of this module's goals.

   * Basic role support
       This includes composing into your class, composing roles from other
       roles, roles declaring requirements and conflict resolution.

   * Moose-like syntax
       To ease migration difficulties, we use a Moose-like syntax. If you
       wish to upgrade to Moose later, or you find that others on your
       project are already familiar with Moose, this should make
       "Role::Basic" easier to learn.

   * No handling of SUPER:: bug
       A well-known bug in OO Perl is that a SUPER:: method is invoked
       against the class its declared in, not against the class of the
       invocant. Handling this properly generally involves eval'ing a
       method directly into the correct package:

           eval <<"END_METHOD";
           package $some_package;

           sub some_method { ... }
           END_METHOD

       Or using a different method resolution order (MRO) such as with
       Class::C3 or friends. We alert you to this limitation but make no
       attempt to address it. We consider this a feature because roles
       should not know or care how they are composed and probably should
       not know if a superclass exists. This helps to keep this module
       simple, a primary design goal.

   * Composition Safety
       In addition to the normal conflict resolution, only one "with"
       statement is allowed:

           package Foo;
           use Role::Basic;
           with 'Some::Role';
           with 'Another::Role'; # boom!

       This is because when you have more than one "with" statement, the
       latter will ignore conflicts with the first. We could work around
       this, but this would be significantly different from the behavior of
       Moose.

   * Override Safety
       By default, we aim to behave like Moose::Role. This means that if a
       class consuming a role has a method with the same name the role
       provides, the class *silently* wins. This has been a somewhat
       contentious issue in the "Moose" community and the "silent"
       behaviour has won. However, there are those who prefer that they
       don't have their methods silently ignored. We provide two optional
       environment variables to handle this:

           $ENV{PERL_ROLE_OVERRIDE_WARN}
           $ENV{PERL_ROLE_OVERRIDE_DIE}

       If you prefer, you can set one of those to true and a class
       overridding a role's method will "warn" or "die", as appropriate. As
       you might expect, you can handle this with normal role behaviour or
       exclusion or aliasing.

           package My::Class;
           use Role::Basic 'with';
           with 'My::Role' => { -excludes => 'conflicting_method' };

       From your author's email exchanges with the authors of the original
       traits paper (referenced here with permission), the "class silently
       wins" behaviour was not intended. About this, Dr. Andrew P. Black
       wrote the following:

           Yes, it is really important that a programmer can see clearly when a trait
           method is being overridden -- just as it is important that it is clear
           when an inherited method is being overridden.

           In Smalltalk, where a program is viewed as a graph of objects, the obvious
           solution to this problem is to provide an adequate tool to show the
           programmer interesting properties of the program.  The original traits
           browser did this for Smalltalk; the reason that we implemented it is that
           traits were really NOT a good idea (that is,they were not very usable or
           maintainable) without it.  Since then, the same sort of "virtual
           protocols" have been built into the browser for other properties, like
           "overridden methods".

       Note that those are provided as environment variables and not as
       syntax in the code itself to help keep the code closer to the Moose
       syntax.

   * No instance application
       "Role::Basic" does not support applying roles to object instances.
       This may change in the future.

   * No method modifiers
       These have been especially problematic. Consider a "before" modifier
       which multiplies a value by 2 and another before modifier which
       divides a value by 3. The order in which those modifiers are applied
       becomes extremely important. and role-consumption is no longer
       entirely declarative, but becomes partially procedural. This causes
       enough problems that on Sep 14, 2010 on the Moose mailing list,
       Stevan Little wrote:

           I totally agree [with the described application order problems], and if I
           had to do it over again, I would not have allowed method modifiers in
           roles. They ruin the unordered-ness of roles and bring about edge cases
           like this that are not so easily solved.

       Thus, "Role::Basic" does not and *will not* support method
       modifiers. If you need them, consider Moose.

AUTHOR
   Curtis 'Ovid' Poe, "<ovid at cpan.org>"

BUGS
   Please report any bugs or feature requests to "bug-role-basic at
   rt.cpan.org", or through the web interface at
   <http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Role-Basic>. I will be
   notified, and then you'll automatically be notified of progress on your
   bug as I make changes.

SUPPORT
   You can find documentation for this module with the perldoc command.

       perldoc Role::Basic

   You can also look for information at:

   * RT: CPAN's request tracker
       <http://rt.cpan.org/NoAuth/Bugs.html?Dist=Role-Basic>

   * AnnoCPAN: Annotated CPAN documentation
       <http://annocpan.org/dist/Role-Basic>

   * CPAN Ratings
       <http://cpanratings.perl.org/d/Role-Basic>

   * Search CPAN
       <http://search.cpan.org/dist/Role-Basic/>

ACKNOWLEDGEMENTS
LICENSE AND COPYRIGHT
   Copyright 2010 Curtis 'Ovid' Poe.

   This program is free software; you can redistribute it and/or modify it
   under the terms of either: the GNU General Public License as published
   by the Free Software Foundation; or the Artistic License.

   See http://dev.perl.org/licenses/ for more information.