BrowserUk has asked for the wisdom of the Perl Monks concerning the following question:

I'm refactoring a piece of code that uses $x, $y, $z. There are 6 repetitions of a large chunk of code that are essencially identical, but for the 'ordering' of those three variables.

This is ripe for refactoring into a subroutine called 6 times. Ie:

if( $x ) { doStuff( $x, $y, $z ); doStuff( $x, $z, $y ); } if( $y ) { doStuff( $y, $x, $z ); doStuff( $y, $z, $x ); } if( $z ) { doStuff( $z, $x, $y ); doStuff( $z, $y, $x ); }

But here is a dilemma I've encountered many times before, what do you name the 3 variables inside the sub:

sub doStuff { my( $?, $?, $? ) = @_; .... }

I know it's trivial, just call'em $p, $q, $r or $u, $v, $w or $a, $b, $c I hear the collective mind screaming, but it is a large and fairly complex piece of code, and $x, $y, $z are actually placeholders for a bunch of different entities that have x, y & z components all interacting and it gets quite confusing -- here's one of the 6 blocks in the code I'm adapting:

So my question is, is there some technique or pattern or something that has been devised to deal with this? Have you arrived at some way of dealing with this situation that works for you?


With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority". I'm with torvalds on this
In the absence of evidence, opinion is indistinguishable from prejudice. Agile (and TDD) debunked

Replies are listed 'Best First'.
Re: Refactoring technique?
by hdb (Monsignor) on Apr 24, 2015 at 12:54 UTC

    Not sure what your question is. Just naming of parameters? If they have specific roles, find a name corresponding to that role. If they are interchangeable strings call them $text1, $text2, $text3.

      Not sure what your question is. Just naming of parameters?

      Yes & no. Imagine you're the programmer charged with looking at this code (see the spoiler) a couple of years from now, and you're trying to make sense of $text1, $text2, & $text3 in context.

      If they have specific roles, find a name corresponding to that role.

      Again, take a look at the code in spoiler. Can you see a "name corresponding to that role"? <P.Or for a better sense of the scale of the problem:

      • look at the original code;
      • find the function called _BoundingBoxDraw();
      • and then look for the 6 blocks that begin with the line:<code>gg=_GetGrid( ... );</c>

      The 3 parameters need to be substituted everywhere that x, y, or z are used within that block, but sometimes the first parameter will be the x component of all the things; sometimes the y; sometimes the z; and so on for the other two parameters.

      Within the context of 3D code x, y, z give some sense of what the thing you're dealing with is; text1, text2, text3 don't.

      Similarly, for u, v, w; but it's worse, because you intuitively think of them as being placeholders for x, y, z respectively, but they aren't. Or rather sometimes they will be but mostly they will be some other ordering.

      Similarly, if you use numbers -- say $xyz1, $xyz2, $xyz3 -- we tend to associate them to some ordering, even though we know that any one of the formal parameters could be any one of the actual parameters.

      Its just something that has recurringly given me pause for thought each time I've encountered it down the years and I've never really come up with a good solution/approach to the problem.


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority". I'm with torvalds on this
      In the absence of evidence, opinion is indistinguishable from prejudice. Agile (and TDD) debunked

        Now I got you. For my education (I have never used js), how do you parameterize x, y and z anyway. You have a lot of something.x and somethingelse.y. If you would want to write doStuff( u, v) how would you use u and v in the code?

Re: Refactoring technique?
by flexvault (Monsignor) on Apr 24, 2015 at 15:31 UTC

    Hello BrowserUk,

      So my question is, is there some technique or pattern or something that has been devised to deal with this?

    I look at the subroutine as providing a specific function, so I would name the input parameters as how they relate to the specific function. It really doesn't matter where the input values come from, but what is the purpose of the subroutine. So if the sub is going to build a box, then I would design the sub as:

    # my $graphic = buildbox( $x, $y, $z ); sub buildbox { my $length = shift; my $height = shift; my width = shift; ... }
    To the maintainer, it should be obvious what the subroutine does and not how it gets called! YMMV.

    Regards...Ed

    "Well done is better than well said." - Benjamin Franklin

      It really doesn't matter where the input values come from, but what is the purpose of the subroutine.

      You're right! Until I can give doStuff( ... ): a proper name, the parameter names are always going to be a compromise.

      The problem is that the 6 blocks of code that will be replaced by the calls to doStuff(), do an aweful lot of stuff; so understanding all the stuff they do sufficiently to give it an appropriate name is quite a challenge. More so as I'm working in a language I'm only barely familiar with, and the author has made some ... what you might term politely .. dubious choices.

      Eg. The code is littered with calls to a function called _OAV(), which is annotated with //Object, Attribute, Value. It looks like this:

      Which is just horrible!


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority". I'm with torvalds on this
      In the absence of evidence, opinion is indistinguishable from prejudice. Agile (and TDD) debunked

        Which is just horrible!
        Ewww. Agreed.

        It seems to me that the purpose of this is to dispatch the setting of attributes. Perhaps setAttrDispatcher( obj, attr, value ). Still ick. Longer (of course, that is hard not to be), and still confusing (where does useSVG come from, for example).

        update: small bit of cleanup and clarification

        --MidLifeXis

        BrowserUk,

        WOW! Now I understand!

        So the new sub would be:

        # my $WhoKnows = SeeOriginalAuthorForMoreInformation( $oo, $aa, $vv ); + sub SeeOriginalAuthorForMoreInformation { my $Object = shift; my $Attribute = shift; my $Value = shift; ... }
        I guess the author wants you to be a miracle worker :-)

        It wouldn't be so bad if you could move 'to' and 'from' to a different subroutine. Good Luck!

        Regards...Ed

        "Well done is better than well said." - Benjamin Franklin

Re: Refactoring technique?
by marinersk (Priest) on Apr 24, 2015 at 12:57 UTC

    I'd be inclined to generalize the subroutine names to reflect the category of use.

    For example, if these are axis coordinates, I'd be inclined to call the parameters $coord1, $coord2, and $coord3, or something similar. Since I'm a huge fan of the 2x3 naming standard, it would probably be more like $genco1, $genco2, and $genco3.

      I'd be inclined to call the parameters $coord1 , $coord2 , and $coord3

      But imagine your coming into this code a year from now, aren't you going to mentally substitute $x, $y, $z for $coord1 , $coord2, & $coord3 respectively?

      Since I'm a huge fan of the 2x3 naming standard

      I don't think I've ever heard of that; and Google didn't find anything likely except your post?

      (Is that the US military thing of SecNav for Secretary of Navy?)

      it would probably be more like $genco1 , $genco2 , and $genco3

      As in General Coordinate N? (Yuck! :)


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority". I'm with torvalds on this
      In the absence of evidence, opinion is indistinguishable from prejudice. Agile (and TDD) debunked

        Yes, you've read me correctly. There are few who like my approach to naming variables, so I translate into those yucky inconsistent-length variable names when others are likely to be subjected to reading my code.

        One engineer, after modifying some of his code to match my naming convention, indicated he really did like the way his code lined up, but he just couldn't bring himself to de-Englishify his variables names just so the code lined up nicely.

        I don't Clark other people's code, and I do try to play along when the code isn't going to be strictly mine, but I find a serene and refreshing beauty in consistency and functional abbreviation.

        In that, I am definitely a Rare Bird.

        Sorry, missed the other question in your post. 2x3was probably just a local name for the standard.

        Back when Chad an 8-character limitation on identifiers, the use of TLAs was common (TLA = Three-Letter Abbreviation). There were also odd occasions when it still made sense under the conventions of the day to have non-array repetitions (very rare, but greater than zero occurances).

        So the standard just sort of naturally developed out of the other coding standards in play at the time, where function/instance combinations just sort of rolled off our fingers. Variables started taking on forms like:

          inpfnm  Input filename
        outfnmOutput filename
        INPFILInput file handle (technically a stream pointer in C)
        OUTFILOutput file handle
        genpos01General Position 1
        genpos02General Position 2

        It was an ugly standard, seen from today's descriptive tendencies, but for old mainframe hacks and formatting pedants such as myself, it seemed a thing of beauty and joy; concise, predictable, and sensible.

        It was a marked improvement to the other mainframe tendency of the day to simply remove the vowels, yielding unwieldy names that begged for typos and were of inconsistent length in the source code ( MRCHNT_VNDR_ID -- yuck!)

        Like I said in another post, I try to be kind to normal people when others have to read my code; but if I expect to be the only user, all my blocks line up nicely, and I quietly revel in my control-freak haven of bliss.

Re: Refactoring technique?
by Anonymous Monk on Apr 24, 2015 at 14:09 UTC

    If the elements have no individual meaning, why name them at all? Make them unnamed array members.

    use Algorithm::Combinatorics ':all'; foreach (permutations([$x, $y, $z])) { doStuff($_) if $_->[0]; }

      That makes a lot of sense, but in context, may be rather harder to achieve than in your snippet.


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority". I'm with torvalds on this
      In the absence of evidence, opinion is indistinguishable from prejudice. Agile (and TDD) debunked