Moo, how do you annoy me? Let me count the ways...

OK, Moo is actually a rather nice little OO framework. It's inspired by Moose but not a clone of it.

When Moo detects Moose has been loaded, it "inflates" all Moo classes and roles into Moose classes and roles, so Moo code integrates with Moose code perfectly. Because of this, and Moo's very light memory and CPU footprint, many Moose-based projects are migrating to Moo. High profile migrations include Throwable, Message-Passing and MooseX-Role-Loggable.

Not all Moose-based projects are easy to port to Moo. Some require a high level of introspection and meta-hackery that only Moose can provide. But if Moo does seem to be a good fit for your project, switching to Moo is not as simple as dropping the "se" from your "use Moose" lines. There are a number of incompatibilities between the declarative syntaxes of Moo and Moose.

I've recently released MooX-late to help smooth over the differences and translate Moose code to Moo. Currently it handles:

  • stringy type constraints, like isa => "Str"
  • non-reference defaults, like default => 1
  • Moose's lazy_build shortcut
  • Exporting the blessed and confess functions like Moose does

But I'd love to hear what other people think are the Moo annoyances. What is preventing you from porting simple classes and roles to Moo? What does Moose do for you that Moo does not? What features should I add to MooX-late?


Hi Toby

I'm finishing off, again :-(, an article on converting from Hash::FieldHash to, firstly Moos, and then Moo, as applied to a chain of modules.

The double transition is a deliberate part of the assessment of those 2.

The biggest pain of Moo, though, is that defaults are not initialized before new/BUILD are called. This necessitates work-around methods, which must then be called, for big users of BUILD, such as myself.

You've mentioned the other pains of differing syntax of 'default' taking a subref and 'isa'. I would have preferred that isa was just ignored, instead of causing pain, which pain includes new returning the value of a 'default', in 1 case I encountered. Incomprehension is a polite word for the result...

non-lazy Moo defaults are fully initialised before BUILD, just like they are in Moose. Whatever you think you're working around, it isn't that. Please supply a repro case or a failing test if you believe you are seeing this behaviour.

isa + MooX::Types::MooseLike works pretty much the same as isa + MooseX::Types in Moose - which is best practice for any sizeable project.

I'm comfortable with not supporting the "let's guess what the user meant" bug source that is string isa; if I'm doing typed code I like mistaken type names to be detected at compile time rather than a check for $obj->is('StR') or whatever :)

If new() returned a default, somebody declared something with quote_sub() that used return - so it got inlined, and then the inlined code returned from new. Ideally, when this happens a small gnome should exit the monitor and hit the developer with a mallet.

Hi Matt

Bug against Moo submitted. The closest I could get to reproducing the problem was for the default to not be set in BUILD, and simultaneously the code dying in BUILD.

Here's hoping I didn't do something too silly.


... and sadly, you did, as the RT discussion showed.

Trying to make the same package both a class and a role isn't supposed to work; the bug was that it didn't explode and tell you that.

toby's provided a patch that makes Moo die() loudly when you make that mistake, which is now in 1.0.7

Thanks very much both of you for the help.

Leave a comment

About Toby Inkster

user-pic I'm tobyink on CPAN, IRC and PerlMonks.