# Architecture: general module and specific module

**URL:** https://discourse.julialang.org/t/architecture-general-module-and-specific-module/47127
**Category:** New to Julia
**Tags:** design
**Created:** [September 23, 2020, 10:10am UTC](https://discourse.julialang.org/t/architecture-general-module-and-specific-module/47127 "2020-09-23T10:10:10Z")
**Posts on this page:** 19
**Page:** 1

<div class="post-metadata">

### Author: ![misha\_mikhasenko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/misha_mikhasenko/32/5060_2.png) [@misha\_mikhasenko](https://discourse.julialang.org/u/misha_mikhasenko)
#### Post date: [September 23, 2020, 10:10am UTC](https://discourse.julialang.org/t/architecture-general-module-and-specific-module/47127/1 "2020-09-23T10:10:10Z")

</div>

I guess I am lacking knowledge of design patterns,  
can someone suggest the right solution (common in Julia) to set of specific modules that reexport general module functionality with one argument inserted?

The general module defines functions that depend on a `state` (require the state as an input).  
I what to have a set of specific modules that do not require typing the `state` explicitly.

```julia
module General

export state, st1, st2
struct state{T}
   par1::T
   par2::T
end

st1 = state(1.1, 2.2)
st2 = state(2.2, 3.3)

# methods
export calculation, someothercalculation
calculation(x, s::state) = 2x * s.par1 + s.par2
someothercalculation(x, s::state) = 3x * s.par1 + s.par2

end

```

The specific modules implement the same methods for specific states, these are now for single-argument.

```julia
module Specific1

using Reexport
@reexport using General

export st
st = st1

import General: calculation, someothercalculation
calculation(x) = calculation(x,st)
someothercalculation(x) = someothercalculation(x,st)

end

```

to create `Specific2` I actually would duplicate the `Specific1` code except for the `st = st1` line,  
that become `st = st2`.

There must be a better way.

---

<div class="post-metadata">

### Author: ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)
#### Post date: [September 23, 2020, 10:45am UTC](https://discourse.julialang.org/t/architecture-general-module-and-specific-module/47127/2 "2020-09-23T10:45:22Z")

</div>

I think I don’t fully understand your use cases for `Specific1` and `Specific2`. Do they both operate on the same types and define the same functions? Are they just “workspaces” to perform calculations on a single instance of `State{Float64}`?

---

<div class="post-metadata">

### Author: ![misha\_mikhasenko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/misha_mikhasenko/32/5060_2.png) [@misha\_mikhasenko](https://discourse.julialang.org/u/misha_mikhasenko)
#### Post date: [September 23, 2020, 11:28am UTC](https://discourse.julialang.org/t/architecture-general-module-and-specific-module/47127/3 "2020-09-23T11:28:03Z")

</div>

ah, yes, I oversimplified, perhaps. The point is that a lot of functionality is shared between `Specific1` and `Specific2`, but they might contain some different functions.

The use cases are as follows:

#### file: `my_first_analysis.jl`

```julia
using Specific1

data = load_sample()
results = calculation.(data)

@save "results1.jld2" results  

```

#### file: `my_second_analysis.jl`

```julia
using Specific2

data = load_sample()
results = calculation.(data)

@save "results2.jld2" results  

```

---

<div class="post-metadata">

### Author: ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)
#### Post date: [September 23, 2020, 11:54am UTC](https://discourse.julialang.org/t/architecture-general-module-and-specific-module/47127/4 "2020-09-23T11:54:18Z")

</div>

So to see if I understand correctly, `Specific1` exports `calculations`, which is defined as

```julia
# where `Specific1.st1` is some global const.
Specific1.calculation(x) = General.calculation(x, st1) 

```

This doesn’t seem like a case where you want two different modules. Rather you should use a function to do the work, and perhaps multiple dispatch or higher order functions as necessary. Consider, for example:

```julia
using General: calculation, State

# Returns a function that wraps st. Maybe this is 
# incorporated into the General api if very common
# and necessary?
make_specific(f, st) = x -> f(x, st)

# used as in
data = load_data()
st1 = State(1.1, 2.2)
calc_st1 = make_specific(calculation, st1)

results = calc_st1.(data)
@save "results1.jld2" results  

```

Alternatively, you could wrap all the state-dependent computation you want to in a function that takes in the state. For example,

```julia
using General: calculation, State

function do_the_thing(st, data, filename)
    # using Ref to broadcast the entire `st` with 
    # each element of data. Maybe this was holding you back?
    results = calculation.(data, Ref(st))
    @save "$filename.jld2" results   
end

#used as in:
data = load_data()
do_the_thing(State(1.1, 2.2), data, "results1")

```

One of these two is probably the design paradigm you want.

---

<div class="post-metadata">

### Author: ![misha\_mikhasenko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/misha_mikhasenko/32/5060_2.png) [@misha\_mikhasenko](https://discourse.julialang.org/u/misha_mikhasenko)
#### Post date: [September 23, 2020, 1:36pm UTC](https://discourse.julialang.org/t/architecture-general-module-and-specific-module/47127/5 "2020-09-23T13:36:03Z")

</div>

thanks for the thoughts, that is useful.

the problem is that I have ~100 functions that need to be redefined for a specific state.  
I want to hide this redefinitions to a module that can be easily imported (it cannot be the general one).

Once I am done with the analysis of the `st1`. I want to move on to the analysis of `st2` without duplicating redefinition code.

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [September 23, 2020, 1:40pm UTC](https://discourse.julialang.org/t/architecture-general-module-and-specific-module/47127/6 "2020-09-23T13:40:44Z")

</div>

> [@misha\_mikhasenko](#):
>
> I have ~100 functions that need to be redefined for a specific state

I don’t know the details of your problem, so maybe this is justified, but it looks like a code smell.

When designed idiomatically, even complex APIs in Julia have about 5–15 core functions, and a couple more optional ones for performance optimizations etc.

---

<div class="post-metadata">

### Author: ![misha\_mikhasenko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/misha_mikhasenko/32/5060_2.png) [@misha\_mikhasenko](https://discourse.julialang.org/u/misha_mikhasenko)
#### Post date: [September 23, 2020, 1:41pm UTC](https://discourse.julialang.org/t/architecture-general-module-and-specific-module/47127/7 "2020-09-23T13:41:40Z")

</div>

The second approach with `do_the_thing(st, ...)` is a good one.  
While `the thing` gets too specific with many dependencies, so it is hard to make a good function out of this.

---

<div class="post-metadata">

### Author: ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)
#### Post date: [September 23, 2020, 1:48pm UTC](https://discourse.julialang.org/t/architecture-general-module-and-specific-module/47127/8 "2020-09-23T13:48:00Z")

</div>

> [@misha\_mikhasenko](#):
>
> the problem is that I have ~100 functions that need to be redefined for a specific state.  
> I want to hide this redefinitions to a module that can be easily imported (it cannot be the general one).
> 
> Once I am done with the analysis of the `st1` . I want to move on to the analysis of `st2` without duplicating redefinition code.

The first part suggests you may need a (slight) refactoring. The second is a sentiment I strongly agree with!

For example, if `calculation` is already defined in `General` as

```julia
calculation(x, st) = # something that uses st and x together

```

then, strictly speaking, a version `calculations(x)` may be 1. not necessary, 2. more trouble than it’s worth. You already have a perfectly general function that can handle arbitrary states!

The user of `General` (you, if you’re running the analyses yourself) can simply call a function (or several – but certainly not 100) like `do_the_thing` that pass the `state` as far into the callstack as it needs to go.

---

<div class="post-metadata">

### Author: ![misha\_mikhasenko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/misha_mikhasenko/32/5060_2.png) [@misha\_mikhasenko](https://discourse.julialang.org/u/misha_mikhasenko)
#### Post date: [September 23, 2020, 7:04pm UTC](https://discourse.julialang.org/t/architecture-general-module-and-specific-module/47127/9 "2020-09-23T19:04:26Z")

</div>

The `state` in the previous example is something fundamental that you would like to fix once and use throughout the whole analysis. I would have it `const` defined once on the general module.

I am trying to come up with a good analogy for my real case.  
Let’s say, I study the dynamics of falling objects on the Earth. My `state` contains the gravitational acceleration, speed of sound, air viscosity (I am making things up).

All calculations depend on these parameters or their derivatives, but I do not want to pull them as an argument. I am never interested in how results depend on these parameters because I cannot change them.

I have got a similar project on Venus, I need to do almost the same calculations, with different fundamental parameters.

Do you see what I mean?

---

<div class="post-metadata">

### Author: ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)
#### Post date: [September 23, 2020, 7:34pm UTC](https://discourse.julialang.org/t/architecture-general-module-and-specific-module/47127/10 "2020-09-23T19:34:35Z")

</div>

Sure, I think so. Should I assume the “state” is (or could/should be) a global `const`? If so, you could make it e.g. a mutable struct (or a dict, etc.) so that its parameters can be redefined if needed. For example

```julia
# inside General

const STATE = Dict(:g => 9.8)

some_calc(x) = 0.5 * x * STATE[:g]^2

# if you already have a version with st, like you said, 
# you can have global state as the default, with optional
# second argument
some_calc(x, st = STATE) = 0.5 * x * st[:g]^2

```

Then `General` can also define a method for overwriting the state in case the user needs it to change.

```julia
function edit_global_state!(;kwargs...)
    for (k, v) in kwargs
        STATE[k] = v
    end
end

# allows:
# edit_global_state!(g = 11.23)
# to set :g

```

By the way, the other paradigms I mentioned would still work just fine in the astrodynamics case. For example, a user could do

```julia
# let's say Earth is exported for user convenience:
some_calc(parameters, Earth) 
# can also set Earth to be default positional:
some_calc(parameters)  

some_calc(parameters, General.Jupiter) # not exported
some_calc(parameters, Planet(1,1,1,1)) # user-defined

```

As a final note, if _nothing_ I’ve said so far is the right fit, (first of all, sorry!) then I really need to know more about the use case to see how it is unique (these are all the most standard and common approaches in Julia). I’m happy to look through source code if you care to post or link.

---

<div class="post-metadata">

### Author: ![misha\_mikhasenko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/misha_mikhasenko/32/5060_2.png) [@misha\_mikhasenko](https://discourse.julialang.org/u/misha_mikhasenko)
#### Post date: [September 23, 2020, 7:52pm UTC](https://discourse.julialang.org/t/architecture-general-module-and-specific-module/47127/11 "2020-09-23T19:52:25Z")

</div>

Fantastic. Yes, that is it, I think.

It seems that I can write my code

```julia
using General
set_planet!(:earth)

```

no specific modules.

Perhaps, even

```julia
# inside General
mutable struct conditions
    st::state
end

const used_conditions = conditions(state(0,0,0,0))

function set_planet!(planet)
   planet == :earth && used_conditions.st = state(1,1,1,1)
   planet == :venus && used_conditions.st = state(1,2,2,3)
end

```

🎆🎆🎆

---

<div class="post-metadata">

### Author: ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)
#### Post date: [September 23, 2020, 8:16pm UTC](https://discourse.julialang.org/t/architecture-general-module-and-specific-module/47127/12 "2020-09-23T20:16:48Z")

</div>

Great! Note that there could be a performance hit to using a mutable struct for this (could be minimal; hard to say), so for any high performance stuff, I suggest passing `used_conditions.st` in as early in the stack as reasonable.

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [September 23, 2020, 8:25pm UTC](https://discourse.julialang.org/t/architecture-general-module-and-specific-module/47127/13 "2020-09-23T20:25:20Z")

</div>

This is perhaps analogous to how Plots.jl does it. You load Plots, and then you set the backend (unless you want the default):

```julia
using Plots
plotly() # select backend

```

This function call presumably sets up a lot of ‘constant’ state.

---

<div class="post-metadata">

### Author: ![misha\_mikhasenko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/misha_mikhasenko/32/5060_2.png) [@misha\_mikhasenko](https://discourse.julialang.org/u/misha_mikhasenko)
#### Post date: [September 23, 2020, 8:54pm UTC](https://discourse.julialang.org/t/architecture-general-module-and-specific-module/47127/14 "2020-09-23T20:54:58Z")

</div>

good point.  
Still, I guess it should not be slower than the general call `calculation(x, st)`.  
The fastest way, I suppose, would be to compile with `const st = state(1,1,1,1)`. Not clear how to achieve that without code duplication in the original post, tho.

Nevertheless, I think I am satisfied with the solution for now.

---

<div class="post-metadata">

### Author: ![Olivier\_Merchiers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/olivier_merchiers/32/4073_2.png) [@Olivier\_Merchiers](https://discourse.julialang.org/u/Olivier_Merchiers)
#### Post date: [September 26, 2020, 9:18am UTC](https://discourse.julialang.org/t/architecture-general-module-and-specific-module/47127/15 "2020-09-26T09:18:54Z")

</div>

That’s an interesting comment.  
Could you point me to a package that follows those principles?  
Thanks

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [September 26, 2020, 9:21am UTC](https://discourse.julialang.org/t/architecture-general-module-and-specific-module/47127/16 "2020-09-26T09:21:31Z")

</div>

I would start with

[https://docs.julialang.org/en/v1/manual/interfaces/](https://docs.julialang.org/en/v1/manual/interfaces/)

as a nice example of API design.

---

<div class="post-metadata">

### Author: ![Olivier\_Merchiers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/olivier_merchiers/32/4073_2.png) [@Olivier\_Merchiers](https://discourse.julialang.org/u/Olivier_Merchiers)
#### Post date: [September 26, 2020, 9:29am UTC](https://discourse.julialang.org/t/architecture-general-module-and-specific-module/47127/17 "2020-09-26T09:29:25Z")

</div>

Thanks for the quick answer.  
I’ve read that part of the manual few times already. It is indeed a very nice example. But I always struggle a bit to relate that to scientific computing.  
If I would look at one of your packages, which one would you recommend?  
Thanks again

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [September 26, 2020, 11:35am UTC](https://discourse.julialang.org/t/architecture-general-module-and-specific-module/47127/18 "2020-09-26T11:35:29Z")

</div>

I don’t think my packages are in any way exemplary, but eg

[https://tamaspapp.eu/LogDensityProblems.jl/dev/#log-density-api-1](https://tamaspapp.eu/LogDensityProblems.jl/dev/#log-density-api-1)

has a very sparse API.

---

<div class="post-metadata">

### Author: ![Olivier\_Merchiers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/olivier_merchiers/32/4073_2.png) [@Olivier\_Merchiers](https://discourse.julialang.org/u/Olivier_Merchiers)
#### Post date: [September 26, 2020, 6:20pm UTC](https://discourse.julialang.org/t/architecture-general-module-and-specific-module/47127/19 "2020-09-26T18:20:46Z")

</div>

Thank you very much!
