# Proper way of organizing code into subpackages

**URL:** <https://discourse.julialang.org/t/proper-way-of-organizing-code-into-subpackages/52835>\
**Category:** New to Julia\
**Tags:** packages, code-organization\
**Created:** [January 4, 2021, 5:34pm UTC](https://discourse.julialang.org/t/proper-way-of-organizing-code-into-subpackages/52835 "2021-01-04T17:34:30Z")\
**Posts on this page:** 9\
**Page:** 3

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [August 22, 2022, 8:37pm UTC](https://discourse.julialang.org/t/proper-way-of-organizing-code-into-subpackages/52835/42 "2022-08-22T20:37:18Z")

</div>

> [@patrick-kidger](#):
>
> Adding methods to a function defined somewhere else is _mutating global state_, and this is a Bad Thing.
> 
> If I could, I would have this be prohibited by the compiler.

Are you proposing that the compiler disallow multiple dispatch?

> [@patrick-kidger](#):
>
> It is completely possible to use Python-style `from pkg import foo`, as the success of [FromFile](https://github.com/Roger-luo/FromFile.jl) has demonstrated.

Unfortunately, I don’t think FromFile really achieves the dependency management that you want it to achieve. I’m away from my computer, so I’ll just link to two old comments, [here](https://discourse.julialang.org/t/implicitly-loaded-modules-in-the-future/62646/265) and [here](https://discourse.julialang.org/t/implicitly-loaded-modules-in-the-future/62646/266), that explain why I think `@from` doesn’t provide real dependency management.

---

<div class="post-metadata">

**Author:** ![patrick-kidger](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/patrick-kidger/32/20378_2.png) [@patrick-kidger](https://discourse.julialang.org/u/patrick-kidger)\
**Post date:** [August 23, 2022, 10:50am UTC](https://discourse.julialang.org/t/proper-way-of-organizing-code-into-subpackages/52835/43 "2022-08-23T10:50:58Z")

</div>

I am not advocating prohibiting multiple dispatch.

What I am suggesting is that the compiler should prohibit exactly the kind of shenanigans you link to as being the “problems” with FromFile. That is to say, mutating global method tables wrt types you don’t own, etc.

Anyway, I’ll leave things there. Obviously I am no longer a Julia user anyway, so I don’t really have any stake in this any more.

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [August 23, 2022, 12:14pm UTC](https://discourse.julialang.org/t/proper-way-of-organizing-code-into-subpackages/52835/44 "2022-08-23T12:14:35Z")

</div>

> [@patrick-kidger](#):
>
> What I am suggesting is that the compiler should prohibit exactly the kind of shenanigans you link to as being the “problems” with FromFile. That is to say, mutating global method tables wrt types you don’t own, etc.

The second example that I linked to uses `Int` and `Float64`, but it could just have easily used custom types that I own and it would have come to exactly the same conclusion. Besides, in that example I own the function `bar`, so it’s perfectly valid to define `Int` and `Float64` methods for `bar`.

---

<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:** [August 23, 2022, 7:50pm UTC](https://discourse.julialang.org/t/proper-way-of-organizing-code-into-subpackages/52835/45 "2022-08-23T19:50:39Z")

</div>

> [@patrick-kidger](#):
>
> That is to say, mutating global method tables wrt types you don’t own, etc.

Would this be similar in concept to a sealed class from Kotlin or Java where the subclasses must be known at compile time?

> **[Sealed classes and interfaces | Kotlin](https://kotlinlang.org/docs/sealed-classes.html)**

I’ll coin the term “Sealed Module” to mean a module from which it is error to explicitly or implicitly `import` any of its contents into another module. You can still do `using` to bring them into your namespace, but you would be prevented from extending the methods.

---

<div class="post-metadata">

**Author:** ![alastair-marshall](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alastair-marshall/32/21418_2.png) [@alastair-marshall](https://discourse.julialang.org/u/alastair-marshall)\
**Post date:** [August 23, 2022, 8:07pm UTC](https://discourse.julialang.org/t/proper-way-of-organizing-code-into-subpackages/52835/46 "2022-08-23T20:07:26Z")

</div>

> [@patrick-kidger](#):
>
> Obviously I am no longer a Julia user anyway, so I don’t really have any stake in this any more.

This is why I always appreciate your thoughts when you post, you’ve got experience on both sides and that’s really useful. Especially when it comes to comparisons between Julia and JAX

---

<div class="post-metadata">

**Author:** ![adienes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/adienes/32/37459_2.png) [@adienes](https://discourse.julialang.org/u/adienes)\
**Post date:** [August 24, 2022, 12:57pm UTC](https://discourse.julialang.org/t/proper-way-of-organizing-code-into-subpackages/52835/47 "2022-08-24T12:57:46Z")

</div>

I am starting to feel (at least, based on those comments that you linked) that you are suggesting that since all methods are “global” they should not be organized into modules—if this is not what you’re implying please correct me, as I do not mean to put words in your mouth. I very much agree with @patrick-kidger that seems like a dangerous way to live.

In your example

```julia
module DemoPackage
       
	module A
		struct S end
		foo(::S) = 1
	end
	
	module B
		import ..A: foo
		struct T end
		foo(::T) = 2
	end
	
	module C
		import ..A: foo
		struct U end
		foo(::U) = 3
	end
	
	import .A: S
	import .B: T
	import .C: foo, U
	export foo, S, T, U

```

I would expect `foo` (upon importation from `DemoPackage`) to be only defined on type `U` (and subtypes). I do not think the choice of which module to import it from should be arbitrary. If one wants to be able to call `foo(S)` then I think one should have to import the method from `A` as well.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [August 24, 2022, 1:27pm UTC](https://discourse.julialang.org/t/proper-way-of-organizing-code-into-subpackages/52835/48 "2022-08-24T13:27:48Z")

</div>

> [@adienes](#):
>
> If one wants to be able to call `foo(S)` then I think one should have to import the method from `A` as well.

I’m not agreeing not disagreeing, one may prefer one way or the other. But when you do `import ..A: foo` you are very explicit saying that you want to extend the functionality of the function defined in `A`, and that means what it means in Julia: adding a method to a global method table of that function.

One can always _not_ import the function from the other module, and define a new function. And we can then, if wanting to be strict use something like:

```julia
julia> module A
           foo(x::Int) = 1
       end
Main.A

julia> module B
           foo(x::Float64) = 2
       end
Main.B

julia> import .A: foo

julia> foo(x::Float64) = B.foo(x)
foo (generic function with 2 methods)

```

to then only extend the functionality of the function to the type you want.

---

<div class="post-metadata">

**Author:** ![adienes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/adienes/32/37459_2.png) [@adienes](https://discourse.julialang.org/u/adienes)\
**Post date:** [August 24, 2022, 1:52pm UTC](https://discourse.julialang.org/t/proper-way-of-organizing-code-into-subpackages/52835/49 "2022-08-24T13:52:11Z")

</div>

> [@lmiq](#):
>
> But when you do `import ..A: foo` you are very explicit saying that you want to extend the functionality of the function defined in `A`, and that means what it means in Julia: adding a method to a global method table of that function.

Gotcha, thanks for clarifying. I think I would almost always prefer something more like the latter pattern (or really, something like)

```julia
module A
    foo(x::TypeOwnedByA) = ...
end

module B
    foo(x::TypeOwnedByB) = ...
end

import .A: foo
import .B: foo

```

I feel pretty strongly that if I define a method in module `A`, and I later import that method in module `B`, that the behavior should only depend on how it’s defined in `A` (or extended in `B`), and not whatever extensions I or some other developer have added in a tertiary module `C`, unless I explicitly import the method from `C` as well.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [August 24, 2022, 2:04pm UTC](https://discourse.julialang.org/t/proper-way-of-organizing-code-into-subpackages/52835/50 "2022-08-24T14:04:07Z")

</div>

> [@adienes](#):
>
> and not whatever extensions I or some other developer have added in a tertiary module `C`, unless I explicitly import the method from `C` as well.

Type-piracies apart, that is what you get, as the fact that a function has a method for a type you are not aware about should not be important.

Alternatively one can simply not import at all the functions, and just use them qualified by the modules (i. e. call with `B.foo(x)`, `A.foo(x)`) which is somewhat more organized, but you are giving up on the flexibility of multiple dispatch then.

[Previous page](https://discourse.julialang.org/t/proper-way-of-organizing-code-into-subpackages/52835.md?page=2)
