Organizing structures and action functions into files

Hello everyone,
I have a question about organizing structures and action functions into files.
In Julia’s programming paradigm, we usually first identify the nouns of a problem and implement the corresponding struct for each noun. Then, we identify the verbs and realize how different nouns interact with each other. This is equivalent to implementing functions that describe the interaction of different structures.

For example, I am writing a code to simulate a person eating different fruits (both CPU and GPU):

## person.jl
struct Person
end

struct PersonGPU
end
## apple.jl
struct Apple <: Fruit
end

function eat!(p::Person, fruit::Apple)
end

function eat!(p::PersonGPU, fruit::Apple)
end
## banana.jl
struct Banana <: Fruit
end

function eat!(p::Person, fruit::Banan)
end

function eat!(p::PersonGPU, fruit::Banana)
end

Basically, I put the action eat! for each fruit right after its struct declaration. So, if I add more fruits in the future, I can easily look up (and hence manage) the eat! function for each fruit.

However, if I do this, I will be coupling Person with Fruit (?) To avoid this, I can move all eat! functions into a separate file:

## eat.jl

function eat!(p::Person, fruit::Apple)
end
function eat!(p::PersonGPU, fruit::Apple)
end

function eat!(p::Person, fruit::Banan)
end
function eat!(p::PersonGPU, fruit::Banana)
end

It looks cleaner than the first approach. But it might be more difficult to find (or manage) the corresponding eat! function for a fruit. If the number of fruits increases, I might need to do a keyword search in the file eat.jl.

What would be your suggestion? Thanks.

There’s no right answer, but I put method definitions in the same file as the type definition. They have to go after the type definition anyway, and that makes it easiest to check whether a method for that type exists.

If a method is more generic – e.g. something like read_json(filename) – I would make a file called json.jl, and put json-related utilities there.

Remember that you only need type declarations for multiple dispatch. In the example you gave, it would probably be possible to make a method that works on both Person and PersonGPU, and thus I would condense them into two methods eat!(p, fruit::Apple), eat!(p, fruit::Banana) instead of four.