Putting functions in a separate mod? (Project structure best practice)

I have a basic Tauri GUI-application. Initially I had all the Tauri-commands - the hooks which can be called from the front-end - in my main.rs like this:

//...

fn new_project_if_none() -> std::io::Result<()> {
    //...
}

fn counter(tx: mpsc::Sender<u64>, is_playing: Arc<(Mutex<bool>, Condvar)>, reset: Arc<Mutex<bool>>) {
    // ...
}

#[tauri::command]
fn play(app_handle: tauri::AppHandle, is_playing: State<IsPlayingState>, first_click: State<FirstClickState>, seconds_state: State<SecondsState>, reset_state: State<ResetState>) {
    // ...
}

#[tauri::command]
fn save(task_description: &str, seconds_state: State<SecondsState>, reset_state: State<ResetState>, app_handle: tauri::AppHandle) -> Result<(), String> {
   //...
}

#[tauri::command]
fn update_finished_tasks(app_handle: tauri::AppHandle) -> Result<(), String> {
    //...
}

// I have more Tauri-commands but you get the idea.

fn main() {
    // ...
    tauri::Builder::default()
        .manage(tauri_commands::IsPlayingState(is_playing))
        .manage(FirstClickState(first_click))
        .manage(SecondsState(seconds))
        .manage(ResetState(reset))
        .invoke_handler(tauri::generate_handler![play, save, update_finished_tasks, delete_task, create_new_project, load_projects, delete_project, select_project, exit])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

Now I have made a new file called tauri_commands and placed my Tauri-commands there. Then I did mod tauri_commands in my main.rs and call the functions like tauri_commands::play(...).

Is this considered a good practice in Rust to structure my project more and to not bloat the main.rs-file?

I have the idea that, unlike other languages like e.g Java where every class need it's own separate file, Rust gives a lot of freedom in how you structure your project and there aren't clear instructions. I like this freedom but it sometimes makes it hard to know how to structure your project. I have also read that in Rust it isn't always adviced to make a lot of separate modules unless really necessary.

Edit: I also moved the functions counter and new_project_if_none in a module called utils.rs

This recent thread has some advice: Best way to organize structure / modules in project

But you are correct that you have a lot of freedom/flexibility here, so you can also adapt things based on what you find works well with your tools and workflow.

2 Likes

So it would also be okay to create a new directory /services and place modules like project_service.rs and task_service.rs in it;

So I take all the logic out of my Tauri-command functions so those only act as a "hook"/controller and all my business logic is in the service-modules?

Or is that approach too OOP?

Yes, that sounds reasonable. The nice thing about this is that these modules can have private/internal fields and functions, and you will know that these private APIs are not visible to the rest of your code. This can make it easier to change the implementation of a module later on.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.