in reply to Best way to fix a broken but functional program?

The very first thing to do is to run it and get a set of known output. You don't want to be messing with something you don't understand until you have a baseline.

The second thing is to make a copy somewhere, not in your working directory. (Oh, you do have a directory structure just for this effort, right?) Then, make another backup copy in your working directory. Then, you have your working copy. If this thing is critical in your e-commerce system, then you have to maintain a copy that works, even if it's unmaintainable.

The third thing is to print out a copy and take it home. Go to a diner and drink coffee, smoke a pack of cigarettes, and read the code. Mark up your printout.

The fouth thing is to reformat it. DO NOT MAKE A SINGLE CODE CHANGE! Simply get the code to "look normal". Get the squigglies to line up. Get the capitalization of if-then out of there.

Up until this point, you haven't made a single functional change. You've also read the code at least 2-3 times all the way through, in the process of reformatting. Now, before enabling strict, start going through and making it strict. You haven't enabled strict, yet.

Every iteration of this, you have to re-run it and make sure it still works. You will have to find a way of doing this. THIS IS THE MOST CRITICAL PART. Give it the exact same input and run against the known output. diff the files and make sure their identical. If they're not, back up and find out what you accidentally changed.

Once you think you got all the my things in place, enable strict vars. Do NOT enable strict 'refs' yet. You'll go nuts. Don't be afraid to 'use vars qw(....)' a lot. Clean up the ones you missed.

After that, start moving the code around. Make functions. Start uncoupling the data. Start localizing the data. Start perl-izing the code. Use hash-slices. Use unpack instead of substr. Use the backwards-if. Use common-sense.

Once you have that done, you should have gotten most of the symbolic references cleaned up. Enable strict 'refs'. Clean up what you missed.

Now, go to full strict. Clean up what you missed.

Now, add warnings. Clean up what you missed.

During this entire process, document what you can.

Don't be surprised if you discover that, in the process of cleaning this up, you have to clean up other stuff. Maybe there were globals that were cross-file. Maybe there were dependencies you didn't know about. Leave those dependencies in there for the other files!! Don't attempt to touch anything but the file you're working on. You'll go nuts. Mark them to be cleaned up later.

Then, when you're done, you'll probably be down to under 1000 lines and have a very easy script to work with.

I'd estimate a good 2-3 weeks completely on this.

------
/me wants to be the brightest bulb in the chandelier!

Vote paco for President!

Replies are listed 'Best First'.
Re: Bite off a little at a time...
by idnopheq (Chaplain) on Aug 22, 2001 at 22:34 UTC
    Well, all, I guess the core problem is that I cannot decypher it enough to support it, which I have been tasked with. By some miracle, the process has run for over a year w/o restarting, so there is magic within it, no doubt. But what is that story from the Jargon file, about Mel, a real programmer?

    I see areas where things like Net::Telnet maybe employed versus opening raw sockets, where Tie::Hash would make life easier, even where removing seemingly obvious redundencies and lengthy if-elsif statements, would improve things. But, being so sensitive to day-to-day operatios, is there a delicate way to proceed?

    Like I said, cperl-mode will help me with lining things up, and hopefully tcpdump will tell me what is passing between the various hosts. I would most definitely rewrite the thing, but w/o a model office to play in, what can I do other than tweek and test?

    Remember I'm working IT for the auto industry, in a group of four which used to be twenty.

    HTH
    --
    idnopheq
    Apply yourself to new problems without preparation, develop confidence in your ability to to meet situations as they arrise.

      A little at a time, my friend. You have to go slowly.

      The very first thing is that you should ALWAYS have some manner of development box which (relatively) closely mirrors the production environment. What're you going to do, develop in production?!? Of course not!

      Get it lined up. That will help you understand what's going on. Comment it extensively. Then, start breaking out functions. Rename variables. Take it very slowly.

      You really can't do very much, unfortunately, without that development area. Demand that, or say that what the manager requested cannot be safely done.

      ------
      /me wants to be the brightest bulb in the chandelier!

      Vote paco for President!

        Slowly is what I'm all about, hense the post. But I'm in no position to demand anything, as my company Friday laid off 3% of the workforce.

        Given that I'm stuck in a less than optimal situation, I'm trying to at least clean up the syntax to a legible point w/o breaking functionallity. I admit, tho, that $foo and @Foo look too similar and make my eyes bleed.

        I'm taking someone's advice and writing a script that will simply output all of my scalars, arrays, and hashes so I can see what I'm up against.

        Also, I'm deficient when it comes to the debugger ... but necessity is the mother of invention and/or education ...

        HTH
        --
        idnopheq
        Apply yourself to new problems without preparation, develop confidence in your ability to to meet situations as they arrise.