In The Stata Journal Vol. 9, No. 3, 2009 there's a Stata tip (# 77) on re-using macros in multiple do-files, by Jeph Herrin. His solution is to define any local macros in a separate do-file, say locals.do. You can call that do-file with the include command at the top of any do-file that might refer to some of those macros. This is useful, as the author explains, when you want to keep all your macro definitions in one easily editable place, and make them available to whatever projects can use them without having to duplicate the definitions. This is similar to how you would #include header files in C or C++.

Unfortunately, include does not work well with programs. You can invoke it inside a program but include itself cannot be compiled, so the do-file it refers to will have to be interpreted all over again every time you call that program: see help include for the original reference. This negates the speed advantage that you expect when you package your Stata work into programs as opposed to simple do-files. It does not negate all the other advantages -- such as better code portability and the possibility of unit testing -- but still, speed matters. My own solution is to define locals inside an r-class program. Then other programs that need some of these locals call that program, and recover only the locals they need. Below is one example, worked first with include and then with my proposed alternative:
 

// locals.do starts here
local file_path "c:/data/my_path/"
local file_name "file_name.dta"
local my_file    "file_path'file_name'"
// and ends here.

 

OK, now let's put these locals to work:
 

// work.do starts here:
include locals.do
use "my_file'"

 

Alright. This is not bad and it does the job that your locals are neatly separated from the rest of the work. If you use do-files to split a big job into smaller pieces, this is all you need. If, on the other hand, you want to chop the job into pieces smaller still, and encapsulate those pieces into programs, then this is inadequate, as explained above.

The workaround might look like a bit more overhead, but then that's the usual cost of writing programs instead of plain do-files. Some of us, sometimes, find that overhead acceptable:
 

capture prog drop defineMyLocals
program defineMyLocals, rclass

local file_path "c:/data/my_path/"
local file_name "file_name.dta"
local my_file    "file_path'file_name'"

local things "file_path file_name my_file"
foreach thing in things' {
return local thing' thing''
}

end

 

And now let's recover the local my_file':
 

defineMyLocals
local my_file r(my_file)'
use "my_file'"

 

That's it. Your locals.do consists of the definition of the program defineMyLocals. The overhead is obvious. First, adding new locals inside this definition requires the extra step of adding their names to the things list, so that defineMyLocals can return them. Second, using defineMyLocals is also slightly more complicated than a simple include, because you need to recover the locals you need explicitly, via `r()'.

That said, now your locals are defined inside a program, and you can move them around faster. If you're like me and you favor programs over do-files and this isn't your solution, then I'd be curious to see your preferred alternative.