Pathological Anti-Patterns

ziggy on 2002-01-16T18:27:07

I'm debugging a huge piece of legacy code at the moment (the better part of 100,000 lines from what I can tell, some of it included HTML chunks and SQL statements), and it's using one of the earliest, ugliest and nastiest antipatterns I've ever seen: Pass-by-global.

As usual, the global variables being used aren't documented, nor is their behavior. My best bet at the moment is to bring up two ssh sessions and examine a "working" version, comparing it to a new rewritten version that should help isolate what the behavior really is...

Now, a Python bigot would be able to point to this big mess of code and utter: "See! Friends don't let Friends program in Perl!" Realistically speaking, a big pile of messy code is a big pile of messy code in any language, regardless of the idioms used. Java, for example, may be designed to limit or even prohibit the use of global variables. However, that does not prevent pathological anti-patterns from being used -- it just forces new ones to be created. :-) (Python is incapable of preventing this pass-by-global idiom; it just deprecates it differently...)


Been there, done that

jdavidb on 2002-01-16T19:48:27

And feel your pain! We fixed it by systematically removing each function to a separate file, turning on C<use strict;>, and then running

$ perl -c program 2>&1 | head

and removing an error at a time. Fortunately most changes we made removed several thousand error lines at a time. Change "head" to "wc -l" for real fun. After perl -c works clean, take out the -c. After that runs clean, move another function into its own file.

Re:Been there, done that

ziggy on 2002-01-16T21:28:40

I did a brief guesstimation on the size of this system. It's looking like it's roughly 100,000 lines of Perl code. (It's quite difficult to tell actually; there are about 200 non-core, non-CPAN locally writen modules involved here with only the most incestuous of relationships found...) The reason why it's difficult tell the overall size is because (1) the modules are split into two different directory structures, and (2) one of them appears to be isolated to this product (with ~60,000 lines), and the other is code reused across a family of products (consisting of ~227,000 lines). Furthermore, that includes things that should be counted (such as whitespace, comment lines, and HEREDOCs for SQL, HTML, etc.)

What's really nice is that the code exhibits a couple of similar but subtly different anti-patterns:

  • pass-by-global
    (all variables in %main::)
  • export-to-everywhere
    (many modules importing the same symbols from a common module, so they're effectively global, but at the same time not really global)
The really tricky part is that it probably won't get rewritten. I'm dealing with some bits of the backend, but much of the code in dire need of remediation is shared between a backend and a frontend (which is a completely different effort altogether...)

Oh ghod... I feel your pain

pdcawley on 2002-01-16T20:03:20

I had a couple of days consultancy at a company that shall remain nameless. My brief was to take a look at their code and give them a rough idea of how long it would take to convert it to mod_perl and what kind of performance gain they could expect.

Their code was terrible spread out through a bunch of files (but with everything in the main:: package) and doing stuff with a dreadful mix of pass by global whilst occasionally spawning seperate perl processes to (afaict) blow the accumulated global cruft away to do some other work...

I had intended to just bung Apache::PerlRun in place and run the code under that to get an idea about performance gain. But it failed to run.

Oh yes, and the two jerks who'd perpetrated this pile of, ahem, code appeared to be proud of it, and didn't seem to be interested in finding out how to fix it.

I've rarely been more grateful not to get a long contract out of some consultancy.

Re:Oh ghod... I feel your pain

pdcawley on 2002-01-16T21:51:02

Oh yes, forgot to say. When I finally got a travesty of the functionality working under mod_perl, it ran in about 100th of the time.

Similar story

Matts on 2002-01-17T07:37:32

Here at work our anti-virus product is 12,000 lines of very ugly Perl (along with probably lots more C). It took me two weeks to untangle the whole ball of string and re-write it into separate packages. However sadly time pressed on too much and now I pretty much have to re-do the rewrite because changes got made to the original, not the rewrite. *sigh*.