NAME

Evo::Comp

VERSION

version 0.0187

DESCRIPTION

Component-oriented programming

A new promising component-oriented programming concepts. Documentation will be available if someone will be willing to help write it.

Why not OO and Moose like?

The most problems with Moose like modules is with initialization. Let's take a look:

package My::Moose;
use Moose;
has foo => is =>'rw';

package main;
my $obj = My::Moose->new(fo => 3);
print $obj->foo;

As you can see, we passed fo instead of foo, and Moose silently ignored it. You should write a huge amout of extra tests to pervent such errors.

Also traditional OO programming suffers the fragile base class problems (use Google). To solve it, component oriented Evo::Comp introduces flexible component roles Evo::Comp::Role.

So I decided to write all the stuff and name it component oriented programming. More explanation will be written later

SYNOPSYS

package main;
use Evo;

{

  package My::Human;
  use Evo '-Comp *';

  has 'name' => 'unnamed';
  has 'gender', is => 'ro', required => 1;
  has age => check => sub($v) { $v >= 18 };
}

my $alex = My::Human::new(gender => 'male');

# default value "unnamed"
say $alex->name;

# fluent design
$alex->name('Alex')->age(18);
say $alex->name, ': ', $alex->age;

# will die, gender is required
My::Human::new();

# will die, age must be >= 18
My::Human::new(age => 17, gender => 'male');
My::Human::new()->age(17, gender => 'male');

Usage

creating component

Describe a component, use need to import "*" to get it worked

package My::Comp;
use Evo '-Comp *';
has 'simple';

You don't need to call something like __PACKAGE__->meta->make_immutable unlike in Moose, components are fast enough by design.

new

important!!! Because Components reuse code horizontal, there's no need to pass the class string to every invocation of new (or Evo::Comp::Out/"init"). So instead of My::Class->new use My::Comp::new

my $foo = My::Comp::new(simple => 1);
my $foo2 = My::Comp::new();

We're protected from common mistakes, because constructor won't accept unknown attributes

my $foo = My::Comp::new(SiMple => 1);

Storage

The big advantage of component that it's not tied with implementation. The default uses hashes Evo::Comp::Hash, but you can easily switch for example to Evo::Comp::Out and use any other refs

Declaring attribute

package My::Foo;
use Evo '-Comp *';

has 'simple';
has 'short' => 'value';
has 'foo' => default => 'value', is => 'rw', check => sub {1};

Syntax

Simple rw attribute

has 'simple';
# has 'simple', is => 'rw';

Attribute with default value: short form

has 'short' => 'value';
# has 'short', default => 'value';

Full form

has 'foo' => default => 'value', is => 'rw', check => sub {1};

Options

is

Can be 'rw' or 'ro'; Unlike Perl6 is 'rw' by default

default

Attribute will be filled with this value if isn't provided to the new constructor You can't use references, but you can provide a coderef instead of value, in this case return value of an invocation of this function will be used.

has ref => sub { {} };
has ref => sub { {} };

lazy

Like default, but won't be filled at the first invocation, not in constructor.

required

Attributes with this options are required

check

You can provide function that will check passed value (via constuctor and changing), and if that function doesn't return true, an exception will be thrown.

has big => check => sub { shift > 10 };

You can also return (0, "CustomError") to provide more expressive explanation

package main;
use Evo;

{

  package My::Foo;
  use Evo '-Comp *';

  has big => check => sub($val) { $val > 10 ? 1 : (0, "not > 10"); };
};

my $foo = My::Foo::new(big => 11);

$foo->big(9);    # will die
my $bar = My::Foo::new(big => 9);    # will die

Code reuse

Instead of OO inheritance, wich suffers from fragile base class problem, Evo::Comp provides Evo::Comp::Role. This is a perfect choice for code reuse because of it's safety and flexibility. Look at Evo::Comp::Role for more information

with

Load role and install all methods and attributes to the component. Supports "shortcuts" in Evo

package Person;
use Evo '-Comp *';

with ':LoudHuman', ':Human';

Circular requirements can be solved by requiring roles in the single with. See "requires" in Evo::Comp::Role

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.