September 2010 Archives

Moose 1.15 will be out the door shortly (he says with hope in his heart), and it will include a few incompatibilities along with some bug fixes and speedups.

It's worthwhile to discuss both the philosophy and actual practice of backwards compatibility in Moose, so end users know what to expect.

There are a couple principles at work.

  1. Moose favors correctness over backwards compatibility.
  2. Moose supports documented behavior, not accidental behavior or side effects.

These two principles are often related.

In this next release, methods generated by using a native trait will now check their arguments. If you try to pass an argument to an Array's count() method, it will throw an error.

We never documented this one way or another, and the current behavior is clearly wrong, so we feel that changing this is okay.

When incorrect behavior is documented, we don't remove it outright if we can possibly avoid it. Instead, we add a deprecation warning, and will remove it eventually.

This stands in contrast to other projects, like Catalyst, which has a much stronger backwards compatibility guarantee.

So that's the policy, but how about the practice?

We do a lot of testing to smoke these changes. A while back, I wrote a module called Test::DependentModules which allows you to test some or all of the modules dependent on a given module. While we don't test every dependent, since lots of them are stale, we do test quite a few. If you have something on CPAN you'd like to include in the tests, just let us know via irc or email.

When this test finds a problem with a change, we usually offer to help downstream authors change their code, and we try to synchronize new releases of Moose with new releases of dependents. It's most often MooseX modules which get broken, because many of them are intimate with the Moose internals. It's less common for modules which simply use Moose to break outright.

Fey::ORM is effectively a MooseX module, despite the name, as are a few others. Some modules, like Catalyst, poke around in the more arcane corners of Moose, and tend to be more easily broken.

We also maintain a list of conflicting module versions by hand in our Makefile.PL. Unfortunately, the CPAN toolchain doesn't (yet?) have any sort of real support for conflict handling, so all we can do is print out some warnings to the terminal at install time. I hope that in the future, there will be an official way to declare conflicts. Then CPAN clients can let the user choose how to handle them (update the conflicting module, ignore, don't install the new Moose).

Finally, we expect that end users test new versions of Moose (and of any other dependency) before deploying to production. If you don't have testing that you trust, you probably shouldn't be upgrading at all!

This is also documented in the Moose docs, but with less detail.

Hopefully this helps make our decisions a little more transparent. Comments (sans too much flame) are welcome.

For the most part, Moose is pretty well optimized for runtime operations. If you make a class immutable, your constructor will be as fast as it can be. Similarly, attributes are always inlined with the most optimal code we can generate.

However, I've been doing some profiling recently of some of my Moose-using modules, and I've found some areas for improvement.

The 1.13 release addresses one of these. Previously, calls to $object->does() were fairly slow, especially for classes with a bunch of roles or deep inheritance hierarchies. The does() method ended up looking up roles in the metaclass object, and it did this in a really slow way.

With 1.13, all of a class's roles are captured in a hash, and we can look up any role in the time it takes to look up a hash key. If your app makes a lot of calls to does() then this might help. Note that calls to does can happen behind the scenes with any sort of role-based type constraint.

Next up on my list are native traits. It turns out that the code which implements these often goes through some really slow paths in Moose. I'm going to make all native traits inlined as well. In the best case, that will generate code like push @{ $self->{foo} }, @_, which will be much faster than what we do now.

About this Archive

This page is an archive of entries from September 2010 listed from newest to oldest.

August 2010 is the previous archive.

October 2010 is the next archive.

Find recent content on the main index or look in the archives to find all content.

Categories

Pages

Powered by Movable Type 4.38