More subcrates or less subcrates?


#1

I have a discord bot which has a lot of commands (they may be so big that may require few more modules to work).
So, currently, I have the following structure:

src/bot.rs
----commands/
----commands/mod.rs
----commands/add.rs
----commands/remove.rs
----commands/help.rs
----commands/(50+other commands)

So, is this a good(optimal) option to make commands/command a subcrate so it will lead to bot crate, commands crate, and specific command crate (bot, commands, add, remove, help, … crates)? I still don’t know about subcrate’s overhead and use or pros/cons, so I would be happy to hear about that also.


#2

There’s no runtime overhead to using subcrates, you end up with a statically linked exe anyway. There’s a bit of bureaucratic overhead. A big project divided into subcrates will definitely build faster - this will become less important when incremental compilation starts to make a difference.


#3

Okay, but should I create subcrates for each command or only for commands/mod.rs, which will contain all the commands in one crate (commands crate)? What is optimal and why?


#4

I think for each command it’s going to be awkward. Personally I wouldn’t do it like that since it would be a pain to add a new subcrate for each new command.


#5

If I understood you correctly you don’t have sub-crates, but sub-modules. I think in your case current layout is preferred if each command takes less than say 500-1000 LOC and you don’t have reasons to split each command into several files. Also don’t forget that you can mix things up and to refactor you submodule/command from file into folder if such need will arise. By having pub mod in your commands/mod.rs it will be just an implementation detail and will not matter for outside user.


#6

As a user of Rust and crates.io, I prefer fewer sub-crates. Modules seem more ergonomic for organizing code, like you have already done. More crates are less ergonomic for the crates.io user unless they stand on their own. There are only two cases where I can think I would prefer crates instead.

  1. Each crate stands on its own as a useful library and does not require any other crate in the tree to work with and be useful.
  2. The crates are meant to work together as a framework. An example of this use would be Serde. There is the main Serde crate, and then all the other crates for the different serialization formats. So you can get just the Serde you need, and not everything.

Number 2 is also nice because then others can publish crates that are meant to plug into your master crate. Again using Serde as an example, I can define my own serialization format that way. (Full disclosure, I’ve never actually used Serde this way.)

In your case, I like what you’ve done already.

If you did want to break them into sub-crates, I think I would go route 2 above and leave the bot and commands modules in a single crate and make each command its own crate. Each command is a little sub-program anyway.