NAME
Momo,a simple oop module inspired from Mojo::Base and Moo.
SYNOPSIS
package Person;
use Momo;
has name => 'james'; # if not set,default set james
has [qw(age sex)];
sub new{
say "I'm a Person";
}
1;
DESCRIPTION
Why I want to write this module? If you heard about Moose or Moo,you know they are pretty module for perl object-oriented program. Compare with old style of perl5 object-oriented program:
package Foo;
BEGIN{
push @ISA,"Some::SuperClass";
} # or
use base 'Some::SuperClass';
sub new{
my $self = bless {} shift;
$self->{name} = shift;
$self->{age} = shift;
return $self;
}
sub some_method{
say "I'm some method";
}
1;
# invoke method as oop style
my $obj = Foo->new;
$obj->some_method;
In moose or moo,write like this:
package Foo;
use Moose; # or use Moo
extends 'SomeBaseClass' with 'role1','role2';
has x => ( is => 'rw',default => sub { {} },lazy => 1);
has y => ( is => 'ro',default => ref {} );
has z => ( is => 'rw',default => sub { { xx => 'yy'} },required => 1);
before method1 => sub {
.....
};
after method1 => sub {
};
around method1 => sub {
};
1;
It looks so amazing,everything works fine,Moose can give you vast powerful feature of perl Object-Oriented,the syntax sugars like 'extends','has','with'...etc are magic. On the other hand,you can override the attribute with has +x
,and also,with the role make it more inconceivable.
But,I still find some problem:
- the cumbersome syntax in
has
defined -
Every time when I type the
has
blabla,does this below is really I want?has ua=> ( is => 'rw',isa => 'LWP::UserAgent', default => sub { LWP::UserAgent->new },lazy => 1); # is => 'rw', over and over,lazy => 1, over and over,default,over and # over.... # It makes me creazy!
You know perl is a dynamically typed language,not like java ,c++,I think I don't need the feature,even I almost do not used this feature,I also write ruby and python,but I never see this.
- inherit some class of non Moose modules
-
In Moose or Moo,if you want to inherit a calss of non Moose style,all I know is to use MooseX::NonMoose;
package Term::VT102::NBased; use Moose; use MooseX::NonMoose; extends 'Term::VT102'; has [qw/x_base y_base/] => ( is => 'ro', isa => 'Int', default => 1, ); around x => sub { my $orig = shift; my $self = shift; $self->$orig(@_) + $self->x_base - 1; }; # ... (wrap other methods) no Moose; # no need to fiddle with inline_constructor here __PACKAGE__->meta->make_immutable; my $vt = Term::VT102::NBased->new(x_base => 0, y_base => 0);
or:
package Crawler::Event; use Moo; extends 'Object::Event','Moo::Object'; # explicit constructor sub new { my $class = shift; # call Mojo::UserAgent's constructor my $obj = $class->SUPER::new(@_); return $class->meta->new_object( # pass in the constructed object # using the special key __INSTANCE__ __INSTANCE__ => $obj, @_, # pass in the normal args ); } 1;
It looks so weird,this is just a simple object inherit,why I need to type so many code and install a Moosex module. Also,there is another way to fix this,use
deligation
package Website; use Moose; has 'uri' => ( is => 'ro', isa => 'URI', handles => { hostname => 'host', path => 'path', }, );
But I think this is more complex,if you lost some method of handles,when you run your code which just need to inherit LWP,then throw a error like:
Can't find this method
Oh my god,why I must do this?
- speed of runtime slowly
-
Although,Moo have make moose looks tidy and simple,at runtime,it still cost more time than old style of perl Object-Oriented program.
Here is the benchmark of Momo,Moose,Moo,hashref,bless hashref,each test create a object and access the attr,set the attr:
Benchmark: timing 1000000 iterations of blessed_hashref, hashref, momo, moo, moose... blessed_hashref: 1.60316 wallclock secs ( 1.60 usr + 0.00 sys = 1.60 CPU) @ 625000.00/s (n=1000000) hashref: 1.34393 wallclock secs ( 1.35 usr + 0.00 sys = 1.35 CPU) @ 740740.74/s (n=1000000) momo: 3.97532 wallclock secs ( 3.97 usr + 0.00 sys = 3.97 CPU) @ 251889.17/s (n=1000000) moo: 5.36459 wallclock secs ( 5.37 usr + 0.00 sys = 5.37 CPU) @ 186219.74/s (n=1000000) moose: 7.81556 wallclock secs ( 7.81 usr + 0.00 sys = 7.81 CPU) @ 128040.97/s (n=1000000) Rate moose moo momo blessed_hashref hashref moose 128041/s -- -31% -49% -80% -83% moo 186220/s 45% -- -26% -70% -75% momo 251889/s 97% 35% -- -60% -66% blessed_hashref 625000/s 388% 236% 148% -- -16% hashref 740741/s 479% 298% 194% 19% --
The result shows that Momo is faster than Moo,Moose.
When I develop mojo app,I found Mojo::Base
is so simple and light,fast speed, and I add some features like : role,method modifiers,everything works fine for me.
Anyway,if you hate all of these,try Momo,or you can keep working on Moose or Moo.
It's so simple:
package MomoStyle;
use Momo;
extends 'LWP::UserAgent'; #inherit LWP::UserAgent so easy
with 'Logger'; # does a logging role,same as moose's role
has name => 'momo';
has city => 'beijing';
has check => sub {
my $self = shift;
if( $name eq 'momo' ){
# do some stuff here
}
};
# if you need do some other thing,you can override new
sub new{
my $self = shift->SUPER::new(@_);
$self->agent("momo");
$self;
}
1;
FUNCTIONS
Momo exports the following functions
has
has 'name';
has [qw(name1 name2 name3)];
has name => 'foo';
has name => sub {...};
has [qw(name1 name2 name3)] => 'foo';
has [qw(name1 name2 name3)] => sub {...};
Create attributes for hash-based objects, just like the Moose has or Moo, but ignore the option of is
,isa
...
METHODS
Momo implements the following methods.
new
my $object = BaseSubClass->new;
my $object = BaseSubClass->new(name => 'value');
my $object = BaseSubClass->new({name => 'value'});
This base class provides a basic constructor for hash-based objects. You can pass it either a hash or a hash reference with attribute values.
attr
$object->attr('name');
BaseSubClass->attr('name');
BaseSubClass->attr([qw(name1 name2 name3)]);
BaseSubClass->attr(name => 'foo');
BaseSubClass->attr(name => sub {...});
BaseSubClass->attr([qw(name1 name2 name3)] => 'foo');
BaseSubClass->attr([qw(name1 name2 name3)] => sub {...});
Create attribute accessor for hash-based objects, an array reference can be used to create more than one at a time. Pass an optional second argument to set a default value, it should be a constant or a callback. The callback will be executed at accessor read time if there's no set value. Accessors can be chained, that means they return their invocant when they are called with an argument.
extends
use this to inherit a class,different with Moose's extends,you can extends any other module,what if they are blessed style module,
extends 'LWP::UserAgent';
extends 'BaseClass1','BaseClass2';
with
use this to does a role,about role you can check Moose::Role
extends 'Mojo::Lite';
with 'Some::Role';
1;
method_modifiers
Same as Moo and Moose,Momo support method modifiers in Class or Role:
package Role1;
use Momo::Role;
before some_method => sub { print "i'm before method" };
after some_method => sub { print "i'm after method" };
around some_method => sub { $_[1]->$_[0](@_) };
in class package:
package Cat;
use Momo;
before feed => sub { print "I want to eat some water" };
after feed => sub { print "after feed,I'm full" };
around feed => sub { print "I should eat what" };
sub feed { print "I want to feed ..." };
tap
$object = $object->tap(sub {...});
K combinator, tap into a method chain to perform operations on an object within the chain. The object will be the first argument passed to the callback and is also available as $_
.
DEBUGGING
You can set the MOMO_DEBUG
environment variable to get some advanced diagnostics information printed to STDERR
.
MOMO_DEBUG=1
SEE ALSO
Mojo::Base,Moo,Moose,Role::Tiny
TODO
BUGS
Any bugs just email yiming.jin@live.com
,or commit a issue on github: https://github.com/niumang/momo/issues
AUTHOR
舌尖上的牛氓 yiming.jin@live.com
QQ: 492003149
QQ-Group: 211685345
Site: http://perl-china.com
Copyright
Copyright (C) <2013>, <舌尖上的牛氓>.
This module is free software; you can redistribute it and/or modify it under the same terms as Perl 5.10.0. For more details, see the full text of the licenses in the directory LICENSES.
This program is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose.