>EVERY routine should be self-contained.
No. Every routine should have everything self-contained within itself where it makes sense to do so, but PUBLIC variables exist for a reason. They're a tool in the developer's toolbox, and it is inappropriate to avoid them categorically. For example, ON ERROR is a global feature of Visual FoxPro, and its demands are that variables related to its use also be of the same scope.
To debug global variables easily, use SET COVERAGE TO file.log, and then parse that log file through a tool, such as Martina Jindrova's awesome CVP ( see
http://gorila.netlab.cz/cvp.html and
http://gorila.netlab.cz/download/cvp/ ), which can take the log file and search for source code references, or even convert it to a log file with source code on each line (such as for documenting all of the program steps involved in doing some process, such as saving a customer record -- and just by running it), allowing the original source code variable name to be searched for in the converted log, to find the exact location where it's being populated.
The right tool for the right job.