Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
June 29, 2021 02:00 pm GMT

Gradual method renaming in Perl

We have a huge codebase of over 700,000 lines of Perl spread across a couple dozen Git repositories at . Sometimes refactoring is easy if the classes and methods involved are confined to one of those repos, but last week we wanted to rename a method that was potentially used across many of them without having to QA and launch so many changes. After getting some help from Dan Book and Ryan Voots on the #perl libera.chat IRC channel, I arrived at the following solution.

First, if all you want to do is alias the new method call to the old while making the least amount of changes, you can just do this:

*new_method = \&old_method;

This takes advantage of Perls typeglobs by assigning to the new methods name in the symbol table a reference (indicated by the \ character) to the old method. Methods are just subroutines in Perl, and although you dont need the & character when calling one, you do need it if youre passing a subroutine as an argument or creating a reference, as were doing above.

I wanted to do a bit more, though. First, I wanted to log the calls to the old method name so that I could track just how widely its used and have a head start on renaming it elsewhere in our codebase. Also, I didnt want to fill our logs with those callswe have enough noise in there already. And lastly, I wanted future calls to go directly to the new method name without adding another stack frame when using caller or Carp.

With all that in mind, heres the result:

sub old_method {    warn 'old_method is deprecated';    no warnings 'redefine';    *old_method = \&new_method;    goto &new_method;}sub new_method {    # code from old_method goes here}

Old (and not-so-old) hands at programming are probably leaping out of their seats right now yelling, YOURE USING GOTO! GOTO IS CONSIDERED HARMFUL! And theyre right, but this isnt Dijkstras goto. From the Perl manual:

The goto &NAME form is quite different from the other forms of goto. In fact, it isnt a goto in the normal sense at all, and doesnt have the stigma associated with other gotos. Instead, it exits the current subroutine (losing any changes set by local) and immediately calls in its place the named subroutine using the current value of @_. [] After the goto, not even caller will be able to tell that this routine was called first.

perlfunc manual page

The bottom line is that this achieves our third goal above: immediately jumping to the new method as if it were originally called.

The other tricky bit is in the line before, when were redefining old_method to point to new_method while were still inside old_method. (Yes, you can do this.) If youre running under use warnings (and we are, and you should), you first need to disable that warning. Later calls to old_method will go straight to new_method without logging anything.

And thats it. The next step after launching this change is to add a story to our backlog to monitor our logs for calls to the old method, and gradually refactor our other repositories. Then we can finally remove the old method wrapper.


Original Link: https://dev.to/mjgardner/gradual-method-renaming-in-perl-fil

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To