This is a very old article. It has been imported from older blogging software, and the formatting, images, etc may have been lost. Some links may be broken. Some of the information may no longer be correct. Opinions expressed in this article may no longer be held.
Acme-oop-ism is about writing code that works in Moose, Mouse and Moo. We’ve already looked at how Type::Tiny has achieved this. Now I’m going to introduce you to some Acme-oop-ist techniques.
Want to write a reusable class or role to stick on CPAN? If you were planning on using Moose, how about considering Moo instead? Moo doesn’t have all of Moose’s features, but if your project doesn’t need advanced metaprogramming, it may still have enough.
Moo is designed to interact nicely with Moose. Moose and Moo classes can extend each other. Moose classes can consume Moo roles, and vice versa. It won’t much help you interact with Mouse, but two out of three ain’t bad.
Role::Tiny is sometimes also an option.
Rather than creating roles intended for consumption, or base classes intended for inheriting from, each of which would potentially lock people using your module into a particular OO framework, consider creating small classes that can be delegated to.
As an example, rather than creating a
HorseDrawn role that can be applied to cart objects, create a
Horse class that cart objects can delegate conveyance to.
Moo, Mouse and Moose each have handy shortcuts (
handles) for delegated methods.
Use Moo or Class::Tiny, or even hand-written classes to keep dependencies down.
Use the surface syntax
The internals of Moo, Mouse and Moose are rather different to each other (particularly Moo). Their syntactic sugar is less so. Rather than calling
$class->meta->add_attribute(), can you get away with calling
MooX::HandlesVia and MooX::late are two CPAN modules that extend Moo by providing wrappers for
has(). Each of these is Moo-specific, but it’s easy to imagine applications of this idea that are not.
MooseX::MungeHas provides generic logic for munging
has across OO frameworks.
MooX::PrivateAttributes and MooX::ProtectedAttributes manage to work for Moose by using a similar technique – calling the
around sugar instead of metaclass tinkering.
Multiple code paths
As a last resort, you can add different code paths for handling Moose, Mouse and Moo. You can check to see what framework a class is using via
$class->meta->isa(...) and handle it appropriately.
Tools of the trade include run-time loading via
require or Module::Runtime, and judicious use of stringy eval.
install_sub method is an example of this, providing different code paths for installing method modifiers into Moo, Mouse, Moose, and plain Perl classes.
Subclass::Of is another example.
That’s all your Acme-oop for now. I’ll write some more on the topic soon.