Posted on Apr 12, 2009

A year with Java

Last year at this time I took a Java programming class as a refresher as I hadn’t done much with Java since my days as an undergrad (and a few short programs in grad school). After primarily using Perl for the last 7 years, this was a big switch. The difficulty with Perl is that it’s a programming language for concenting adults. You can do almost anything any number of ways. The amount of time it takes to understand a block of Perl code is far greater than that of a block of a statically typed language like Java. This had been a huge issue for our company as we had tons of legacy code that followed no standard.

It is my firm belief that if you are going to develop a large codebase in Perl, you MUST use a fairly stringent coding standard. In my first week in my current role, I came across three separate “subroutines” that were over 2500 SLOC. One of the shorter subroutines had 200 SLOC and 32 regular expressions. 4 of these regular expressions were over 80 characters long. Dynamic subroutines are often used. Map statements that turn arrays into hashes are the norm. One library that I maintain is > 10000 SLOC and contains 7 comments. It has been my personal nightmare for more than a year and a half now.

Some of this has to do with simply not understanding best development practices regardless of language, other things (like not adding a comment for a 120 character regular expression) could have been avoided by the use of a coding standard. 80% of software development is maintenance, plan accordingly. One way to force yourself to do the right thing when writing code is to pretend the guy who is going to be asked to maintain it is completely psychotic and knows where you live.

In any event, I have found that using a stringent coding standard is far less important when using Java because:

  • it’s statically typed – I know what I’m going get back from any subroutine. I don’t have to worry about using Data::Dumper with die statements to figure out what complicated object I’m dealing with.
  • you can use a debugger – no more running the entire program and relying on print statements to figure out what’s going on. I can see the value of each variable and I can make changes on the fly and see the results. This is a huge timesaver.
  • frameworks – although there are a few frameworks for various paradymes in Perl, Java takes the cake here. It cuts down on development time by allowing developers to concentrate on the functionality of their application instead of the middleware that must accompany it. Using a framework (struts, spring, hibernate, etc) also makes it trivial for all developers to understand how a module works.

I can’t understate the huge amount of time our company has saved since switching to Java. “Estimated Time to Fix” is greatly reduced and more work is accomplished.

Posted on Dec 11, 2008

Stupid Bug

I spent an hour trying to figure out what a field in a fixed width file was being truncated by one character. This is what I found:

Definition

<header start=”1″ end=”8″>accountnum</header>

Calcuation

$length = $header->{end} – $header->{start}

Great, except that columns 1 THROUGH 8 total 8, not 7. Ugh.

Posted on Aug 20, 2008

Why Corporates Hate Perl

Interesting post at O’Reilly about Perl and how some companies view it as the major problem behind legacy applications. Obviously false but it just goes to show that Perl should be “used by consenting adults” with some semblance of adherence to standards.

http://www.oreillynet.com/onlamp/blog/2008/08/why_corporates_hate_perl.html

Posted on Nov 24, 2007

Dynamic DNS updates with dnsexit.com

I recently registered a couple of domains and though I’ve been happy with dyndns figured I’d try a free DNS service. dnsexit seemed to have what I needed and I was able to get up and running quickly without any issues. I typically use ddclient for sending my updated IP address to dyndns, but since ddclient doesn’t support dnsexit, I was left to my own resources. The scripts provided by dnsexit were not as full featured as ddclient and didn’t have support for common routers. What I ended up doing was bastardizing domainUpdate (from the bottom of the scripts page) and using it with routerip.pl

To make this work, first install routerip.pl and domainUpdate.pl updating all the necessary variables. Then just change domainUpdate.pl to use routerip.pl to get the IP address of your router instead of your local machine:

replace:

# get IP from @network
# --------------------
foreach $line (@network) {
    if ($line =~ /.*inet addr:(.*)  P-t-P.*/)
    {
        $ip = $1;
        last;
    }
}

with this:

# get IP from routerip.pl
#--------------------
$ip = `/usr/bin/routerip.pl`;
chomp $ip;

Also, since I had more than one domain to update I changed domainUpdate.pl to handle that too by changing the scalar $domain to an array (@domain) and replacing:

if ($ip ne $lastip) {
    $update = "http://www.dnsexit.com/RemoteUpdate.sv?login=$user&password=$pass&host=$domain&myip=$ip";
    get($update);
    open(FILE,">$ipfile") || die "Can't open $ipfile $!\n";
    print FILE "$ip";
    close(FILE);
    `$logger "IP updated."`;
    print "IP updated!\n";
} 

with:

if ($ip ne $lastip) {
    foreach $domain (@domains)
    {
        $update = "http://www.dnsexit.com/RemoteUpdate.sv?login=$user&password=$pass&host=$domain&myip=$ip";
        $success = get($update);
        die "Could not connect to dnsexitn" unless (defined($success));
        open(FILE,">$ipfile") || die "Can't open $ipfile $!n";
        print FILE "$ip";
        close(FILE);
        `$logger "IP updated."`;
        print "IP updated!n";
    }
}

Posted on Oct 30, 2007

Using Perl in Software Development

I’ve been using Perl since 2001 in a variety of roles beginning with systems administration. For the last few years I have been a “Software Engineer.” I put that in quotes because popular opinion states that using a scripting language to develop software somehow makes you less of a Software Engineer. Users of languages like Java, C, C++, etc argue that a language like Perl does not have the proper restraints to force developers to write elegant and understandable applications. In some respects, they are correct. A scripting language like Perl allows developers to make their code barely legible. There are plenty of open source applications you can download that prove this point. Yes I’m sure I could find some open source Java project and find that it’s pretty ugly too, but for the most part you would find that most Java programs look a lot alike and won’t vary in style (and stability) as much as scripting languages.

A lot of this is due to the enforcement of standards. As an example, let’s look at a method/subroutine that gets the greatest common denominator in Java and Perl.

In Java:

private int gcd(int num, int denom)

{

    while (denom > 0)

    {

        int q = num/denom;

        int r = num - q*denom;

        num = denom;

        denom = r;

    }

    return(num);

}

In Perl:

sub gcd

{

    my ($n, $m) = @_;

    while ($m) {

        my $k = $n % $m;

        ($n, $m) = ($m, $k);

    }

    return $n;

}

Just by looking at the code you know these things about the Java that you do not about the Perl:

  1. Return type
  2. Argument types

Also, if you try to pass the wrong number of arguments or incorrect types of arguments to the Java method, you will get an exception. In Perl, you will end up with a logic error because the Perl interpreter WILL do the computation for you but you are likely to get a bad result. Sure, there is always the “Garbage in, garbage out” to fall back on, but it would be nice if you knew going forward that your code could potentially give you a bad result.

There are lots of instances like this where Perl will give developers enough slack to hang themselves. Without variable or return types and declarations, developers can make their code very unstable. Languages like Java force developers to think things through by requiring variable and return types. This makes the language more difficult to pick up, but has the benefit of requiring the developer to know what they are doing to write the code. Of course we can all find examples of horrible design and code in any language, but you will find more examples in languages such as Perl that are so easy to pick up.

What differentiates the “scripters” from the “developers” the most is not the language however, it is adhering to good software development practices. Someone using Java probably has a background in software development while someone who uses Perl could be from any number of backgrounds. Systems administration is where I picked up Perl and I’ll be the first to admit I’ve written some pretty bad scripts in my years. Since moving to development however, I’ve learned that by adhering to solid software development practices, even scripting languages are viable choices.

Why use Perl?

The main reason I use Perl is that I find most tasks easier to code. It takes far fewer lines of code for most tasks in Perl as it would in Java or some other traditional development language. Due to the nature of my job I also do a lot of file IO and communicating with the Operating System. There are few better choices than Perl for these tasks. Also, there are a vast amount of modules available on http://cpan.org that you may use with relative ease for most tasks. If you can think of it, chances are someone has already written it and made it available via cpan. The lack of “types” in Perl can either be a blessing or a curse depending on how well you write your code. Sure it saves time and gives you a bit more freedom not having to worry about declaring types for your variables and subroutines, but on more than one occasion I’ve used the string comparision (cmp) operator in place of it’s numeric counterpart (<=>).

Below are some of the things that I have learned in my experience as a software engineer to make Perl a more attractive option for development. I think there are enough benefits to using Perl for some projects (yes, there are plenty of projects out there that are better suited for Java or some other language) to work around it’s shortcomings.

use strict;

This is one of the most important things you can do to avoid the common pitfalls of using a “scripting” language. The ‘strict’ module makes you specify scope for all of your variables so you don’t step on any unintentional globals or use more memory than you have to.

Enable warnings (-w)

If you are doing something potentially stupid, using warnings will usually give you a heads-up. This offers you some protection from yourself and Perl.

Use a main() subroutine

No this is not required by Perl. You may in fact simply open an editor and create a 3,000 line script that does not include a single subroutine. In all of my scripts I have a stanza that looks like this:

main();
sub main
{

.......

}

The advantage I gain from this is that I always know where to look in every one of my scripts for the start of my program. In fact, this lies right in line with using……

Coding Standards

There are many tools that allow you to apply standards to your code in traditional development languages. I do not know of any for Perl, but that doesn’t make it any less important. Taking simple steps to ensure consistency make your code much more readable for other and yourself when you go back in a year and try to figure out how something worked. This doesn’t have to be too constricting, it needs to ensure consistency. Some of the things I always include:

  • Constant variables are all upper-case, words separated with an underscore (MY_CONSTANT)
  • Global variables begin with an upper-case letter, words separated with an underscore (My_Global)
  • Locally scoped variables are always lower case, words separated with an underscore (my_local)
  • Each word in a subroutine name begins with an upper case letter and does not include any underscores (MyFavoriteSub)
  • ‘use’ statements, constants and globals are always declared in the top of each file
  • Always put braces on a new line
  • Every subroutine includes the following subroutine header:
#################################################
# Description:
# Arguments:  arg1 (type)
# Returns:  arg (type)
#################################################

Use an IDE

There are a few out there for Perl. I use the EPIC Perl Eclipse module. I know a lot of people who are happier using vi than an IDE. Typically an IDE does give you some advantages however, such as syntax highlighting, error checking, etc.

Compile

One of Perl’s drawbacks, especially if your project uses lots of modules, is that you need to install all of these modules on every machine you are going to run your code on. There is a product called the Perl Developers Kit (PDK) from ActiveState (which I own no stock in) that allows you to compile your applications into binary format. It supports Linux, Solaris and (if you must) Windows. What it does is bundle all your code together with a trimmed down version of the Perl interpreter and all the modules your code uses in a binary that you may run without even having Perl installed on your system. As an added benefit, if your code is company sensitive (or just sensitive to you) you don’t need to give it to your users.