Hey there Julians!
I’m still a bloody beginner with Julia, but want to start with a medium size OOP-structured project. (I’m also a CS student, so I’m still learning how to engineer software the right way)
I started writing a prototype of a project(a board game), but I started running in so many issues related to project structure, usage of modules and submodules etc… and tools - I want autocomplete and the linter(VSCode) to work!
I haven’t found any good resource in the last 2 weeks, where someone outlines a good strategy in a detailed way. I’ve read many threads, which answered many questions, but still not all.
I’ve picked up all the Julia Packt Books, but I haven’t found something specific regarding this topic. In one book (Best Practices and … Julia Packt - something like this) the author suggested in a very short side note to use “types.jl” file to define all your types.
I’m not sure which way is the best practice (in a OOP-like style/way) in Julia. I think I’ve found kind of 3 ways how I could handle this. If there are other ways you are welcome to share them!
Side Note: I would love to be able to use autocomplete and linter, I think this can’t work at the moment for some strategies - for example splitting the code in files (but not submodules) and include the files in the main package file. I think here the linter and autocompleter wouldn’t work - correct me if I’m wrong!
In the following I’m showing my project in a very simplified way. I’ve written it only with this editor, so probably this code isn’t runnable and has some mistakes, but I think you get the differences and my resulting question out of it.
The main problem is, that some structs contain/use other structs as DataTypes. The Character is on the Node position. The Game Board is built of many Nodes. The GameSystem is moving a Character to a different Node. Even more that’s not included in this example: A character has tickets to move from node to node. Node connections require specific tickets to travel a character from one to the other. Maybe just my software design is completely screwed up? (Are these Circular Dependencies?)
Please share any resources you have on this topic - especially best practices.
Or are there any lightweight, easy understandable example projects, where I could learn how to build mid scale projects in a OOP-like way in Julia?
Using only Submodules - OOP like way (Feels wrong, too cumbersome and dangerous for a bigger project)
GameBoard.jl
module GameBoard
using ..GameNode
export Board, z
struct Board
gameNodes::Vector{Node}
end
function z()
...
end
end
GameCharacter.jl
module GameCharacter
using ..GameNode
export Character, y
struct Character
positionOnBoard::Node
end
function y()
...
end
end
GameNode.jl
module GameNode
export Node, x
struct Node
name::String
index::Int64
end
function x()
...
end
end
GameSystem.jl
module GameSystem
include("GameNode.jl")
using .GameNode # Probably not necessary
include("GameBoard.jl")
using .GameBoard
include("GameCharacter.jl")
using .GameCharacter
struct System
board::Board
characters::Vector{Character}
end
function init()
...
end
end
Using a file with all defined types/“Classes” (Feels just not right and not too readable and not enough OOP-like)
Types.jl
module Types
export Node, Character, Board, System
struct Node
name::String
index::Int64
end
struct Character
positionOnBoard::Node
end
struct Board
gameNodes::Vector{Node}
end
struct System
board::Board
characters::Vector{Character}
end
end
GameBoard.jl
module GameBoard
using ..GameNode
export z
function z()
...
end
end
GameCharacter.jl
module GameCharacter
using ..GameNode
export y
function y()
...
end
end
GameNode.jl
module GameNode
export x
function x()
...
end
end
GameSystem.jl
module GameSystem
include("Types.jl")
using .Types
include("GameNode.jl")
using .GameNode # Probably not necessary
include("GameBoard.jl")
using .GameBoard
include("GameCharacter.jl")
using .GameCharacter
function init()
...
end
end
Using a different hierarchy (Feels completely confusing and not applicable for real world use - big projects)
GameBoard.jl
module GameBoard
include("GameNode.jl")
using .GameNode
export Board, z
struct Board
gameNodes::Vector{Node}
end
function z()
...
end
end
GameCharacter.jl
module GameCharacter
using ..GameBoard.GameNode
export Character, y
# any other export for GamenNode needed?
struct Character
positionOnBoard::Node
end
function y()
...
end
end
GameNode.jl
module GameNode
export Node, x
struct Node
name::String
index::Int64
end
function x()
...
end
end
GameSystem.jl
module GameSystem
include("GameBoard.jl")
using .GameBoard
# using .GameBoard.GameNode # Explicit using needed?
include("GameCharacter.jl")
using .GameCharacter
struct System
board::Board
characters::Vector{Character}
end
function init()
...
end
end