# Best way to structure Julia code

**URL:** <https://discourse.julialang.org/t/best-way-to-structure-julia-code/26591>\
**Category:** General Usage\
**Tags:** question\
**Created:** [July 20, 2019, 4:59pm UTC](https://discourse.julialang.org/t/best-way-to-structure-julia-code/26591 "2019-07-20T16:59:13Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [July 20, 2019, 4:59pm UTC](https://discourse.julialang.org/t/best-way-to-structure-julia-code/26591/1 "2019-07-20T16:59:13Z")

</div>

Dear all,  
I am a bit sad that it was told here on the forum that adding a custom directory to the package search path would be depreciated.

If I write a Julia program I would like to structure it by using a module for each separate piece of code. But I want to have all my code in one git repository, and not one repo for each module.

Should every module be a package that lives in a separate repo? I think that would be stupid, because it causes lots of unnecessary overhead.

What do you think?

Uwe

---

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [July 20, 2019, 5:17pm UTC](https://discourse.julialang.org/t/best-way-to-structure-julia-code/26591/2 "2019-07-20T17:17:13Z")

</div>

Is there anything wrong with having one module per file, and storing all the files in the SRC folder?

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [July 20, 2019, 5:31pm UTC](https://discourse.julialang.org/t/best-way-to-structure-julia-code/26591/3 "2019-07-20T17:31:21Z")

</div>

This is what I would also like to continue to do, but it is not (yet) supported by the linter of vs-code, and Kristoffer Carlsson says:

> [@How to use local module within a Project directory?](https://discourse.julialang.org/t/how-to-use-local-module-within-a-project-directory/26358/4):
>
> I think there are some things in the loading of code that were put there to make the transition between the old package manager without Project files (0.6) to the new package manager (0.7) easier.
> 
> I would advise against touching `LOAD_PATH` and just use packages and `dev` for local code you want to reuse.

---

<div class="post-metadata">

**Author:** ![tuckermcclure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tuckermcclure/32/1187_2.png) [@tuckermcclure](https://discourse.julialang.org/u/tuckermcclure)\
**Post date:** [July 20, 2019, 6:06pm UTC](https://discourse.julialang.org/t/best-way-to-structure-julia-code/26591/4 "2019-07-20T18:06:45Z")

</div>

Hey @ufechner7, I agree with you. Just to be clear though, you can still break your code into modules; you’ll just need to know “where” the module is loaded. (e…g, `using ..MyModuleThatTheParentModuleLoadedAlready`). Since that’s not convenient for me (the reason mentioned in the post you linked), I’m no longer breaking my code into modules but rather just into a bunch of different files, and I include all of those files within the same module. Basically, I have one module: MyEntireProject, and it loads all of the necessary functions. There are certainly things about this approach that don’t work (maybe you don’t have just one big project but several), but for my big project anyway, everything kind of depends on everything else anyway, so it is working for me. Just my 2 cents on getting stuff working while hoping for a better way.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [July 20, 2019, 6:14pm UTC](https://discourse.julialang.org/t/best-way-to-structure-julia-code/26591/5 "2019-07-20T18:14:25Z")

</div>

> [@ufechner7](#):
>
> This is what I would also like to continue to do, but it is not (yet) supported by the linter of vs-code, and Kristoffer Carlsson says:

It is supported when you `include` the files which doesn’t need any change to `LOAD_PATH`. A `module` is just a namespace, there can be multiple modules in one file or one module spread out over other files.

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [July 20, 2019, 7:12pm UTC](https://discourse.julialang.org/t/best-way-to-structure-julia-code/26591/6 "2019-07-20T19:12:22Z")

</div>

Well, I don’t think that precompilation of modules works if you include them. Correct me if I am wrong.  
In addition exported type definitions of a module are not visible if the module is included, but are visible if it is used by “using ”.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [July 20, 2019, 7:35pm UTC](https://discourse.julialang.org/t/best-way-to-structure-julia-code/26591/7 "2019-07-20T19:35:33Z")

</div>

> [@ufechner7](#):
>
> Well, I don’t think that precompilation of modules works if you include them.

They are precompiled together with the toplevel module when it is loaded.

> [@ufechner7](#):
>
> In addition exported type definitions of a module are not visible if the module is included

You do

```julia
include("MyModule.jl")
using .MyModule

```

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [July 20, 2019, 7:40pm UTC](https://discourse.julialang.org/t/best-way-to-structure-julia-code/26591/8 "2019-07-20T19:40:57Z")

</div>

Thanks for your suggestion:

> [@kristoffer.carlsson](#):
>
> include(“MyModule.jl”) using .MyModule

It seams to work.

But it looks like an ugly workaround for me.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [July 20, 2019, 9:12pm UTC](https://discourse.julialang.org/t/best-way-to-structure-julia-code/26591/9 "2019-07-20T21:12:28Z")

</div>

> [@ufechner7](#):
>
> But it looks like an ugly workaround for me.

You need two lines, one to say where the module is and one to import it (with `using` or `import` etc.). That’s not much different from one line to modify the load path and another to import the module, so I really don’t see the problem.

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [July 20, 2019, 9:48pm UTC](https://discourse.julialang.org/t/best-way-to-structure-julia-code/26591/10 "2019-07-20T21:48:30Z")

</div>

You need to type the module name twice. And once with file name extension, brackets and quotes and once without all of this, but with a leading dot. Why is this simple task so complicated? In a good programming language simple tasks are simple. And this is not even documented in the manual.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [July 20, 2019, 11:18pm UTC](https://discourse.julialang.org/t/best-way-to-structure-julia-code/26591/11 "2019-07-20T23:18:51Z")

</div>

> [@ufechner7](#):
>
> You need to type the module name twice

No, you need to type the file where the module exist. There could be multiple modules in that file.

It seems you want something like [relative using/import should search current directory · Issue #4600 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/4600).

> [@ufechner7](#):
>
> Why is this simple task so complicated? In a good programming language simple tasks are simple.

This comes of as kinda obnoxious.

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [July 20, 2019, 11:26pm UTC](https://discourse.julialang.org/t/best-way-to-structure-julia-code/26591/12 "2019-07-20T23:26:57Z")

</div>

Thanks for providing a reference to the relevant issue. It would be nice if a solution would be implemented.

---

<div class="post-metadata">

**Author:** ![sdewaele](https://avatars.discourse-cdn.com/v4/letter/s/7ab992/32.png) [@sdewaele](https://discourse.julialang.org/u/sdewaele)\
**Post date:** [July 30, 2019, 8:33pm UTC](https://discourse.julialang.org/t/best-way-to-structure-julia-code/26591/13 "2019-07-30T20:33:54Z")

</div>

If I understand correctly, the following will be the case after the option to add to the search path is eliminated: **The only way to benefit from precompilation of a local module is to `dev` it**. Otherwise, one has to use the `include` method described above, and the module is recompiled.

This raises the following concern for me. My linux environment where I use Julia has no internet connection. Because of this, I am not able to use `dev`. Consequently, I have no option to get the speed gain associated with module precompilation.

Is this correct, or is there a solution for this situation?

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [July 30, 2019, 9:16pm UTC](https://discourse.julialang.org/t/best-way-to-structure-julia-code/26591/14 "2019-07-30T21:16:56Z")

</div>

Well, if you add the current directory to the module search path:

```julia
push!(LOAD_PATH, pwd())

```

and the use:

```julia
using <modulename>

```

then precompilation works. Only the vscode linter chokes, until the issue [https://github.com/julia-vscode/julia-vscode/issues/307](https://github.com/julia-vscode/julia-vscode/issues/307) is fixed.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [July 30, 2019, 9:29pm UTC](https://discourse.julialang.org/t/best-way-to-structure-julia-code/26591/15 "2019-07-30T21:29:25Z")

</div>

> [@sdewaele](#):
>
> This raises the following concern for me. My linux environment where I use Julia has no internet connection. Because of this, I am not able to use `dev` .

What do you mean? Devving a path doesn’t require any internet connection.

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [July 30, 2019, 11:10pm UTC](https://discourse.julialang.org/t/best-way-to-structure-julia-code/26591/16 "2019-07-30T23:10:57Z")

</div>

> [@ufechner7](#):
>
> Should every module be a package that lives in a separate repo? I think that would be stupid, because it causes lots of unnecessary overhead.
> 
> What do you think?

The structure that I use (and I think hasn’t yet been mentioned here) is having each module be a submodule of the global module associated to your project/package.

Submodules can `use` or `import` one another, provided that they provide either the correct relative path (with the right number of leading dots, which I find cumbersome) or an absolute path starting with the global module.

So something like this works (assuming you are in a project named “Top”):

```julia
module Top

# Potentially in a "A.jl" file
module A
export a
a() = "OK"
end

# Potentially in a "B.jl" file
module B
using Top.A
export b
b() = a()
end

using .B
export check
check() = b()

end # module

```

As already mentioned, this organization in top module + submodules is orthogonal to the organization of source files: using adequately placed `include`s, each submodule could be in its own file, or split in separate files, or all submodules could be grouped in one file.

As far as I know, everything works well with such a setup, including `Revise`, precompilation and so on.

---

<div class="post-metadata">

**Author:** ![sdewaele](https://avatars.discourse-cdn.com/v4/letter/s/7ab992/32.png) [@sdewaele](https://discourse.julialang.org/u/sdewaele)\
**Post date:** [July 31, 2019, 1:00pm UTC](https://discourse.julialang.org/t/best-way-to-structure-julia-code/26591/17 "2019-07-31T13:00:31Z")

</div>

Thanks. I misinterpreted your initial post as meaning that this option would no longer be available. Apart from the vscode issue, this does work indeed.

---

<div class="post-metadata">

**Author:** ![sdewaele](https://avatars.discourse-cdn.com/v4/letter/s/7ab992/32.png) [@sdewaele](https://discourse.julialang.org/u/sdewaele)\
**Post date:** [July 31, 2019, 6:04pm UTC](https://discourse.julialang.org/t/best-way-to-structure-julia-code/26591/18 "2019-07-31T18:04:58Z")

</div>

You are correct. Perhaps this was an issue in the past (\<v1.1); I tried again today and it works now. I had an other issue but this is related to write permissions to the environment folder. I could work around that by copying the Project/Manifest files to a dir where I do have write permissions, activate that environment and then `dev` my project.
