I’ve known about Moose for some time.The first time I talked about it in a training course was at the Teach-In back in the summer of 2007. It’s been part of my training courses ever since.
But even though I was telling people about Moose in my training courses, I wasn’t really making use of it in my own code. Obviously as a freelancer, in my day-job I’m constrained to using whatever technologies my clients are using and I have yet to be paid to work on a project that is already using Moose (although I’ve suggested that a few clients switch to it).
That leaves my own code. Which is largely my CPAN modules. Until recently I hadn’t used Moose for any of them. The first one I released that used Moose was Guardian::OpenPlatform::API. That was a new module which used Moose right from the start. But I knew that eventually I’d want to go back and refactor my existing modules to use Moose wherever it was appropriate.
Having gone to YAPC::Europe this year, I was subjected to another week of people telling me face to face just how cool Moose was. So I decided that it was time to bite the bullet and start refactoring.
The next module I tried was Parse::RPM::Spec. I chose this for two reasons. Firstly, it’s very much an attribute-driven module. Apart from the initial parsing of the spec file, objects of this class exist simply to return the values of their attributes. This makes it a great match for Moose. In fact converting it to use Moose was largely a case of removing code. The second reason for choosing it was more pragmatic – as far as I know no-one is using the module so if I broke anything I wouldn’t have hordes of angry users on my back.
Impressed by how easily that conversion was I moved on to Array::Compare. This module holds a special place in my heart as it was my very first CPAN module. I don’t think it’s a particularly useful module. It’s algorithm is pretty basic and other than the project that I originally wrote it for I’ve never used it in any production code. I often use it to try out new techniques. I released version 2.00 on August 9th (the change of implementation seemed to justify bumping the major version number).
Yesterday I got an RT ticket asking me to stop using Moose. The ticket is pretty clear that for several uses (it specifically mentions command line usage) the extra overhead added by Moose leads to an unacceptable performance hit.
I’m not sure which way to go on this. As a developer I like using Moose. Moose makes it much easier to write object oriented code in Perl. And I think that over the next year or so more and more CPAN developers will be using Moose in their code. Already if you’re writing something reasonably complex in Perl there’s a good chance that you’ll be using a module that uses Moose. As time goes on the percentage of Perl code that relies on Moose will increase. But if it really imposes an unacceptable performance hit for smaller applications, do I really want to force developers into using Moose sooner than they want to?
I think I’m going to put on hold my plans to move stuff to Moose until I’ve thought this through a bit more. But I’d be interested in hearing other people’s opinions. If you’re a CPAN author, are you planning to move your modules to Moose. And if you’re an application developer, have you started to avoid CPAN modules which force you to use Moose?
Let me know what you think.
Update: Well, didn’t this entry start a lot of discussion? As well as the comments here, there have been a number of other posts that reference my post. Here are the ones I’ve seen (in no particular order):
- Take arms against a sea of troubles
- On Moose and Speed
- Re: Moose Or No Moose
- migrating to moose? hell yeah!
I’ll add more as I come across them. Of course, the more discussion I see, the more unclear my decision becomes.
But thanks for the interest. The discussion has been fascinating.
I reckon these are the sort of people who use Gentoo because the extra 2 nanoseconds they’ll get out of it “are really worth it”. So Moore will deal with them sooner, rather than later.
You could try using Mouse, though, have you considered that?
If you have something already written, on CPAN and people are using it, migrating to Moose may not have a lot a value, particularly if why you are doing is as straightforward as Array::Compare is. For a very complicated distribution, like Catalyst, we decided moving to Moose would help a lot in the mid and long term, since the code is cleaner and Moose gives a stronger context to help people start hacking. Since the move to Moose there has been, in my opinion, a lot more user contributions and more activity on the codebase. There have been 11 updates to Catalyst since the Moose migration, which is a very good sign of renewed interest and activity. So in that case it was a good thing, even though some people were nervous about it.
On the other hand, some people are early to pull the trigger and complain when they see Moose. The complaint regarding speed and dependencies is much less valid then it was a year ago. Also, the ability to use local::lib to install user level dependencies and the ability of the new perls to be easily movable pretty much negates the whole, “I can’t get my shared host to install Moose so I can’t use it” argument. See “http://blog.johngoulah.com/2009/08/deploying-catalyst-shared-hosting/” for a good example of this. So really some people are just being obstinate in my opinion.
Moose is not for everything. It is a tool and so has to be used for the right job. You have to balance that against “easy to develop” for yourself and “works like it needs to” for the users.
Dave, did you do any benchmarks? It would be nice to see some numbers.
I would like to say thanks for the conversions though — even if you end up reverting it’s a plus for the community to see how straight forward and simple it is to start using Moose (maybe I’m just a sucker for before-and-after pictures).
I am a CPAN developer (started more recently) and all of my modules released to the CPAN use Moose (http://search.cpan.org/~dougdude/). I am about to release URI::pack, which actually won’t use Moose, as I feel that would be a very unnecessary burden on the URI package. I’ve never seen any e-mails or tickets about how I should not be using Moose, but since they started out with Moose, I’m not as surprised. Also CPANTS says that no other CPAN module uses any of my modules.
To me, for some modules it would seem the opposite migrations may take place, where a module is quickly written in Moose, and then migrated away from Moose once there is more time to invest (in my experience, writing Moose code is mush faster).
I guess the basic question this raises is whether ease of development for you beats usefulness to others. If that ticket is representative, it suggests that actual users feel that converting to Moose is transferring an unwelcome cost them, and so you might end up with modules that are easy to maintain, but unused. That more people might use Moose in the future is speculation, but this complaint is from an actual user.
Perhaps it would be better to wait for requests to Moose-ify existing modules, and if they don’t come, don’t bother. If converting to Moose is that simple, surely someone will send some patches to you, or fork the module, if they want a Moose version.
Instead, just consider Moose for new code, where there is no opportunity to encourage take-up by people looking for lightweight code, only to find it switched to what they think is heaviness after the fact.
I’d try Mouse too. Unless you’re doing something funky I’d be surprised if it’s more than a 1 letter change to your source code.
Two blog posts that might be of interest.
The first, is about sponsorship to improve Moose’s startup speed.
The second is about using App::Persistent to speed up command line apps that use Moose.
surely this means its time for Array::Compare::Tiny
Going from the Array::Compare::Tiny idea one of the interesting things I’ve seen is Net::Twitter. When Marc Mims took over he ported the entire thing to Moose to ease maintenance since the Twitter API can be a … complicated challenge … to keep up with. However he knew that people would complain (and they did almost immediately) with the new overhead. Thus he worked out a solution where he generates Net::Twitter::Lite from the Moose code.
This may not be the option for you, but was an interesting take on the “What do do with the Moose?” problem.
Mouse is ghetto, even the authors say not to use it. There are plans (I’ll try to blog about them tonight) to make basic Moose usage much faster. That means that as long as you are just using attributes, you should be fine, which a lot of these basic things are. So I’d say stick with Moose. We’ll get it fast for you 🙂
I think your Moose-using modules look pretty nice. I would not hesitate to introduce one as a dependency to my project. (Could you have not used Moose? Sure. But you could have also not written the code at all, or you could have written it in Brainfuck, or whatever. “Coulda, shoulda, woulda…”)
The reality of the current Perl 5 programming situation is that if you want to do OO right, you need to be using Moose. Correctness comes with a small performance hit. (But if you care about absolute performance, why are you writing your performance-critical code in a language that is 50x slower than, say, Haskell?)
Gabor and Adam mention that Moose is too big a dependency for Padre, but honestly, by not using Moose, they are severely limiting the extension possibilities. Nobody writes Eclipse extensions because the extension API is too brittle. It is just plain hard to use. Sure, there are a few token extensions… but if you (as a user) ever wonder “can I do foo”, you probably can’t, and writing “foo” yourself is going to take the rest of the month.
Emacs, on the other hand, ships its own programming language, compiles, runtime, and virtual machine, just so you can say “M-: (next-line)”. (Overengineering!!!1111!) Because of this, though, extending Emacs is a joy. Writing valuable macros takes just a few minutes. Writing complex extensions — support for new programming languages, project management functionality, mail readers, IRC clients, … — is similarly easy. The end result is that the source tree contains 2 million lines of (optional) Lisp extensions!
So basically, a big dependency made it easy to implement new features, and people did. The associated startup time and memory costs just don’t matter — the program itself is too useful for anyone to get too upset. (And BTW, emacs23 has multi-tty support, which makes it start instantly. Just like App::Persistent for Perl.)
For me, a user of a text editor, functionality is the most important thing. So what if it takes 5 seconds to start up? I only do that once every 3 months.
(BTW, for the opposite perspective, look at minimalist “vimscript”. Yeah, you can kind of script the editor with it, but it is nowhere near as powerful as Emacs Lisp. The result is that vim starts fast, but users have to live with compromised productivity inside the editor. That makes me sad.)
So don’t worry about the people complaining to you about using Moose. Their priorities are not necessarily the same as yours. (Most people want to write clean, functional code. Padre is aiming for fast startup times and low memory usage at the cost of cleanliness and functionality. To each their own.)
Anyway, sorry that this became a long rant, but basically — you are writing good code, and most people would rather have a well-implemented module that adds 0.05 seconds to their app startup time than having a flaky-but-fast module, or nothing at all. Don’t worry about complaints on rt.cpan. If Mark and Adam can’t use Array::Compare because it uses Moose, that is their problem, not yours.
The reality of the current Perl 5 programming situation is that if you want to do OO right, you need to be using Moose.
Define “do OO right”. Any answer containing explicit reference to Moose will be disqualified. (“You must use Moose to do OO right.” + “Doing OO right is defined as using Moose.” = “You must use Moose to use Moose”, which isn’t a terribly meaningful statement.)
So don’t worry about the people complaining to you about using Moose. Their priorities are not necessarily the same as yours. (Most people want to write clean, functional code.
False dichotomy. I am convinced that it is possible to write clean, functional code without using Moose. I suspect you would agree, as disagreeing would imply a belief that absolutely no clean, functional Perl code existed prior to the creation of Moose.
Don’t get me wrong – Moose is a great tool and extremely useful in a wide variety of cases. But it is not The One True Way To Write Perl. Remember TIMTOWTDI?
Moose’s developers seem to think it shouldn’t be used for command-line programs.
I’ve seen several Moose-related talks at conferences (including Piers’s excellent MooseX::Declare talk at Yapc Europe this year, which really made me want to use it). But at all the talks given by Moose developers they have specifically said Moose has a significant start-up cost, so is only recommended for persistent environments.
Much of the stuff I write has a command-line interface, and this has been sufficient to put me off Moose so far. It’s really irritating for generic libraries which you know mostly will be used in a mod_perl app or whatever and the command-line use is rare; the minority case appears to be dictating the overall behaviour, which doesn’t seem right. But a delay of even half a second on a command can be enough to turn it from being a joy to use to an irritant.
To those who claim Moose is usable in command-line commands, please can you get Moose developers to stop saying otherwise, cos it’s hard not to take their claims seriously.
For a new Cpan module if you use Moose you’re potentially restricting the scenarios in which it can be used. That’s fine — by definition you’re doing that anyway in all sorts of ways, by deciding the scope of your module. Anybody who’s needs aren’t met by your module simply doesn’t use your module.
However for an existing Cpan module, switching to Moose may be making it no longer usable for some users whose needs were met by the previous version. That’s probably something you want do avoid doing, especially since it isn’t straightforward for users to stick at a particular old release of a Cpan module. Adding Moose to an existing module is much more likely to cause upset than using it in new code.
If you have already written a CPAN Module, i would recommend that you instead of switching to Moose you should write an Moosified version. Array::Compare::Moose.
For completly new Modules i would not hesitate to use Moose from the beginning.
And for the problem with Moose and loading time. Primary it is not a problem from Moose, it is more a problem from perl. Because it always recompile everything instead to cache it, but okay we have it, and we must leave with it.
But primary the loading problem is only for CLI Programs that have a short runtime. If you have something like “sed” or “grep” that needs five or four seconds to load that would be annoyed. But for persistent programs i didn’t care if the starting just needs some seconds to load.
And for Padre that i use myself. I start Padre one time, and then the program runs the whole day. Hey Guys, i really don’t care if startup is 2 secods faster. Even Firefox and a lot of others programs that i use have a longer start time then Padre, so i really don’t see the problem here.
And the other thing, to reduce startup time when a programm gets called often the it is better to use some persistent thing. For this there even exists some blog entry from Jonathan Rockway that describes it:
Well, I use Moose in a distribution [Perl-Dist-WiX] that’s basically a command-line program [perldist] that wraps around 30 modules for ease of use and maintenance. It also takes between 30 minutes and 6 hours to run, depending on what you pass it, how fast your machine and hard drive are, and what subclasses you ask it to use. (I’m thinking a Perl-Dist-Padre build on my slow laptop without compiling a .par of Alien::wxWidgets first- but you get the idea.)
At that point, 2 sec. added to the startup time for a command-line program is not an issue, and if they improve that, it’s just frosting on the cake!
I’ve read all the arguments and I am still thinking about. I discovered this blog post about a month ago, decided to come back after some time, now I am working on my own modules.
Being a maintainer for the package collection around an OS I appreciate the use of Moose in any way. Even if it’s not that fast as a specialized perlish version of some routines it delivers a solid and stable framework for oop in Perl. I think this might lead into a lower rate of bugfix releases of the modules you work on.
Custom argument and type checking of constructors seems to be leading into bugs fast, Moose provides handy methods for it.
As for your module Array::Compare I think Moose is still the right way to go, even if a serious performance hit might strike some of the users. Forking it and delivering a tiny version by someone (as already suggested) might not be the best way of dealing with this problem: it requires all the depended software to be changed and being re-released just as a key dependency has changed.
I think API compatibilty is the highest good in the first place, which can be easily done – either in Moose or not. I just saw that it’s still using Moose, good choice imho.
A Moose is just a crap for people unable to write OO code in Perl. Stupid scrutiny, boring cliche of oo in pure Perl. Just more mess .. for stupid ugly perl teennie boys.
Just for the record. I’m in the (painful) process of deMoosifying XML::Schematron.
I don’t get all that “coolness” which just introduces a huge list of dependencies (in my case the app is running on an oldish platform and just the prospect of forcing the customer to keep an eye on 7-ish big Perl packages is… beyond disgusting).
700K of Moose just for 80K of packages? Thanks, but no thanks.
Just came in from the future to say that ‘use Moo’ is a viable. mostly compatible, upgrades appropriately, starts up faster, alternative to Moose.