Telephone +44(0)1524 64544
Email: info@shadowcat.co.uk

fpw-2012 - moo

Sat Dec 22 00:30:00 2012

Slides for the talk moo at fpw-2012

-

   ______
  < Moo! >
   ~~~~~~
          \   ^__^
           \  (oo)\______
              (__)\             )\/\
                  ||~~~~w |
                  ||           ||

-

Moose

-

<3

-

0.01 released
March 15, 2006

-

I started with
about ... 0.18

-

0.18 released
March 10, 2007

-

What is
Moose?

-

What is
Moose
to me?

-

The OO I
always knew
perl5 was
capable of

-

... but wasn't
good enough
to implement

-

Class::Accessor

-

Class::Accessor
Class::MakeMethods
Class::Base

-

Too many!

-

DBIx::Class::AccessorGroup
became
Class::Accessor::Grouped

-

Damian
wrote
Class::Std

-

... but
nobody
used it

-

One class
builder to
rule them all

-

Moose

-

Why did I
stop using
Moose?

-

I didn't.

-

Catalyst
is Moose

-

All Shadowcat's
clients are
using Moose

-

Moose
rocks

-

This is
all the 
Italians'
fault.

-

IPW
2009

-

Antiquated
Perl

-

Web::Simple

-

Targets:
usable as CGI

-

Targets:
usable as CGI
fast startup
no XS deps

-

Wrote my own
accessors

-

Wrote my own
constructor

-

Perling like
it's 1999

-

*GRUMBLE*

-

Multiple
projects
like this

-

Web::Simple
Data::Query
HTML::Zoom

-

Moose use
impedes
adoption

-

Mouse?

-

Can be
pure perl

-

Describes
itself as
"Moose minus
the antlers"

-

Well ...

-

It still
has a
metamodel

-

The antlers
are just
smaller

-

Mouse is
Moose--

-

Not what
I wanted

-

So I put
on the
hair shirt

-

Used no object
system at all
in my projects
for a year

-

IT
HURT

-

Method
modifiers

-

  before foo => sub {
    shift->do_before_foo;
  };

-

  sub foo {
    my $self = shift;
    $self->do_before_foo;
    $self->next::method(@_);
  }

-

  after foo => sub {
    shift->do_after_foo;
  };

-

  sub foo {
    my $self = shift;
    my @ret = wantarray
      ? $self->next::method(@_)
      : scalar $self->next::method(@_)
    $self->do_after_foo;
    return wantarray
      ? @ret
      : $ret[0];
  }

-

(and that fails
for void context)

-

Intelligent
accessors

-

  has foo => (
    is => 'ro',
    lazy => 1,
    builder => '_build_foo'
  );

-

  sub foo {
    my $self = shift;
    die "Readonly" if @_;
    unless (exists $self->{foo}) {
      $self->{foo} = $self->_build_foo;
    }
    return $self->{foo}
  }

-

Intelligent
constructors

-

  has foo => (is => 'ro', required => 1);
  has bar => (is => 'ro', default => sub { 0 });

-

  sub new {
    my $class = shift;
    my %args = @_ == 1 ? %{$_[0]} : @_;
    die "foo is required"
      unless exists $args{foo};
    $args{bar} = 0
      unless $args{bar};
    my %new;
    @new{qw(foo bar)} = @args{qw(foo bar)};
    bless (\%new, $class);
  }

-

Subclassing
gets even
worse ...

-

Runtime
role
application

-

  apply_all_roles($obj, @roles)

-

  my $new_class = ref($obj).'::__ANON__'.++$i;
  @{"${new_class}::ISA"} = ref($obj);
  eval "package ${new_class}; use $_" for @roles;
  bless($obj, $new_class);

-

ARGH

-

-

So ...

-

About two 
years ago

-

Working on
site in
New York

-

Bored at the
weekend

-

(I am useless
at being
a tourist)

-

Coffee.
Subway.

-

I hacked.
ribasushi
and frew
tested.

-

So, what did
we produce?

-

-

Accessor
generation

-

  has foo => (
    is => 'ro', lazy => 1,
    default => sub { 0 }
  );

-

Simple
sugar

-

Moose has
lazy_build

-

  has foo => (
    is => 'ro',
    lazy => 1,
    builder => '_build_foo',
    predicate => 'has_foo',
    clearer => 'clear_foo'
  );

-

Bit too
much.

-

  has foo => (
    is => 'ro',
    lazy => 1,
    builder => '_build_foo'
  );

-

  has foo => (
    is => 'lazy'
  );

-

Now available in Moose via
MooseX::AttributeShortcuts

-

Method
Modifiers

-

Class::Method::Modifiers

-

  before foo => sub {
  around bar => sub {
  after baz => sub {

-

Types?

-

No type
system

-

Lots of
arguing
about
Moose's

-

  has foo => (
    ...
    isa => sub {
      <pass check>
        or die "Not a valid thing"
    }
  );

-

MooX::Types::MooseLike

-

  use MooX::Types::MooseLike::Base qw(Str);

  has foo => (
    ...
    isa => Str,
  );

-

Moose:
  use strict;
  use warnings;

-

Moo:
  use strictures 1;

-

strictures?

-

  use strict;
  use warnings FATAL => 'all';

-

when run
from a
test ...

-

  use strict;
  use warnings FATAL => 'all';
  no indirect;
  no multidimensional;
  no bareword::filehandles;

-

Defaults designed
to save newbies
from themselves

-

Moose?

-

  use MyMooClass;
  ...
  require Moose;
  my $meta = MyMooClass->meta;

-

Moo pretends
to be Moose

-

No need for
Any::Moose

-

  package MyMooClass;
  ...
  with 'MyMooseRole';

-

  package MyMooseClass;
  ...
  with 'MyMooRole';

-

and
even
...

-

  package MyMooRole;
  ...
  with 'MyMouseRole';
  ...
  package MyMooseRole;
  ...
  with 'MyMooRole';

-

Moose
subclassing
Moo
subclassing
Moose
subclassing
Moo

-

Moo
subclassing
Moose
subclassing
Moo
subclassing
Mouse

-

Pure
perl

-

Class::XSAccessor
used to speed
things up

-

(later, we need to
steal the Mouse
accessor code)

-

No required
non-core XS

-

App::FatPacker

-

deployment
via ftp

-

deployment
via ftp
(bloody
germans)

-

Object::Remote

-

  my $obj = MyMooClass->new::on(
    $server # connects via ssh
                # and sends fatpacked
                # code to other host
  );

-

It works.

-

It works.
Try it.

-

"I'm not sure
if I should use
Moose for this?"

-

Use
Moo!

-

Use
Moo
*first*

-

Moose will
still be
there later

-

Users - #moose
Hacking - #web-simple

-

'Moo' is
60% of
'Moose'

-

Moo: "almost
but not quite
two thirds
of Moose"

-

Questions?

-

Thank You
IRC:mst
mst@shadowcat.co.uk
@shadowcat_mst