Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine


by ait (Friar)
on Jan 02, 2011 at 17:48 UTC ( #880087=note: print w/ replies, xml ) Need Help??

in reply to Re: RFC: Tutorial "Introspecting your Moose code using Test Point Callbacks"















Comment on Re^2: RFC: Tutorial "Introspecting your Moose code using Test Point Callbacks"
Re^3: RFC: Tutorial "Introspecting your Moose code using Test Point Callbacks"
by ELISHEVA (Prior) on Jan 02, 2011 at 18:25 UTC


    You sound like you might be limited in the amount of refactoring you can do, but there is one technique I'd like to share, just in case it might fit and you find some opportunity to do some refactoring.

    Oftentimes, when a function turns big long and ugly and it doesn't make sense to refactor, the chief culprit is a large amount of state data shared among the different steps of a function. The classic example of such a function is a giant loop that is pushing and popping a stack in lieu of recursion, but there are other examples as well.

    In these cases I have often found it quite helpful to design and build a functor object. This is an object whose data is all that ugly automatic data shared throughout the function (in your case, it might be something like the current state of your scoring variables). Then I define a set of small focused functions each reading and setting the shared data as needed. This eliminates the need to pass lots of data between methods, but still allows me to break the long ugly function into small conceptual chunks.

    Nearly every time I do this, I watch the algorithm and all its problem areas unfold before my eyes. When each chunk of the algorithm has the breathing room to live in its own subroutine, I often become aware of a set of edge cases and conditions that ought to have been checked for but weren't. Something about code living in its own little home seems to invite a closer look at the algorithm and all of its associated if, ands, and buts. Furthermore, there is no longer a concern about all of those hairy conditions clouding up the overall logic because they are nicely encapsulated in a subroutine.

    Another advantage of this approach it that it becomes much easier to run just a part of the algorithm. If you want to run everything, you call the functor's run method. Since little data is being passed from subroutine to subroutine, this "run" method starts looking like a list of steps. Depending on your granularity needs you can sometimes break the list into a part A, B, and C and make each of those a subroutine and then run just a part of the algorithm, do some tests, then run another part. This would be much much harder to do if A, B, and C were wired together by data passed from one to another via parameters rather than shared from within the object.

    Just a thought.

    Update: explaining how a functor object can affect the ability to stop and start a process.

      Thanks again for your valuable input. I will definitely consider your functor recommendation. Regarding the use of callbacks to test or diagnose specific spots inside a function, do you see any situation where it can be useful? Or do you consider that it always boils down to a design or refactoring issue? Lastly, did my comments on these sub-tests as a way to diagnose a failed test make any sense?

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://880087]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (8)
As of 2014-12-26 20:12 GMT
Find Nodes?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?

    Results (175 votes), past polls