An interface is a contract between two parts of a program.
It sets a Protocol that guarantees a functionality.
It provides vertical communication between layers. And it also defines the layers' borders.
The protocol describes and prescribes the "expected behavior" (a specification) while the library is an "actual implementation" of this set of rules. Precisely stating what is expected of a supplier of a service and a user of that service is essential. Having good (easy-to-understand, encouraging efficient use, not error-prone, supporting testing, etc.) interfaces is probably the most important single aspect of code organization.
Correctness. Assumptions not stated in an interface are easily overlooked and hard to test.
Sometimes we control the details of a set of operations by an environment variable, e.g., normal vs. verbose output or debug vs. optimized. The use of a non-local control is potentially confusing, but controls only implementation details of otherwise fixed semantics.
A function should not make control-flow decisions based on the values of variables declared at namespace scope.
A function should not write to variables declared at namespace scope.
Singletons are basically complicated global objects in disguise.
Types are the simplest and best documentation, improve legibility due to their well-defined meaning, and are checked at compile time.
Also, precisely typed code is often better optimized.
Elaborate from there if necessary.
If you need many parameters, probably you are missing an abstraction. Or violating the rule
One function, one task.
Life is already prone to confusion enough.
Differentiate the inputs, the processed, and the outputs.
If you can’t give the service, rethink the contract.
Don’t improvise a similar unsatisfactory solution.
Accept your fate and go a step back.
Compilation is writing down the layers, to computer instructions. If you are not going to layer it, better go directly to machine language.