Global variables and program structure


#1

I am not proud of my program structure.

My code is contained within a single module,
my main variables are contained in 8 mutable composite types
sometimes with as many as 30 type-annotated fields.
Some of my functions create the main variables as const globals
and these are conveniently used at various places in other functions.
Exported variables and functions are used from the REPL.

I know that this is considered bad programming practice
and type inference may fail at some places.
So I have tried hard to pass these variables as arguments
to all my functions but I have never succeded.
With several call levels the code becomes too ugly
and quick program development becomes a pain.

I really expect the arrival of type-annotated globals,
and hope that any performance penalty will be gone.

But please advise:

  • Is this program structure really that terrible?
  • How do you arrange your code in a better way?

#2

One of the main problems with that style is that your logic is non-local and hard to debug.

Put your variables into structs, and pass those around (see Parameters.jl for some helper macros). Break your functions up into smaller ones which only do one thing and thus only need access to a few variables. Compose those smaller functions into larger ones.

There is definitely a trade-off between quick programming and writing maintainable code. But at least for bigger projects it does pay off as eventually there will be code maintenance and refactoring.


#3

My variables are already packed into structs.
Passing them around is the problem.

When variables are packed logically into 8 different structs
passing around various combinations of 8 different structs
as function arguments can become really complex.

Consider the extreme case:
One may pack ALL main variables (hundreds of them) into a SINGLE struct,
then only a single extra argument must be passed at each function call.

But is this really a better programming style?


#4

It is much easier to talk about program structure with concrete code in mind. If you post a minimal working example, you may get more specific advice. Sometimes the effort to create a MWE itself is helpful in reorganizing your program.


#5

I think this is an unlikely venue to get you a satisfactory answer to such a broad and not really Julia specific question. I see two possibilities how this forum could help you along: recommended books and example codes. If you are into physical models then this relatively simple code which calculates steady state subglacial drainage may be of use: https://bitbucket.org/maurow/rchannelode.jl.

Maybe someone knows a good book? Or more/better example packages?


#6

Thank you for the code example.
And yes, other examples are welcome.