List of perl subroutine refactoring options

I am currently refactoring the application code, and I want to remove some parameters from the routine. For example, let's say I have the following [1]:

sub do_something { my ( $param1, $param2, $param3, $param4 ) = ( @_ ); .... } 

However, as part of refactoring, I made parameters 2 and 3 redundant. Updating this method signature is the easy part, but is there an easy way to update all calls to it?

I did this in the way of some grep / sed / perl custom-made, but some sub calls have several lines, which makes it painful, and every time I do this in the project it's custom-made. Are there any tools that are good for this particular refactoring?

[1] - Not the actual names of parameters or routines, I assure you!

+4
source share
2 answers

Padre has some features for refactoring, but I don't know if it can do what you want.

Change your interface to accept hashes instead of positional lists, this will make changes in the future less effective than now.

 sub do_something { my (%param) = (@_); ... } do_something(foo => 23, bar => 42); 
+3
source

If you have a test suite that has almost 100% code coverage, you can use it to find all call sites.

Given the argument for the position in the freeze frame, the built-in caller returns

  • Caller Package Name
  • File name
  • Line number
  • Full Submenu
  • ... and a few more

Now we can add some code that registers the position of calls. We can either put the result in some data structure for automatic processing, or write the report to a log file. For instance.

 sub this_logs { { # seperate scope to not pollute your sub state $log_fh //= do { open my $fh, ">", "record_callsites.log"; # assuming autodie; $fh; }; state $seen = {}; my (undef, undef, undef, $sub) = caller(1); my ($package, $file, $line, ) = caller(0); my $site = $sub ? "$sub()" : "pkg $package"; unless ($seen->{$file}{$line}++) { say {$log_fh} "CALL from $site at $file line $line"; } } my ($param1, $param2) = @_; # etc } 

Assuming all your code was

 this_logs(1, 2, 3); # direct call foo(); # call from same package my $sub = "this_" . "logs"; baz($sub); # call by name Foo::bar(); # call from different package foo(); # duplicate call sub foo { return this_logs(5, 6, 7); } sub baz { shift()->(1, 2, 3); # no strict refs for this, please }; package Foo; sub bar { main::this_logs(); } 

This will create a log file.

 CALL from pkg main at - line 20 CALL from main::foo() at - line 28 CALL from main::baz() at - line 31 CALL from Foo::bar() at - line 3 

(File name means STDIN)

Therefore, given the appropriate test suite, it can find call sites for which the grepped command cannot be run.

If you have a non-monotic editor, you can also issue a script that opens each file one by one and positions the cursor on the correct line:

 say "kate -l $line $file"; say "vim +$line $file"; 
0
source

Source: https://habr.com/ru/post/1493591/


All Articles