That's a decision to be made on a case by case basis. A tradeoff among a lot of factors.
In general I try to avoid SHARED items at all, but I don't let that ideal get in the way of getting the job done. You can get to a point where parameter lists become unwieldy but in general passing parameters is probably the way to go.
One thing to consider is wrapping up a "blob" of data items you need to use in several procedures within a module - inside a TYPE. Then pass instances of that TYPE as parameters. Of course there is a performance tradeoff, any simple data (integer types, etc.) is probably better passed as BYVAL on its own where that makes sense.
You asked about arrays though.
Well if you can allocate an array inside a Sub/Function, pass it around, and then deallocate it by exiting the scope of the original routine... you might save a lot of DGROUP storage by reusing it over time. By default such arrays are DYNAMIC, and using REDIM instead of DIM forces this if needed.
http://support.microsoft.com/default.asp...-US;Q58926 is worth a look too.
Maybe somebody else can point you to a more comprehensive guide.
I have a hard time explaining my own strategy. Over the years I've developed a sort of sense of what "feels right" and it tends toward passing parameters. I know what "feels wrong" too but I still do it if the alternative becomes too convoluted. Of course my gut feeling could be 100% wrong in a lot of cases.
The real tradeoffs are speed vs. size vs. readability and maintainability.
Well, I'll throw in "getting the dumb thing to work" as a factor as well. :wink:
The defaults and the general rules can also vary for programs run from the IDE vs. compiled as an EXE too.