# How to structure project in julia

**URL:** <https://discourse.julialang.org/t/how-to-structure-project-in-julia/99458>\
**Category:** New to Julia\
**Created:** [May 26, 2023, 7:12pm UTC](https://discourse.julialang.org/t/how-to-structure-project-in-julia/99458 "2023-05-26T19:12:59Z")\
**Posts on this page:** 9\
**Page:** 3

<div class="post-metadata">

**Author:** ![zgornel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zgornel/32/217487_2.png) [@zgornel](https://discourse.julialang.org/u/zgornel)\
**Post date:** [May 28, 2023, 11:53am UTC](https://discourse.julialang.org/t/how-to-structure-project-in-julia/99458/42 "2023-05-28T11:53:11Z")

</div>

I see what you mean. The approach you took seems to me a sound one to take despite the drawbacks which I believe are present everywhere. Furthermore, this reminds me of - if I remember correctly - The Cathedral and the Bazaar by Eric Raymond where he posits that a way for devs to stay engaged and happy is to be owners of their software (by owners I mean sole developers with some autonomy and ideally, copyright). In that case it was more like moving the module inter communication from internal API (case for big corporations and software systems) to external/public APIs relying on some OS provided protocol i.e. file IO for UNIX for example. I wonder if this may be a barrier for development of very large codebases w internal APIs, as @MacKa 's observations seem to point to.

---

<div class="post-metadata">

**Author:** ![caleb-allen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/caleb-allen/32/14054_2.png) [@caleb-allen](https://discourse.julialang.org/u/caleb-allen)\
**Post date:** [May 28, 2023, 3:53pm UTC](https://discourse.julialang.org/t/how-to-structure-project-in-julia/99458/43 "2023-05-28T15:53:38Z")

</div>

> [@zgornel](#):
>
> The Cathedral and the Bazaar by Eric Raymond

As an aside, this piqued my interest and I just finished reading it. What a great essay! The Julia project is clearly set up as a Bazaar, and I think that comes with some surprises to certain users. Areas without polish are really just problems waiting to be solved by whomever is able

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [May 28, 2023, 6:53pm UTC](https://discourse.julialang.org/t/how-to-structure-project-in-julia/99458/44 "2023-05-28T18:53:06Z")

</div>

Sorry, late for the discussion, but let me give my two cents:

**The best option is a mix of options 2 and 4, which by themselves are not really options I see someone considering.**

> [@MacKa](#):
>
> ### 2. Use include
> 
> Include file followed by .using
> 
> ```julia
> #file ModuleB.jl
> module ModuleB.jl
> include("ModuleA.jl")
> using .ModuleA
> ...
> end
> 
> ```
> 
> This doesn’t work when more than one dependency includes the same file due to lack of include once semantics, there is no `#pragma once` or `#ifdef` to my knowledge, I rate this option as worse than C.

> [@MacKa](#):
>
> ### 4. Create one monolithic file
> 
> Create one main julia file per project, all files are included into the monolith:
> 
> ```julia
> #file ModuleB.jl
> module ModuleB.jl
> # no dependencies declared here
> ...
> end
> #file Monolith.jl
> include("ModuleA.jl")
> include("ModuleB.jl")
> 
> ```
> 
> Only downsides:
> 
> - modules can’t declare their dependencies
> - files must be included in topological order
> - files/modules become just inlines, they can’t be executed/tested in julia
> - worse than C, it’s not 1970 anymore
> - over my dead body option

A submodule should only be `include`d where it appears in the hierarchy for an external user. If a package `Graphs.jl` has `Graphs.Algorithms` then `Algorithms.jl` should be `include`d inside `Graphs.jl`, if it is `Graphs.Utilities.Algorithms` then then `Algorithms.jl` should be `include`d inside `Utilities.jl` which is `include`d inside `Graphs.jl`. In other words, `include` should be only used to build the unique hierarchy of the modules in the project, it is not a tool to load code that will just be called. What however, if `Graphs.Experimental.Search` needs to use some methods from `Graphs.Utilities.Algorithms`? Simple, in `Search.jl` you do:

```julia
import ...Utilities.Algorithms

```

See [Modules · The Julia Language](https://docs.julialang.org/en/v1/manual/modules/#Submodules-and-relative-paths) about the relative import syntax.

I structured a rather large package with all my code from my PhD following this system. Here is the main file: [https://github.com/henriquebecker91/GuillotineModels.jl/blob/master/src/GuillotineModels.jl](https://github.com/henriquebecker91/GuillotineModels.jl/blob/master/src/GuillotineModels.jl) and here is the file of `GuillotineModels.PPG2KP`: [https://github.com/henriquebecker91/GuillotineModels.jl/blob/master/src/PPG2KP/PPG2KP.jl](https://github.com/henriquebecker91/GuillotineModels.jl/blob/master/src/PPG2KP/PPG2KP.jl) Note that I did also started a new subfolder for each submodule that had submodules themselves to avoid clashes like two `Algorithm.jl` in a `Graphs.Utilities.Algorithms` and a `Graphs.Experimental.Algorithms`.

---

<div class="post-metadata">

**Author:** ![filchristou](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/filchristou/32/26760_2.png) [@filchristou](https://discourse.julialang.org/u/filchristou)\
**Post date:** [May 30, 2023, 7:31pm UTC](https://discourse.julialang.org/t/how-to-structure-project-in-julia/99458/45 "2023-05-30T19:31:58Z")

</div>

One common pain point I find with nested modules is that each time you need to redefine all `using` and `import` dependencies. For my use cases it is pretty obvious that a nested module should have **at least** the same dependencies and namespace visibility as its parent. I see how this could create much noise in multi nested cases, but in my opinion if you don’t want this, you probably don’t even need nested modules. (Happy to hear counter use-cases)  
Such a feature could probably be implemented with a macro, but unfortunately macros don’t play well with LSP, since this aspect was already mentioned above.

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [May 30, 2023, 7:55pm UTC](https://discourse.julialang.org/t/how-to-structure-project-in-julia/99458/46 "2023-05-30T19:55:47Z")

</div>

> [@filchristou](#):
>
> One common pain point I find with nested modules is that each time you need to redefine all `using` and `import` dependencies.

You could just refer to the parent module’s namespace instead of redoing the import.

```julia
julia> module A
           export helloworld
           helloworld() = println("Hello World")
       end
Main.A

julia> module B
           using ..A
           module C
               import ..B
               foo() = B.helloworld()
           end
       end
Main.B

julia> B.C.foo()
Hello World

```

If you want exactly the same imports as the parent module, I’m less clear on why one would need a nested module to begin with as well.

Also for some Reexport.jl may be useful.

> **[GitHub - simonster/Reexport.jl: Julia macro for re-exporting one module from...](https://github.com/simonster/Reexport.jl)**
>
> Julia macro for re-exporting one module from another - GitHub - simonster/Reexport.jl: Julia macro for re-exporting one module from another

---

<div class="post-metadata">

**Author:** ![filchristou](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/filchristou/32/26760_2.png) [@filchristou](https://discourse.julialang.org/u/filchristou)\
**Post date:** [May 31, 2023, 5:47am UTC](https://discourse.julialang.org/t/how-to-structure-project-in-julia/99458/47 "2023-05-31T05:47:47Z")

</div>

You are right, `@reexport` can already do this.  
A small example for reference, since I already tested it:

```julia
module A
    using Reexport
    @reexport using Graphs
    export s3

    s3() = SimpleGraph(3)
    s5() = SimpleGraph(5)
    module B
        # using Graphs # --> this line is not needed anymore
        using ..A
        s1s3s5() = [SimpleGraph(1), s3(), A.s5()]
    end
end

```

---

<div class="post-metadata">

**Author:** ![filchristou](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/filchristou/32/26760_2.png) [@filchristou](https://discourse.julialang.org/u/filchristou)\
**Post date:** [May 31, 2023, 6:08am UTC](https://discourse.julialang.org/t/how-to-structure-project-in-julia/99458/48 "2023-05-31T06:08:10Z")

</div>

On thinking this twice, @reexport will nicely propagate the dependencies in inner modules, but it will also pollute the user’s session in case the user makes a `using A`. So I wouldn’t prefer it for more complex (and realistic) scenarios. I think the unique solution is to write the boilerplate code (e.g. the `using Graphs` etc.).  
The question is why nested modules start with a 0 dependencies (e.g. Graphs) and don’t inherit their parent’s ? Or, to be more dramatic, what features do nested modules actually bring into the table, that are developer attractive ? (other than logically categorizing structs/functions which is mostly user-focused)

---

<div class="post-metadata">

**Author:** ![zgornel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zgornel/32/217487_2.png) [@zgornel](https://discourse.julialang.org/u/zgornel)\
**Post date:** [June 5, 2023, 5:43pm UTC](https://discourse.julialang.org/t/how-to-structure-project-in-julia/99458/49 "2023-06-05T17:43:04Z")

</div>

> [@filchristou](#):
>
> The question is why nested modules start with a 0 dependencies (e.g. Graphs) and don’t inherit their parent’s ? Or, to be more dramatic, what features do nested modules actually bring into the table, that are developer attractive ?

I think such a behavior may create dependency problems (i.e. create depedency cycles) and would be most unwelcome. The rule is namespace isolation for safety. Therefore the developer is required to be explicit or intentional.

For example, in clean architecture patterns (i.e. where functional dependencies run only towards the higher level modules), one should only import the interfaces (in Julia, import functions to be overloaded for example) that the parent module exposes as such (although such thing is not enforced in Julia; happens at package level with all the modules ending in `<SomethingSomething>Base`). This makes it easier to work independently on larger codebases as only changes to the interface will break lower level functionality and changes to lower level code will not affect higher level functionality. More on this stuff [here](https://en.wikipedia.org/wiki/Dependency_inversion_principle). I am not sure if this is the case - but the `Pkg` dependency resolver should handle this sort of things at higher level and I remember some efforts years ago towards this - probably long solved by now.

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [June 5, 2023, 6:15pm UTC](https://discourse.julialang.org/t/how-to-structure-project-in-julia/99458/50 "2023-06-05T18:15:24Z")

</div>

> [@filchristou](#):
>
> On thinking this twice, @reexport will nicely propagate the dependencies in inner modules, but it will also pollute the user’s session in case the user makes a `using A`. So I wouldn’t prefer it for more complex (and realistic) scenarios. I think the unique solution is to write the boilerplate code (e.g. the `using Graphs` etc.).

Create an inner module that `@reexport`s what you want. Use that module for all your internal modules.

> [@filchristou](#):
>
> The question is why nested modules start with a 0 dependencies (e.g. Graphs) and don’t inherit their parent’s ? Or, to be more dramatic, what features do nested modules actually bring into the table, that are developer attractive ?

The main feature for me is that it helps to segment my code into parts that have distinct group of dependencies. The other feature is that it creates a namespace.

Overall, it is better that Julia imports less by default. It is then much easier to customize Julia to do exactly what you want.

[Previous page](https://discourse.julialang.org/t/how-to-structure-project-in-julia/99458.md?page=2)
