Provided by: librole-basic-perl_0.16-1_all bug

NAME

       Role::Basic::Philosophy - Why Role::Basic exists.

RATIONALE

       Note: the words "trait" and "role" will be used interchangeably throughout this documentation.

       After years of using roles, your author has found that many people would be happy to use roles but are
       not willing/comfortable with using Moose.  This module implements roles and nothing else. It does so in a
       (relatively) simple bit of code.  However, you should be aware that there are some differences between
       Role::Basic and Moose::Role.

       Moose is a fantastic technology and your author is quite happy with it. He urges you to check it out and
       perhaps even consider Role::Basic a "stepping-stone" to Moose.  However, after an informal poll with many
       respondents replying on blogs.perl.org, Twitter, Facebook and private email unanimously saying they
       wanted this module for roles and not as a stepping-stone to Moose, your author took the liberty of
       deciding to implement traits in a rather faithful fashion, rather than strictly adhere to the design of
       Moose::Role.  For areas where we differ, Role::Basic intends to be more restrictive when syntax is the
       same. This allows an easier migration to Moose::Role when the time is right. Otherwise, Role::Basic will
       offer a different syntax to avoid confusion.

TRAITS

       As most of you probably know, roles are the Perl implmentation of traits as described in
       <http://scg.unibe.ch/research/traits/>.  (The name "role" was chosen because "trait" was already used in
       Perl 6.)  In particular, we direct you to two papers, both of which are easy to read:

       •   <http://scg.unibe.ch/scgbib?_s=tgXJjGrs0380ejY6&_k=Swgdwx_C&query=nathanael+traits+composable+units+ecoop&display=abstract&_n&19>

           The seminal "traits paper" which much of the documentation refers to.

       •   <http://scg.unibe.ch/scgbib?_s=tgXJjGrs0380ejY6&_k=Swgdwx_C&query=traits+the+formal+model&display=abstract&_n&23>

           "Traits: The Formal Model".

           While  less well-known, this relatively easy to read paper outlines the mathematical underpinnings of
           traits and explains several design decisions taken here.

       It is important to refer back to those papers  because  Role::Basic  attempts  to  implements  traits  as
       described  in  the  research, whereas Moose::Role attempts to implement something very similar to traits,
       but with more of a "Perlish" feel.  This is not intended as a criticism of  Moose::Role,  but  merely  an
       attempt to alert the reader to key differences.

   The Basics
       Roles are simply bundles of behavior which classes may use. If you have two completely unrelated classes,
       your  code  may  still  require  each  of  them to serialize themselves as JSON even though neither class
       naturally has anything to do with JSON (for example, "Person" and "Order" classes).  There are  a  number
       of  approaches  to  this problem but if you're here I'll skip the explanation and assume that you already
       understand roles and would like to know why we don't follow the Moose::Role specification.

       As you already probably know, roles allow you to state that your class "DOES" some behaviour, and  allows
       you  to  exclude  or  alias bits and pieces of the roles you're including.  The original specification of
       traits made it clear that this was to be done in such a fashion that no matter how you grouped the traits
       or in which order you used them, the outcome behavior would be the same. That's why we  have  subtle  but
       forward-compatible differences with Moose::Role.

       Commutative

       The   formal   model   (<http://scg.unibe.ch/archive/papers/Scha02cTraitsModel.pdf>)  states  that  trait
       composition must be commutative (section 3.4, proposition 1).  This means that:

           (A + B) = (B + A)

       In other words, it should not matter what order you compose the traits in. It is  well  known  that  with
       both  inheritance  and  mixins, this does not hold (making refactoring a dicey proposition at times), but
       when   method   modifiers   are   used   with    Moose::Role,    the    same    issues    arises    (from
       <http://blogs.perl.org/users/ovid/2010/12/rolebasic---when-you-only-want-roles.html>):

           {
               package Some::Role;
               use Moose::Role;
               requires qw(some_method);

               before some_method => sub {
                   my $self = shift;
                   $self->some_number( $self->some_number + 2 );
               };
           }
           {
               package Another::Role;
               use Moose::Role;
               requires qw(some_method);

               before some_method => sub {
                   my $self = shift;
                   $self->some_number( $self->some_number / 2 );
               };
           }
           {
               package Some::Class;
               use Moose;
               my @roles =
                 int( rand(2) )
                 ? qw(Another::Role Some::Role)
                 : qw(Some::Role Another::Role);
               with @roles;

               has some_number => ( is => 'rw', isa => 'Num' );
               sub some_method { print shift->some_number, $/ }
           }
           my $o = Some::Class->new( { some_number => 7 } );
           $o->some_method;

       If  you  run  this  code,  it  might  print  4.5,  but  it  might  print 5.5. As with mixins and multiple
       inheritance, you have no way of knowing the exact behaviour which will be exhibited short of running  the
       code.  No  introspection  will help. This is not an issue with Role::Basic because we do not allow method
       modifiers.  If you think you need them, please consider Moose.

       Associative

       The  formal  model  (<http://scg.unibe.ch/archive/papers/Scha02cTraitsModel.pdf>)   states   that   trait
       composition must be associative (section 3.4, proposition 1).  This means that:

           (A + B) + C = A + (B + C)

       Moose  is associative if and only if you do not have multiple methods with the same name.  In Moose, if a
       role providing method M consumes one other role which also provides method M, we have a conflict:

           package Some::Role;
           use Moose::Role;
           sub bar { __PACKAGE__ }

           package Some::Other::Role;
           use Moose::Role;
           with 'Some::Role';
           sub bar { __PACKAGE__ }

           package Some::Class;
           use Moose;
           with 'Some::Other::Role';

           package main;
           my $o = Some::Class->new;
           print $o->bar;

       However, if the role consumes two or more other roles which provide the same  method,  we  don't  have  a
       conflict:

           package Some::Role;
           use Moose::Role;
           sub bar { __PACKAGE__ }

           package Some::Other::Role;
           use Moose::Role;
           sub bar { __PACKAGE__ }

           package Another::Role;
           use Moose::Role;
           with qw(Some::Role Some::Other::Role);
           sub bar { __PACKAGE__ }

           package Some::Class;
           use Moose;
           with 'Another::Role';

           package main;
           my $o = Some::Class->new;
           print $o->bar;

       This is because, in Moose, when you have two or more roles consumed, any conflicting methods are excluded
       and considered to be requirements.

       See        "Moose::Role       composition       edge       cases"       for       more       explanation:
       <http://search.cpan.org/~drolsky/Moose-1.21/lib/Moose/Spec/Role.pod#Composition_Edge_Cases>.

       This makes roles easy to use at times, but it means that the following three  groups  of  roles  are  not
       guaranteed to provide the same behavior:

        RoleA does RoleB, RoleC
        RoleB does RoleA, RoleC
        RoleC does RoleA, RoleB

       Further,  you  as  a  developer have no way of knowing that we have had methods silently excluded without
       reading all of the code.

       For Role::Basic there are no edge cases. If "RoleA", "RoleB", and "RoleC" all provide method M,  you  are
       guaranteed  to  get  a  conflict  at  composition  time  and  must specifically address the problem. This
       addresses the associative issue because strictly speaking,  a  trait  is  merely  a  bundle  of  services
       provided,  not  its name.  Thus, a trait with its "foo" method excluded is not the same as itself without
       the "foo" method excluded.

       Benefits of associative and commutative behaviour

       While we recognize that not everyone will be happy with the decisions  we  have  made,  we  have  several
       benefits here:

       •   We adhere to the formal definition of traits

       •   Ordering and grouping of traits does not alter their behavior

       •   We're forward-compatible with Moose::Role

CONCLUSION

       The  primary  goal  of  Role::Basic is to provide traits in a simple and safe manner. We are huge fans of
       Moose and Moose::Role and suggest that everyone check them out. The decision of  Moose::Role  to  deviate
       from the "associative" and "commutative" deviations from the original traits model is, in our experience,
       less  likely  to  occur  with  roles  than  with  mixins and inhertance, so please do not take this as an
       indictment, but rather in the spirit of TIMTOWTDI.

perl v5.40.1                                       2025-03-01                       Role::Basic::Philosophy(3pm)