Once upon a time, it was realized that human beings couldn't reliably hold an entire program inside their heads at once, so it was necessary to subdivide tasks into subtasks small enough to grasp.

The trouble with globals to maintain state is that it "breaks encapsulation", you get "action-at-a-distance" between your subtasks, i.e. you don't have something small enough to hold in your head.

So from there, you get to the idea that we should write "pure functions" where all arguments are explicitly passed in to the routine, and all returns are explicity passed out of it, and there are no "side-effects".

The trouble is that if you actually try to write large software projects that way it often gets pretty awkward: if you end up passing in a few dozen pieces of information and returning a dozen, that straight-jacket starts feeling pretty tight.

So, is there some sort of compromise solution? OOP design, with multiple classes is one of them -- but another, very similar one, is proceedural design with multiple modules. These days I have a slight preference for OOP code, but as far as scoping concerns go, the two are close to identical. The main advantage of OOP (in my opinion) is that the namespaces of the things you're using are always labeled by a short alias, i.e. the names of the objects: consider $Some::Hairy::Name::Space::important_variable, vs the Exporter style of important_variable, vs the OOP style of $shns->get_important_variable.

As to what do do to refactor your hairy code, I'd suggest:

Okay, now here's a possible strategy for getting the globals under control:

After all that, with any luck you'll be in a position to subdivide this module into multiple modules, one centered around each of the hashes. You could even, you know, bless those hashes, and then you've got perl object classes.

How do you deal with routines that need to work on more than one of the hashes? In the OOP style, you can do things like pass objects into a method as arguments. That just changes the way you unpack the values a little (if you're being good and using accessors).

All of this work might not be worth it to you of course, but the early stages of what I'm talking about here (moving the code to a module and writing tests) is bound to be helpful even if you don't complete the program.


In reply to Re^4: What are the core points of good procedural software design? (functions, code structuring) by doom
in thread What are the core points of good procedural software design? (functions, code structuring) by Anonymous Monk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.