Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Re: What are the core points of good procedural software design? (functions, code structuring)

by BrowserUk (Patriarch)
on Jun 23, 2008 at 15:14 UTC ( [id://693550]=note: print w/replies, xml ) Need Help??


in reply to What are the core points of good procedural software design? (functions, code structuring)

I realize that functions modifying globals is not a terribly good idea, but am not sure how to escape it.

It's gonna sound trite, but the easiest way to escape it, is to not do it! Because once you have started doing it (in any particular script), it becomes really hard to undo it.

For new (standalone) code, there are a couple of simple steps that will help you avoid it:

  1. Put all your subroutines at the top of your script.

    In particular, define all your subroutines before you declare any variables.

    By placing your 'main' code at the bottom of the script, it prevents you from using non-locally scoped variables within them and forces you to pass any information you require within them, via parameters.

  2. Never declare variables 'en-masse'.

    Only declare variables when, and where you need them.

    By declaring your variables where you first use them, you will naturally limit their scope. And limiting scope is the very essence of structured programming.

When it comes to trying to sort out existing spaghetti code, there are two schools of thought:

  • Make minimal changes commensurate with achieving your goal.
  • Re-write from scratch.

Which of these is applicable will depend very much upon your immediate goals. There is no one right answer.

If your goal is to add a new smallish feature to an existing, working script in a hurry, the minimal changes route is often the best way to go. That includes, unfortunately, perpetuating existing bad practices against your better judgement. Trying to re-write or even just re-structure existing code to accommodate new features can lead to disastrous consequences, especially if time pressures are involved.

It can often save time in the long run, to go with the flow and add the new feature in the existing style in order to meet the immediate goal, and leave restructuring until things are stable. Restructuring should always be tackled from a position of a known and stable base. That is, don't try to both re-structure and add new features at the same time. You'll never be sure that whether bugs and deficiencies you encounter are a result of the restructuring, or the new features. And it will usually be some subtle, and untraceable, interaction of the two.

By restructuring the existing, working code, regression testing becomes a usually relatively simple process of substituting the restructured script for the original in a realistic scenario, preferably using inputs and outputs derived from live operations, and checking that they do the same thing. This is usually far quicker than trying to generate comprehensive test scripts to exercise all aspects of the existing script, which can be an extremely difficult and costly process. Made even more costly as much of it will need to be discarded and/or re-written to suite the new script if it is extensively re-structured.

It's also the case that trying to re-structure existing code, using existing unit test scripts for verification often leads you into making the same structural choices, and mistakes as were made for the script you are re-structuring. Hence, defeating some or all of the purpose of the exercise. By limiting regression testing to matching the overall output for one or more sets of realistic inputs, you free yourself from the design constraints and mistakes of the original authors.

Only once the re-structured script (or module) has been verified against what it is to replace, and preferably exercised in-situ for a while in the live system, should you consider adding new features to it. Of course, if the re-structuring is prompted by the need for a new feature and the difficulty (perceived or actual), of adding it to the existing code, then this implies deferring that addition until the re-structuring is done and dusted. And that can be politically difficult to propose. But in the long term, separating the two steps will nearly always prove less costly.

However, there is nothing to stop you from acknowledging the requirements of the new feature(s) during your re-structuring exercise, and catering for them in advance.


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".
In the absence of evidence, opinion is indistinguishable from prejudice.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (5)
As of 2024-03-28 13:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found