About Kent Cowgill
Articles filed under...
abs ab_ripper andylester arms back baggyshorts bestpractices biceps bike birthday blog bugs bus calculator cardio catalyst cgi chart chest chinups code cpan datamodel dbi doctor documentation exercise exhaustion fitness flattire flat_tire google gps heart_rate helmet history home houston html humor journal kate kenpo kenpo_x kettlebell knees lazy legs lisa lisanne maps math matthew michaelmckenna mom montreal motivation movie mysql oops orm P90X pain park patellar_tendonitis patrick pdf perl phb photos physical_therapy plyometrics poor_gait presentation procrastination progress pullups pushups pyramid rabbits racecondition rant refactor rest ribs ride route running shoulders situps slides sore spike sql statistics syntax test testing textile timex training triceps ups versioncontrol video vim vimrc walk warren work workouts yapc yapcna2007 yoga youtube

A R C H I V E S

(3)
(1)
(3)
(2)
(7)
(15)
(16)
(25)
(3)
(4)
(2)
(4)
(11)
(1)
(1)
(3)
(2)
(2)
(10)
(5)
(2)
(3)
(4)
(9)
(21)
(3)
(3)
(1)
(6)
(4)
(1)
(4)
(3)
(2)
(1)


    Is Kent Cowgill Online?
    View Kent Cowgill's profile on LinkedIn
    Add to Technorati Favorites

    Recent Entries...

    Re: Re: Yoga kicks my butt

    Chris @ 46: Tatyana @ 21 – at best its a stop gap measure...

    Re: Vibram FiveFingers FTW

    Hats off to whoever wrote this up and potesd it....

    Re: A little more detail on using a new model

    百度 [url=http://www.sina.com]sina[/url] ...

    Re: Catching up through week 7

    testing video ...

    Re: Porting a non-Moose object to Moose

    Wow, look what I found, greedy genius ...

    Re: Porting a non-Moose object to Moose

    Kevin, You're right, that does seem a little confusing. ...

    Re: Porting a non-Moose object to Moose

    Wait. I'm confused. Moose isn't the tool to reach for. So...

    Re: Porting a non-Moose object to Moose

    You should switch to MooseX::Types to declare your Typed and...

    Porting a non-Moose object to Moose

    I'm currently working with a lot of legacy code in an envi...

    Testing strategy for mocking code

    I keep finding myself using the following idiom for writing ...

    weblog | `web·lôg -läg |
    noun
    Another term for BLOG
    ORIGIN 1990s: from web in the sense [World Wide Web] and log in the sense [regular record of incidents.]
    blog | bläg |
    noun
    A web site on which an individual or group of users produces an ongoing narrative.
    ORIGIN a shortening of WEBLOG.

    Indirect confusion

    Kent Cowgill

    I'm really not understanding something. I've run into a module for which I had a lot of difficulty writing the first few tests. This usually happens when the module under scrutiny does something a little weird, so I'm used to it by now.

    But this one is a lot weird.

    The code for the module I'm looking at is structured exactly like this:

    package foo;

    use strict;
    use warnings;

    sub firstSub {
      my $string_orig = shift;

      # in the production code, this
      # somehow works and doesn't die
      my $string = secondSub $string_orig;

      return ( foo => $string, bar => $string_orig );
    }

    sub secondSub {
      my $string = shift;
      my $ret = join '', reverse split //, $string;
      return $ret;
    }

    1;

    What's strange is that when I use the module and try to call "firstSub", I get a Can't locate method object secondSub via package VALUE_PASSED at line blah, of course substituting VALUE_PASSED for whatever value I actually pass :) But the module - as is - works on the development server, and has worked on the production server for years with this exact structure and syntax.

    So for this example, this code (reduced to the smallest example that still exhibits the behavior, but essentially the same structure) tries to call the modules' subroutine via:

    use foo;

    my %q = foo::firstSub( 'MTFNPY' );
      
    print "$_: $q{$_}" for keys %q;

    And the output I get is:

    Can't locate object method "secondSub" via package "MTFNPY" (perhaps you forgot to load "MTFNPY"?) at foo.pm line 13.

    A little boggling. I tried a few things, including this ugliness:

    {
      no warnings 'once';
      *MTFNPY::secondSub = \&foo::secondSub;
    }

    ... but of course that will only work as long as I'm passing the value of "MTFNPY".

    Running the code through B::Deparse confirms that line is interpreted as my $string = $string_orig->secondSub.

    I see I've got a couple of options:

    1. Fix the code minimally - re-order the subroutines inside the module so the second subroutine is defined first, so it will be correctly interpreted as a function call.
    2. Fix the code a little less minimally - add parens around the argument to secondSub.
    3. Fix* my tests and don't touch the original code until my tests are complete so I am 100% certain I don't break anything else. (I'm fairly sure either of these changes won't, but "fairly" isn't 100%).

    * By which I mean 'just make it work'

    So, I add this near the top of my test file:

    BEGIN {
    package foo;
      use subs 'secondSub';
    }
    use_ok( 'foo' );

    ... which basically tells the interpreter that package foo will be defining a subroutine called secondSub, which is to say predeclaring them - before the foo module has a chance to load, by taking place inside a BEGIN block.

    And lo, testing successful.

    But what I still don't understand is how exactly the code in the original module works at all! I'm testing on the same box where the code lives - where the code runs day in and day out without bringing the test server down to a screeching halt. I know - I added trace debugging statements all around, thinking that perhaps the code has always been silently failing and the failure was just dealt with. But no, the code was making it through that step and doing exactly what my predecessor(s) expected it to do. It's just doing it wrong.

    Related Photos: perl

    Main Page | Login

    Do you want to buy me ? Find more gift ideas at my wishlist