Hello,
I've been trying to wrap my head around how is best to organize files for a module. I searched similar threads and issues in github with the same problems but I still can't reach to a good conclusion.
From what I read, if I'm writing a library and want to keep code split between files, I have only two options to avoid circular references between modules.
1) Declare all the types in the same place. The psychological attachment to having extremely closely related data structures in the same file is quite apparent in a lot of people. But even if I can accept that if the types are so related to cause circular dependency problems then having them in the same module shouldn't be too ugly from a point of design, I really hate that I lose encapsulation for those types. I.e, if I want to have all procs related to a type in another file and work with internal state, then I have to mark those fields as exported thus having all those fields exported for any user of the ( principal module | library | entrypoint file)
To avoid this, then comes the second way:
2) Using Includes. The idea is simple, the module can be treated as a single giant files with all the small parts in the included files. But this makes working with the files quite messy. For an IDE, the included file does not have any context information on where it is being included, so it can't access the main module types or includes for autocomplete, location of errors, etc. Also, correct me if I'm wrong, but including does not provide any scoping so one has to be extra careful with inclusion of modules from the included excerpts and symbols naming. Additionaly the included file is not valid a nim source file on it's own as it's missing imports and all the context the parent gives so it's uglier to use the "when main" idiom for testing.
The question is, how is typically source written? Is there any other pattern I'm not seeing? Am I missing any different way to structure stuff that makes sense in nim? It's worth mentioning that another answer I saw abuse generics to trick some of the dependency problems. It felt more of a hack than a proper solution, but if it's considered fine let me know.
Include also slows compilation, with a single change you must recompile more files.
A third alternative is forward declaration. Declare just the type names in a single module but defer their implementation to other files.