Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

comment on

( #3333=superdoc: print w/replies, xml ) Need Help??

I've been using refactoring techniques for Perl programming, recently, and I was wondering about others' experiences with it. I'll start by defining refactoring and how I do it... there is an excellent book on the subject, Refactoring: Improving the Design of Existing Code, by Martin Fowler. The examples are in Java, but many of the refactoring techniques described therein can be applied to Perl.

Anyway, like the book title says, refactoring is the process of taking existing programs and improving their designs, step-by-step. I find it helpful when in the course of my job I need to add features to legacy code that someone else (or a previous, less learned version of myself) wrote. You can boil down refactoring to these steps applied repeatedly:

  • Pick a patch of code that's desperately in need of improvement. (A subroutine, for example.)
  • Write a small test program that tests the current functionality of that piece of code. (NOTE: Not the expected functionality... this is not bug fixing or feature addition. The current functionality.)
  • Check your tests and code into some kind of version control system, so that you can always retreat to a previous version if you cause a bug.
  • Make a small change that makes the code easier to comprehend and enhance. (For example, pull a small function out of a larger one. Turn a global variable into a function call.)
  • Run the test you've just defined, plus any other tests you've defined for the program.
  • Repeat.

Using the Test and Test::Harness modules that come along with Perl saves a lot of time while writing the tests.

In his book, Fowler defines a list of "refactorings"-- small procedures for improving code. You can get a list of them at his website, I'm working on a similar list focused on Perl, and hope to put up a website collecting them. An example refactoring for Perl would be:

Transform Global Variable To Function Call
Indication: You've got a global or package variable that is being used by a number of different functions to communicate some value.
Solution: Replace the global variable with an exportable function which returns an equivalent value.

  1. Extract the part of code that initializes the global variable into an exportable function.
  2. Tie the global variable to that function.
  3. Test.
  4. Replace instances of the global variable with calls to the new function.
  5. Test.
  6. Untie the global variable from the function.
  7. Test.

Other Perl-oriented refactorings would include:

  • Unreinvent Wheel: replace needlessly rewritten code (like a CGI parser or templating system) with a call to a CPAN module.
  • Strictify Module: Gradually remove errors under 'use strict', testing as you go, until you can finally run the module under 'strict'.
  • Localize Variable: A variable is used only in a single subroutine. Good! Localize it with 'my'.

These would be better with some examples; I'll post some as followup if people are interested. Many of these things are obvious, common-sense things to do, but it's frequently useful to have them written down someplace so that one isn't tempted to skip a step.

Refactoring is extremely useful to me because it gives me a middle-ground alternative between living with incomprehensible code and tossing and rewriting a large Perl project. For small projects it's not such a problem to rewrite from scratch, but I've inherited more than a couple of huge projects consisting of poorly-written RUNNING code. It's my experience that all specs and documentation for such projects are completely out of date. No one knows everything that the software does, but people are out there using it, and management isn't interested in funding a long rewriting project that may lead nowhere... they just want this one feature added. Oh, and this other one. Oh, and this other one, too...

Sorry to have run on for so long, but it's a big topic and I wanted to at least scratch the surface of it. What experiences do people have with this sort of thing? Any refactorings that you find helpful? Any questions?


Update: I am now maintaining a list of Perl refactorings on my homenode.

In reply to Refactoring by stephen

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or or How to display code and escape characters are good places to start.
Log In?

What's my password?
Create A New User
Domain Nodelet?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (3)
As of 2021-10-22 01:30 GMT
Find Nodes?
    Voting Booth?
    My first memorable Perl project was:

    Results (85 votes). Check out past polls.