Last night I was speaking at the Milton Keynes Perl Mongers technical meeting. I gave a new talk about how Moose (and, in particular, Moose traits) make Perlanet easier to maintain and enhance. The slides are available on Slideshare.
I’ve been teaching basic Moose in my training courses for several years now. And, as I’ve mentioned before, I’ve been slowly converting some of my CPAN modules to use Moose. But there are still bits of Moose that I haven’t really needed to get to grips with.
One such area is Moose’s support for Traits. Oh, I knew vaguely what they were and I understood why you might use them. But I’d never implemented a system using traits, so my knowledge about how you’d actually use them was a bit shaky to say the least.
But over the last few days I’ve learned quite a lot about how to use traits. And I’ve had to learn it pretty quickly.
It all started a few weeks ago when I got a github pull request from Oliver Charles. Oliver had taken a fork of my Perlanet repository and had massively refactored the codebase so that all the clever bits were implemented as traits.
What this means is that the core Perlanet code is pretty dumb. In order to do anything really useful with it to need to add in some traits. There are traits to read the configuration from a YAML file, traits to carry out various kinds of cleaning of the input and a trait to produce the output using the Template Toolkit. There are also traits to handle caching and OPML generation. All in all it makes the code far nicer to work on.
Oh, and there’s a Perlanet::Simple module which uses all of the traits required to implement the Perlanet behaviour that users currently expect.
There were a few problems with Oliver’s initial version. Some of the dependencies weren’t quite right. But we soon fixed that and last week I finally released Perlanet 0.47 which implemented these changes.
Then I installed it on the server which hosts most of my planets. And everything broke.
So I’ve spent a lot of the weekend fixing these issues. Part of it was that Oliver’s changes assumed some configuration file changes that I hadn’t implemented. I changed his changes so that they worked with the existing configuration settings (we don’t want users having to change configuration files unnecessarily). Other changes were harder to track down. I particularly enjoyed one where no feeds were fetched unless the user turned on OPML support. I learned a lot about how traits worked by tracking that one down.
But it all seems to be fixed now. Perlanet version 0.51 is available on CPAN and it will hopefully be a lot easier to customise to your needs. I hope we’ll see a number of other Perlanet traits appearing over the next few months.
And, most importantly, I’ve learnt a lot about traits. I think I understand them now.
If you want to learn traits, I can highly recommend asking someone to implement traits in one of your projects. And it’s even better if they do it in a slightly broken way so that you need to debug it.
I think they’re running up against this bug in XML::Feed (which is one of the modules that Perlanet uses to process the feeds it subscribes to). There’s a patch in the bug report that I’ve applied to my local installation of XML::Feed and it seems to have fixed the problem.
Until the author releases a new version of XML::Feed that includes this patch, I recommend that anyone using XML::Feed (and that includes everyone using Perlanet) applies the patch for themselves.
I can be a bit of a lazy open source author at times. I love it when someone improves my code and then just emails me patches. I love it even more now that I’m using Github so that people can just fork my code and send me pull requests.
That happened over the weekend. I got a pull request from cycles saying that he’d been refactoring Perlanet and asking if I’d be interested in merging his changes. These refactorings had come out of a mini-hackathon that had been run by the North West England Perl Mongers. I knew that they had been interested in using Perlanet to power the Iron Man aggregator, but that the monolithic nature of the code made it hard for them to subclass the bits that they needed to change.
So what cycles has done is to take my code and break it down into a number of smaller functions (and a couple more classes) so that people can subclass it and override methods where they want different behaviour to the defaults that I use. I can see this leading to a little ecosystem of Perlanet subclasses where people release their favourite tweaks to CPAN. I see this as a good thing.
I liked cycles’ changes so I merged them into my repository. They’re available there now if you want to look. I haven’t yet released a new version to CPAN as there are a few things I want to check out first.
Firstly, this new update seems to have increased the version of Moose required. With the version of Moose that I was running on my system (0.88), a lot of the tests were failing. Updating to 0.93 solved that problem. I need to work out exactly what the problem was and update the “requires” line in Build.PL appropriately.
Secondly, the newer version of Moose gave a deprecation warning when used with CHI. Updating to the latest version of CHI fixed that (but that, in turn, meant upgrading a few modules in the Log::Any family). This is all starting to get a bit too close to the bleeding edge of CPAN for a module that I want as many people as possible to use.
Finally, cycles had started to use TryCatch in the module. Not, of course, that I object to high quality exception handling in my code, but this is another module that isn’t yet in general use. It’s something that you won’t find in a “standard” (whatever that means) Perl installation.
I’m in the process of building RPMs of all of the missing modules (or later versions for the modules where the Fedora/Centos build is just lagging CPAN a bit). They’ll be available from rpm.mag-sol.com in the next few days.
Currently I’m leaning towards just releasing the new version and hoping that the people who want to use it will have enough enthusiasm that they won’t complain about the updated and new modules that are required. But I thought it would be interesting to ask for your opinions too.
As a user of CPAN modules, how do you decide when a module is too cutting edge for you to use? Do you just install newer versions of modules automatically when an installation asks you too? Or are you a little more careful than that? Would the constraints in this latest version of Perlanet prevent you from using it?
And as a writer of CPAN modules, how cutting edge do you allow yourself to be? Are you happy to release stuff that only works with the very latest versions of Moose or other fast-moving modules? Or do you like to ensure that your stuff is usable by people who might be a little behind the curve?
I should make it clear that I’m very grateful for the work that cycles did and I’m not disparaging his efforts at all. I’m just dithering a bit about how cutting edge I want to be.
Maybe it’s just me, but when I know that people are using my code it galvanises me into improving it. Following the discovery that people were actually using Perlanet, I’ve made quite a few releases over the last week or so. I thought people might be interested in what I’ve been doing.
Release 0.30 was a big one. I incorporated a lot of the improvements that Alex had made in his fork. Most important was probably switching to URI::Fetch instead of LWP::UserAgent. This means that we can now cache the feeds and only re-request them when they have changed.
Release 0.31 documented the caching feature. It also removed some annoying debugging output unless the program was running in a console. I also tweaked the output for failed requests and thereby introduced a nasty bug that wasn’t fixed for some days.
Release 0.32 added some better help for the ‘perlanet’ command line program and added a lot more of Alex’s fixes and improvements. I also tried running the code through both ‘perltidy’ and ‘perlcritic’ and made some changes based on their suggestions.
Release 0.33 featured a much improved test suite. It also fixed the nasty bug that I introduced in 0.31. If you were using a cache and a feed hadn’t changed from the previous request then it wasn’t processed at all. I found this bug whilst working on the test suite. Testing is good, boys and girls!
Release 0.34 went out in the last hour. Overnight I got a bug report about the caching support. I’ve been using CHI to provide caching, and because not everyone wants to use caching I had marked it as an optional dependency in Build.PL. But I was loading it in the code whether or not it was being used. So if you didn’t have it installed, Perlanet didn’t work at all. I’ve now made it truly optional – it’s only loaded if required. And if you try to use caching but don’t have CHI installed everything still works – just without a cache.
That got me thinking. And the version currently in github applies the same principle to OPML support using XML::OPML::SimpleGen. Not everyone wants to generate an OPML file, so I shouldn’t force everyone to install that module. That will be in release 0.35 which will go out in the next couple of days. I’m also thinking of doing the same for the HTML::Tidy and HTML::Scrubber support.
I still have some more of Alex’s patches to apply. But I’m considering how to make things like filter support into an optional add-on. I’ve tried to get some discussion of these features going on the Perlanet mailing list. If you’re interested in Perlanet, please subscribe to the list and get involved in the discussions.
 I should point out that Perlanet already has support for HTML::Tidy, but installing HTML::Tidy is a bit of a black art currently. The RT queue seems to imply that the module has been abandoned. Does anyone want to offer to take it over from Andy?