Moops is sugar for writing object-oriented Perl. It provides similar syntax to MooseX::Declare and Stevan Little's p5-mop-redux. It's some glue between Moo, Type::Tiny, Function::Parameters and Try::Tiny, but for those occasions when you want the backing of a meta object protocol, allows you to easily swap Moose (or even Mouse) in place of Moo with very minimal changes.

Here's an example of a complete, usable class definition in Moops:

   use Moops;
   
   class Person :ro {
      has first_name => (isa => Str);
      has last_name  => (isa => Str);
   }

Note the :ro shortcut, to make attributes default to being read-only. Boilerplate code like use namespace::sweep and __PACKAGE__->meta->make_immutable can be omitted because Moops does that all for you.

Here's a more extensive example, showing off some other Moops features.

   class User extends Person using Moose :ro {
      use DateTime ();
      
      has password    => (isa => Str);
      has last_login  => (
         is      => 'rwp',
         isa     => InstanceOf['DateTime'],
         handles => { 'date_of_last_login' => 'date' },
      );
      
      method login ( Str $pw ) {
         return 0 if $pw ne $self->password;
         $self->_set_last_login( DateTime->now );
         return 1;
      }
   }

Moops goes to great lengths to smooth over the differences between Moo and Moose. Type constraints are taken from Types::Standard, so the same types will be available for attribute declarations and method signatures, no matter whether you're using Moo, Moose or Mouse. The Moo-specific is => 'rwp' is munged by MooseX::MungeHas into something Moose is capable of understanding.

Roles can be declared and used just as easily:

   role Breakable :rwp {
      has is_broken => (isa => Bool);
      after break () {
         $self->_set_is_broken(1);
      }
   }
   
   class Engine;
   
   class Car with Breakable {
      
      has engine    => (is => 'ro', isa => InstanceOf['Engine']);
      has is_moving => (is => 'rw', isa => Bool);
      
      method start () {
         return if $self->is_broken;
         say "Starting car";
         $self->is_moving(1);
      }
      
      method stop () {
         say "Stopping car";
         $self->is_moving(0);
      }
      
      method break () {
         say "Car broke";
         $self->stop if $self->is_moving;
      }
   }

Moops is still in an early stage of development, but loads and runs significantly faster than MooseX::Declare and doesn't seem to suffer from as many parsing oddities. If you've got a few spare minutes, and a relatively up-to-date Perl installation (Perl 5.14 is required), please download it and give it a go, and let me know how it went for you.