How do you emulate encapsulation or namespaces?

GAMS has no encapsulation. That is, all symbols, except for $setLocal, have global scope. This creates challenges when the code grows. I work with a model that has been developed during decades by a many contributors. A lot of the code consists of data preparation and reporting in various “modules”. For each new such module, the modeller possibly introduces new symbols - which become instantaneously available in all other modules downstream in the code. The risk of changing a symbol in one module in such a way that another module breaks increases when the number of symbols floating around in the memory amounts to hundreds or even thousands, many of which have similar yet distinct uses and meanings.

One way to make the code more structured and truly modular would be by code encapsulation, so that the scope of a symbol is limited to a certain unit of code. That is not currently possible in GAMS - or is it? But are there perhaps workarounds or other good practice in this respect? I could imagine working with something like “namespaces”, where the user would give the symbols prefixes separated by some character, like the dot “.”. For instance, one could declare

parameter module1.price(d1,d2) “Price used in module 1”;

to signal the scope to the developer. Clever editors or scripts could ensure that some modularization rules are not violated, i.e. the symbols are not used outside of their intended “scope”. This particular example doesn’t work because the dot is not permitted in this way. It would also look a bit odd with variables, where there can be suffixes that are also separated with a dot. But perhaps you have some other trick that works to the same effect that you would like to share?

A related topic would be the possibility of unit testing, but that merits its own topic. Please hint in a comment if a thread for unit testing in GAMS already exists here (I found none).

You could use one or more underscores for informal namespaces, but I agree that formal enforcement would be great.

For our very large model projects, I have found that it helps to use savepoints sparingly (r= and s=). Instead, we use gdx files to read and write values where this is a practical alternative.

E.g. a simple structure could look like

sets → variables → equations → calibration → export baseline gdx file

equations savepoint → read baseline gdx file → shock

Here, instead of using a savepoint after calibration, we use a gdx file to save all level changes from calibration. This makes it much easier to reason about the code, as the context window is reduced.
E.g. you can see directly where a value is loaded from in the local context, rather than having to trawl through to a large stack of code to find where the value was last changed.

I think unit testing is generally difficult for most simulation, but I would also be interested in seeing examples. We use the $abort statement for a lot of other tests, such as tests of aggregation or other variables that have to balance. E.g. balances of assets and liabilities across sectors in an economic model.
We do keep our models modular, which allows for running each module as a partial equilibrium model. Zero shock tests, where we run a model and check that nothing changes from its baseline calibration, is also a stable.

/Martin