Antipatterns in Perl

ziggy on 2002-03-01T20:01:11

Matt has written up a snippet about his progress in rewriting a truly large, nasty piece of Perl code. He's removed one antipattern from his code: lots of mutable global variables. That got me to thinking of a different antipattern I'm dealing with in my code at the moment: lots of useless constant globals. :-)

Here's another antipattern I'm dealing with at the moment: the all-singing, all-dancing module. Without going into details, here's what I'm looking at:

  • Load a series of core modules and common CPAN modules (OK).
  • Load a series of application-specific modules to process data (OK).
  • Load a series of application-specific modules to talk to a database (OK....).
  • Load a series of application-specific modules to handle logins over the web (you're losing me...).
  • Load a series of modules to make yourself a web application (you've lost me now).
  • Load some of those modules again (what are you doing?)
  • ...
It's well known here that the code I'm working on is pretty bad. It was written over a period of years by a number of people. And there's some cut-and-paste going on too. The state that it's in right now is both understandable and highly undesirable. No news here.

My big question of the moment is: how to simply and concisely explain what is wrong with this scenario and how to fix it? I've already found instances of modules being loaded that aren't actually used. Removing those extraneous references would go a long way to clarifying what's going on here.


My case

Matts on 2002-03-02T09:26:01

At least for this code I had a plan of attack:

1. Turn on warnings. Adjust code so its -w clean.

2. Move into a single .pm file, with a stub .pl file to call it.

3. Add a test dir, so I can add tests as I go.

4. Remove all globals.

5. Move groups of subs into relevant sub-.pm files.

6. Investigate performance improvements via SelfLoader, etc.

4 is an interesting one, because it's not criminal to have globals, but in this case it's detremental to being able to do step 5. Especially since none of the globals are located near to their relevant functions. One thing I'm concerned about is that I've migrated all the globals into a singleton that stores the global info, but there's no "strict" on that - it's all just hash keys, which is bothersome, and worrying given this developer's perl skills. But I'm hoping it will encourage him to do more lexical scoping, as there's really no need for all this globalisation. I'm also going to investigate doing an optional run-time checking system probably based on tie(), to check the appropriate values are being accessed.

Re:My case

ziggy on 2002-03-02T18:54:08

Unfortunately, I have a different set of goals. The core need here is to replace something on the order of 60KLOC - 250KLOC of locally written Perl code to do very little more than query a database and output XML. I've convinced myself that I could go full bore and get the entire project done, tested and out the door in not a lot of time. However, there is the question of lasting value -- this is only one of a handful of similar codebases at this client, and I'm only rewriting one backend. Re-engineering the front-ends isn't on the table, nor are any of the other products.

So, my approach is sort of a zig-zag: examine a little, rewrite a little, and track the antipatterns as I find them with remedies.