Crufty Old Perl

It’s eighteen months since I wrote “Why Corporates Hate Perl” and it’s worth pointing out that the company I discussed in that article which was dropping Perl in favour of PHP and Java is still employing as many good Perl programmers as it can find.

I talked in that article about some rather unsubtle social engineering that had been going on at that company. Management had started to talk about Perl as a “legacy language” in an attempt to persuade the business that they really don’t want their applications written in Perl. That doesn’t seem to have been as successful as I feared it would be.

But there’s another kind of social engineering that I’ve seen going on. And this is happening at the developer level. I’ve lost count of the number of times I’ve been sitting in meetings with developers, discussing ways to improve the quality of crufty old Perl code when someone throws in the (more than half-serious) suggestion that we should just rewrite the whole thing using Rails or Django.

There seems to be this idea that switching to a new framework in a new language will act as some time of magic bullet and that suddenly all of our problems will be solved. There are so many ways that this perception is flawed, Here are my two favourites.

  1. The current system is old and crufty not because it’s written in Perl, but because it was written by people who didn’t understand the business requirements fully, didn’t know their tools particularly well or were under pressure to deliver on a timescale that didn’t give them time to design the system properly. Often it’s a combination of all three. Given the time to rewrite the system from scratch, of course it will be better. But it will be better because the business is better understood and tools and techniques have been improved – not because it’s no longer written in Perl.
  2. Frameworks in other languages are not easier to use or more powerful than frameworks in Perl. Anything that you can do with Rails or Django you can do just as easily with Catalyst. It’s using a framework that’s the big win here, not the particular framework that you use. Sure, if you’re a Ruby house then using a Ruby framework will probably match your existing developers’ skills more closely but if your current system is written in Perl then, hopefully, you have a team of people with Perl skills and that’s going to be the language you’ll want to look at.

I’m tired of Perl being seen as a second-class citizen in the dynamic languages world. I freely admit that there’s a lot of bad Perl code out there (I’ll even admit to writing some of it) but it’s not bad Perl code because it’s Perl, it’s bad Perl code because it’s bad code.

This is what the Perl marketing initiative is for. We need people to know that Perl is not the same language that they stopped using ten years ago. Modern Perl can compete with any of the features of any other dynamic language.

By al means, try to get the time to rewrite your crufty old systems. But rewrite them in Modern Perl. You’ll enjoy it and you’ll be really productive.

p.s. I should point out that I’m not talking about any specific client here. This is based on conversations that I’ve had at various companies over the last couple of years and also discussions with many developers in many pubs.

A Subway Metaphor

Many years ago I read a science fiction story which has always stayed with me – although I’m buggered if I can remember the title or the author.

It was set in the not too distant future. Another new line was about to be opened on the New York City Subway [In the comments Rozallin points out that it was, in fact, probably Boston and not NYC]. Mathematicians were warning that the line shouldn’t be opened as every new line increased the complexity of the network and they had calculated that opening this particular line would push the network over some limit and would make it theoretically unsolvable. They worried that the safety of passengers couldn’t be guaranteed if they were travelling on an unsolvable graph.

Of course, the mathematicians were ignored. And, of course, trains started going missing soon after the line was opened. And that’s where our hero (a kind of topological Indiana Jones, if I recall correctly) came in.

For some reason, that’s the image that sometimes pops into my head when I’m working on large application that has had random pieces of code added to it by various people over long periods of time. I worry that the system will eventually become so complex that any train (or, more likely, CPU) that is set running on it will vanish into the depths of complexity, never to be seen again.

I had that feeling particularly strongly this afternoon. This system really needs to be brought under control.

Moose or No Moose

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):

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.

What is Wrong With this Picture?

I’ve just found a number of subroutines defined this way in the code that I’m working on.

I discovered the problem because I started getting errors about “too many parameters”. I knew what the problem was (the empty prototype) but it took a couple of minutes of head-scratching before I realised why it had been working before my changes.

Then I realised.

I have a dislike of “unnecessary” &s on subroutine calls. So almost without realising, I had removed them from the calls to these functions.

A few lessons have been learned.

Lesson 1 (for the original author of this code): Prototypes will trip you up. Do not use them.

Lesson 2 (for me): Ampersands aren’t always as pointless as they appear. They may be masking bugs in the code.