Perl is Maintainable

Ugh, I have seen too many people claim that you can't build large programs in perl. Here's the most recent one.

This claim is just plain wrong. I currently maintain a perl application that I wrote at work, which clocks in at 15,000 lines of code. It shows no sign of being creaky, and it is maintainable enough that I sometimes get patches sent in from customers (not just other programmers at work).

The problem is not perl, people. The problem is that people have such low expectations of the mainainability of perl that they write shit perl code, and don't bother trying to make it maintainable.

Yes, the syntax is a bit line-noisy, but that has nothing to do with whether the larger structure of your program is scalable or not.

How do you write good perl code? First, use strict and use warnings. Second, use classes to structure your program, even though Perl is a bit weird about how you declare classes. Third, write unit tests, and make sure they call every function at least once, even if they don't check whether the function returned the correct result.

Here's my idiom for unit tests in Perl. I include something like this at the end of each module, and then run it with "perl -wc":

sub unit_test {
    ... insert your code here ...
}
BEGIN { unit_test() unless caller(2); }

Posted on May 9, 2003 05:16 PM
More programming articles

Comments

I don't want to make this a "my application is bigger than yours" pissing context, but 15,000 doesn't count as a "large" application. I'd place that somewhere on the borderline between "small" and "medium".

Having said that, I don't disagree with your thesis, especially in context. The link that you make refers to the ability to write "large, complex systems" in Python. I have to wonder what he considers "large" and "complex". Would that be a 10k line web site backend, or a 4M line telephone exchange control system?

Posted by: Pseudonym at May 13, 2003 12:24 AM

I absolutely agree -- 15,000 is not large. If you read carefully you'll notice I didn't actually say it was -- but I admit I implied it. However, I believe it is "large" enough to expose any fundamental flaws with perl as a language for application development.

Most of the objections that I've seen against using perl for larger systems is that it has an unreadable syntax. But anyone who's worked on large systems knows that syntax is much less important than large-scale architecture and medium-scale design.

Just for the record, the perl application I was talking about is actually just one piece of the system I work on, which currently includes 175KLOC of C++, 30KLOC of java, and 15KLOC of perl. And this is only the server part of our software -- there's also a preprocessing part, which is equally large. I consider this system to be "large", but still very manageable. I would call a 4M line telephone exchange control system "very large" :)

Posted by: kim at May 13, 2003 10:27 AM

Here's a good description of the difference between perl and java, that is very relevant to this post. It contrasts this perl code:

$depth and $depth += ($datadir =~ tr[/][]) - 1;

against this equivalent java code:

if (depth > 0) {
  int count = 0;
  for (int i = 0; i < datadir.length(); i++) {
     if (datadir.charAt(i) == '/') {
       count++;
     }
  }
  count--;
  depth += count;
}

My own tastes would be somewhere in between. Something like this:

if ($depth > 0) {
        my @slashes = ($datadir =~ /\//g);
        $depth += @slashes - 1;
}

My version does a couple things that improve readability. First, by using // instead of tr, I leave $datadir unmodified -- side effects are generally a bad idea. Second, I gave a name to the result of the regular expression, which helps to describe its purpose.

On the other hand, I do use a couple features that only perl has. First, I take advantage of the fact that an array used in a scalar context returns the length of the array. Second, I assume that the programmer knows what the g modifier on // does. In my opinion, both of these features are pervasive in perl code, so it's reasonable to expect maintainers to understand them.

Posted by: kim at May 22, 2003 11:53 AM

I definately agree your example is the superior code. It is an interesting datapoint that not knowing perl that it was only after I had rephrased the original java problem in python that a second look at your perl allowed me to guess what it did.

Correct me if I'm wrong, but a direct transliteration of your code to Python becomes:

isSlash = lambda c: c == '/'
if depth > 0:
    slashes = filter(isSlash, datadir)
    depth += len(slashes) - 1

Although my first thought was to use fold to accumulate a slash count

reduce(lambda n,c: n + (c == '/'), datadir, depth - 1)

I then reconsidered and decided a list-comp would be more readable

depth += len([c for c in datadir if c == '/']) - 1

IMO for this sort of thing you really can't beat a list comprehension for consise, readable expression of intent.

Posted by: Andrae Muys at August 13, 2003 09:09 PM

Very nice python example! Your list comprehension version is very readable to those who know what list comprehensions are. Thanks for contributing.

I've started playing with python as a potential implementation language for my wiki diamond idea. It's nice to see more evidence that it can be concise.

Posted by: kim at August 14, 2003 09:54 AM

I have a python version which is even shorter, actually it is even shorter than the original perl version:


if depth > 0: depth += datadir.count("/") - 1

Regarding the earlier post, I have to say that the Java version seems to be deliberately written to be verbose. Surely the Java String class has a method similar to count() in my python example, or at least the iteration could be performed using a find() method or similar?

Secondly, as a non-perl programmer I have to say that if the first perl version is considered 'idiomatic', then that is just further evidence that perl should not be used for anything larger than system administration scripts. (Not that I don't like that sort of thing. I enjoy using sed, awk and shell in a Unix environment, and all of these have such idiomatic quirks.)

Posted by: at August 14, 2003 05:31 PM
Post a comment









Remember info?




Prove you're human. Type "human":