Rust - Organizando o projeto em módulos
Fala, pessoal! Vamos continuar nossa série sobre como criar uma API com Rust e Axum. Hoje, o foco será na organização do código. Escrever todo o código no arquivo main.rs
não é recomendado, pois conforme o desenvolvimento avança, o arquivo pode ficar tão grande que se torna quase impossível de manter. O que faremos hoje é separar o código em módulos. Mas o que são módulos no Rust?
Os módulos em Rust são usados para organizar e estruturar o código, permitindo melhor reutilização e separação de responsabilidades. Eles ajudam a dividir um programa em partes menores e mais gerenciáveis.
Obs.:
Faremos uma organização básica para demonstrar como estruturar os módulos. Conforme o projeto cresce, podemos ajustar a estrutura conforme a necessidade.
Existem várias formas de organizar os módulos. Hoje, vou mostrar a que mais utilizo: separando cada um por pastas e criando um arquivo mod.rs
para definir a estrutura.
Estrutura de Arquivos e Diretórios
Primeiro, vamos criar a estrutura de arquivos e diretórios para os módulos, todos dentro do diretório src
:
Crie o diretório config
e dentro dele crie dois arquivos: config.rs
e mod.rs
.
Crie o diretório dtos
e dentro dele crie dois arquivos: user_dto.rs
e mod.rs
.
Crie o diretório routes
e dentro dele crie dois arquivos: routes.rs
e mod.rs
.
Sua estrutura de diretórios deve ficar assim:
src/
├── main.rs
├── config/
│ ├── config.rs
│ ├── mod.rs
├── dtos/
│ ├── mod.rs
│ ├── user_dto.rs
├── routes/
│ ├── mod.rs
│ ├── routes.rs
Configurando os Módulos
Dentro de src/config/config.rs
, primeiro importe os módulos necessários e depois mova a struct
e o impl
do Config
para o arquivo:
use std::env;
pub struct Config {
pub my_rust_variable: String,
}
impl Config {
pub fn new() -> Self {
Config {
my_rust_variable: env::var("MY_RUST_VARIABLE").expect("Variável não encontrada."),
}
}
}
Agora, configure o módulo. Dentro de src/config/mod.rs
, insira:
pub mod config;
O Rust precisa do arquivo mod.rs
para configurar os módulos. Sempre que você criar um módulo dentro de config
, você deve inseri-lo no mod.rs
utilizando o nome do arquivo sem a extensão .rs
.
Dentro de src/dtos/user_dto.rs
, primeiro importe os módulos necessários e depois mova a struct UserDto
para o arquivo:
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub struct UserDto {
pub name: String,
}
Agora, configure o módulo. Dentro de src/dtos/mod.rs
, insira:
pub mod user_dto;
Dentro de src/routes/routes.rs
, primeiro importe os módulos e depois mova as funções das rotas para o arquivo:
use std::env;
use axum::Json;
use dotenvy::dotenv;
use crate::{config::config, dtos::user_dto};
pub async fn get_test() -> &'static str {
"Hello, World!"
}
pub async fn get_system_env() -> String {
match env::var("MY_SYSTEM_VARIABLE") {
Ok(value) => value,
Err(_) => String::from("Variável não encontrada."),
}
}
pub async fn get_env() -> String {
dotenv().ok();
match env::var("MY_RUST_VARIABLE") {
Ok(value) => value,
Err(_) => String::from("Variável não encontrada."),
}
}
pub async fn get_struct_env() -> String {
dotenv().ok();
let config = config::Config::new();
config.my_rust_variable
}
pub async fn post_test(Json(user): Json<user_dto::UserDto>) -> Json<user_dto::UserDto> {
Json(user_dto::UserDto { name: user.name })
}
Agora, configure o módulo. Dentro de src/routes/mod.rs
, insira:
pub mod routes;
Modificando main.rs
Agora que separamos o nosso código em módulos, precisamos modificar o main.rs
para podermos utilizá-los:
use axum::{routing::{get, post}, Router};
mod config;
mod dtos;
mod routes;
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/", get(routes::routes::get_test))
.route("/system_env", get(routes::routes::get_system_env))
.route("/env", get(routes::routes::get_env))
.route("/struct_env", get(routes::routes::get_struct_env))
.route("/", post(routes::routes::post_test));
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
}
Primeiro, importamos cada módulo. Depois, chamamos cada função a partir dele, como em routes::routes::get_system_env
, deixando o código mais limpo e fácil de manter.
Com essa breve introdução a módulos, você já consegue organizar melhor o seu código. Aqui utilizamos uma separação básica de responsabilidades, então, neste momento, foque em aprender como utilizar os módulos em Rust. Depois, com o conceito bem fundamentado, você poderá aplicar Clean Code e outras técnicas para organizar ainda melhor seu código.
No próximo post, vamos falar sobre acesso a banco de dados! Vamos usar a crate SQLx para gerenciar conexões e queries, e eu vou te mostrar como criar um CRUD simples.
Valeu por acompanhar até aqui! Qualquer dúvida, deixa nos comentários. Fique com Deus!
🔗 Link para a postagem no Linkedin
🔗 Confira o código no GitHub.