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

Evo::Comp::Role

VERSION

version 0.0187

DESCRIPTION

OO is considered an anti-pattern because it's hard to change base class and reuse the code written by other person (Fragile base class problem), and every refactoring makes OO applications low-tested or extra-tested. Component oriented programming doesn't have such weakness. It uses roles (like Moose's roles), or so called "mixins".

Because of that, Components are faster, simpler, and more reusable Also Roles can protect you from method and attributes clashing, because all methods and attributes will be installed into one file

I'll write an article about this late (maybe)

Here is a breaf overview

Building and using component roles

To share method, add Role tag. All attributes are shared automatically. In our case method upper_name and attribute name are provided by role.

    # Person/Human.pm
    package Person::Human;
    use Evo '-Comp::Role *';
    has 'name';
    sub upper_name : Role { uc shift->name }

And to use it in the component

    # Person.pm
    package Person;
    use Evo '-Comp *';

    with ':Human';    # same as "Person::Human"; reuse Person::Human code

See "with" in Evo::Comp.

shortcuts

Evo::Comp::Role supports shortcuts, here :Human in Person is resolved to Person::Human. This helps a lot during refactoring. See "shortcuts" in Evo for more information

storage agnostic

The good news are roles don't care what type of storage will be used by derived component (Evo::Comp::Hash, Evo::Comp::Out or others) - it will work. So you can do something like this:

  package Person;
  use Evo '-Comp *';
  with 'Person::Human';

  package PersonArray;
  use Evo '-Comp::Out *';
  with 'Person::Human';

  package main;
  use Evo;
  use Data::Dumper;
  my $person_hash = Person::new(name => 'foo');
  my $person_array = PersonArray::init([1, 2, 3], name => 'bar');

  # hash
  say Dumper $person_hash;

  # array
  say Dumper $person_array;

In the example above, Person is based on hashes, while PersonArray is based on arrays. They both use Person::Human role.

Let's separate Person::Human into 2 different roles;

    # Person/Human.pm
    package Person::Human;
    use Evo '-Comp::Role *';
    has 'name';

    # Person/LoudHuman.pm
    package Person::LoudHuman;
    use Evo '-Comp::Role *';

    requires 'name';
    sub upper_name : Role { uc shift->name }

    package Person;
    use Evo '-Comp *';

    with ':LoudHuman', ':Human';
    sub intro { say "My name is ", shift->upper_name }

Person::LoudHuman provides method upper_name. requires 'name', which is used by upper_name ensures that derivered class has this method or attribute. (attributes should be described before "with" in Evo::Comp, to solve circular requirements, include all roles in one "with" in Evo::Comp)

features

role_gen

Creates generator, very similar to "export_gen" in Evo::Export

role_proxy

  role_proxy 'My::Another', 'My::Another2';

Proxy attributes and methods from one role to another

role_methods

:Role attribute is preffered

requires

List method that should be available in component during role installation. If you require attribute, describe it before "with". If you have circular dependencies, load all roles in the single "with".

SYNOPSYS

  package main;
  use Evo;

  {

    package Person::Human;
    use Evo '-Comp::Role *; -Loaded';
    has 'name';
    sub upper_name : Role { uc shift->name }

    package Person;
    use Evo '-Comp *';

    with ':Human';    # same as "Person::Human"; reuse Person::Human code
    sub intro { say "My name is ", shift->upper_name }

  };

  my $alex = Person::new(name => 'alex');
  $alex->intro;

Evo::Loaded is only needed to copy-paste this examples into one file and run it. In the real life code, where every role has separate file, it's not neccessary

AUTHOR

alexbyk.com

COPYRIGHT AND LICENSE

This software is copyright (c) 2016 by alexbyk.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.