Monorepositório com Rust: organização de código na prática

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Monorepositório com Rust: organização de código na prática

Monorepositório (monorepo) é uma abordagem de gerenciamento de código onde vários projetos ou componentes são armazenados em um único repositório. No ecossistema Rust, essa prática é especialmente popular devido ao suporte nativo do Cargo Workspace. Neste artigo, vamos explorar como organizar um monorepositório com Rust na prática: desde a criação da estrutura até o gerenciamento de dependências e testes. Você aprenderá como evitar erros comuns e tornar sua base de código escalável.



O que é Cargo Workspace e por que ele é necessário

Cargo Workspace é um mecanismo que permite gerenciar vários crates (bibliotecas ou executáveis) dentro de um único projeto. Em vez de criar repositórios separados para cada componente, você os une em uma estrutura única. Isso oferece várias vantagens:

  • Sistema de build unificado — um único comando cargo build compila todos os crates.
  • Dependências compartilhadas — dependências duplicadas são resolvidas uma vez, reduzindo o tamanho do binário final.
  • Testes simplificados — é possível executar testes para todos os crates com um único comando.
  • Consistência de versões — todos os componentes usam as mesmas versões das bibliotecas.

O monorepositório é especialmente útil para microsserviços, bibliotecas de uso geral ou projetos com uma divisão clara em camadas (por exemplo, core, API, CLI).



Criando a estrutura do monorepositório

Vamos começar com um exemplo prático. Suponha que estamos desenvolvendo um sistema de gerenciamento de tarefas. Teremos três crates:

  • core — biblioteca com a lógica de negócios.
  • cli — executável para linha de comando.
  • server — servidor web (executável).

Primeiro, criamos o diretório raiz e o arquivo Cargo.toml para o workspace:

mkdir task_managercd task_manager# Criando o Cargo.toml raiztouch Cargo.toml

No Cargo.toml raiz, especificamos o workspace:

[workspace]members = [    "core",    "cli",    "server",]

Agora, criamos cada crate com cargo new:

cargo new core --libcargo new clicargo new server

Após isso, a estrutura ficará assim:

task_manager/├── Cargo.toml          # Workspace raiz├── core/│   ├── Cargo.toml│   └── src/│       └── lib.rs├── cli/│   ├── Cargo.toml│   └── src/│       └── main.rs└── server/    ├── Cargo.toml    └── src/        └── main.rs

Observe: o Cargo.toml raiz não contém a seção [package], apenas [workspace]. Isso é importante para o funcionamento correto.



Gerenciando dependências entre crates

Uma das tarefas principais em um monorepositório é configurar corretamente as dependências entre os crates. No nosso exemplo, cli e server dependem de core. Vamos especificar isso nos seus Cargo.toml:

Para cli/Cargo.toml:

[package]name = "cli"version = "0.1.0"edition = "2021"

[dependencies]core = { path = "../core" }clap = { version = "4.0", features = ["derive"] } # Dependência externa para CLI

Para server/Cargo.toml:

[package]name = "server"version = "0.1.0"edition = "2021"

[dependencies]core = { path = "../core" }actix-web = "4" # Dependência externa para o servidor web

No Cargo.toml raiz, também é possível especificar dependências comuns, se todos os crates precisarem delas, mas geralmente isso é feito individualmente. No entanto, o workspace permite resolver conflitos de versão: se dois crates usam a mesma biblioteca, o Cargo automaticamente usará uma única versão.

Blogs

Book Recommendations