http://www.perlmonks.org?node_id=622705

You have a code fragment that can be grouped together

Turn the fragment into a method whose name explains the purpose of the method

(Fowler, p.110)

Fowler's first refactoring pattern is probably the most intuitive and the one I use 90% of the time when I'm refactoring. That's part of the reason I'm going through these patterns, because I know there are plenty of other useful ones out there (there are 72 in the book after all).

Here is Fowler's example in Perl code:

sub print_owing{ my $self = shift; my $e = $self->{_orders}->elements(); my $outstanding = 0.0; # print banner print "**************************\n"; print "***** Customer Owes ******\n"; print "**************************\n"; # calculate outstanding while ( $e->has_more_elements() ){ my $each = $e->next_element(); $outstanding += $each->get_amount(); } # print details print 'name: ', $self->{_name}, "\n"; print "amount: $outstanding\n"; }

becomes:

sub print_owing{ my $self = shift; $self->print_banner(); my $outstanding = $self->get_outstanding(); $self->print_details( $outstanding ); } sub print_banner{ my $self = shift; # print banner print "**************************\n"; print "***** Customer Owes ******\n"; print "**************************\n"; } sub print_details{ my $self = shift; my $outstanding = shift; print 'name: ', $self->{_name}, "\n"; print "amount: $outstanding\n"; } sub get_outstanding{ my $self = shift; my $e = $self->{_orders}->elements(); my $result = 0.0; # calculate outstanding while ( $e->has_more_elements() ){ my $each = $e->next_element(); $result += $each->get_amount(); } return $result; }

Fowler outlines the intricacies through example in three steps but I won't go into that much detail here because I think it's pretty straight forward. You should really buy the book if you're interested. The code with tests include the steps in the refactoring process so you can see the whole thing in Perl.

Instead, I'd like to discuss how I've written the unit tests for the example, as testing is an important part of the refactoring process and writing tests for the refactoring patterns will likely require some decent understanding of Perl unit testing methodologies.

There are three non-standard modules that I use in the tests for this code: Test::MockModule, Test::MockObject and Test::Output. The first two are very useful for working with tests for incomplete modules / classes -- which is the case here -- or situations where you don't want to do a great deal of setup of environmental factors just to test a single method / subroutine. Test::Output is very useful to testing code that generates STDOUT or STDERR as this code does. In order to run these tests, you'll need these three modules. I highly recommend Ian Langworth and chromatic's Perl Testing, A Developer's Notebook if you're not comfortable with writing and maintaining tests.

In the case of the test for Refactoring::ExtractMethod::*, I use Test::MockModule to mock up a new method rather than include it in the class itself. I also used Test::MockObject to put together a quick and dirty object for the _orders object variable. For the purpose of this example it may be overkill, but this is generally how I like to write my tests: isolate the test to the functionality of the method we are testing. Of course this will come back to bite me in the very next refactoring example, but we'll get to that later :)

For now I'll be keeping one tarball of all of the code and I'll update it when I have additional code to share. I'm not sure that's a good long term option, and I'm open to suggestions -- I might CPAN it if I can maintain momentum here.

I welcome comments and conversation on all aspects of this example: implementation of the example in Perl, testing methodology, tactics for maintaining this series of posts, what have you.

perl -e 'split//,q{john hurl, pest caretaker}and(map{print @_[$_]}(joi +n(q{},map{sprintf(qq{%010u},$_)}(2**2*307*4993,5*101*641*5261,7*59*79 +*36997,13*17*71*45131,3**2*67*89*167*181))=~/\d{2}/g));'