-
Notifications
You must be signed in to change notification settings - Fork 35
Description
As I'm working on the Composite Component feature, I'm also exploring alternative approaches to implement this type of recursive structure conveniently, efficiently, and maintainably in julia.
Several things I'd like to address at some point (after we've got all the julia 1.0 stuff cleaned up):
- The standard approach to organizing code in julia makes it a little difficult to reason about the code without searching the text to see where things are used. Contributing to this are:
-
Mimi.jl has most of the "using ..." statements for the entire pkg. As noted in issue Modify approach to "using xxx" statements #214, I would prefer to have each jl do its own "using ..." statement. See that issue for more info.
-
Mimi.jl also exports all public names. I wonder if it would be better to have each jl file export its own "public" names. This keeps the information more local to where it's defined, although a user cannot just look at Mimi.jl to see the public API, but they can run
names(Mimi)
to retrieve this.
- I'd like to know when functions and variables are private to files.
-
Using a single module (Mimi) for everything means we only have exported and non-exported names, but no way to indicate "private to a file" other than convention. We can use the leading-underscore (
_foo
) convention from Python, but I'd prefer something more rigorous. -
One option is to use sub-modules. For example, the file
build.jl
could define within itmodule build
, surrounding all the code in the file, and thenusing .build
. We would explicitly export all names that (i) are intended for use elsewhere in Mimi, (ii) are part of the public API, in which case the names would be re-exported in Mimi.jl. All names defined inMimi.build
that are not exported become effectively private to the file.
- The best approach to general code organization still isn't obvious. Types have to be defined before they can be referenced, which creates an ordering problem. In the first big overhaul, I organized the code roughly into types (which get loaded first), and large-ish files with definition-related, instance-related, and model-related code. I find that having the types separated from the methods integral to their function is not ideal.
- One approach I'd like to consider is to refactor the code so that each type is defined in its own file, along with functions that require only that type and those loaded before it. This will make for a big PR, but we can ensure that for that PR, nothing changes other than the location of code. Alternatively, we can do this refactoring in stages (e.g., one type at a time) to keep it manageable.