Capítulo 11: Modularização, Crates, Visibilidade (pub) e Workspaces
Capítulo 11: Modularização, Crates, Visibilidade (pub) e Workspaces
Especialização em Sistemas com Rust • Rust 2021 Edition • Ownership, Concorrência Segura e Sistemas de Alta Performance
🗺️ Mapa Conceitual do Sistema de Módulos e Árvore de Visibilidade
flowchart TD
CrateRoot["Crate Root (src/lib.rs ou src/main.rs)"] --> ModuloRede["mod rede (pub mod)"]
CrateRoot --> ModuloSeguranca["mod seguranca (privado por padrão)"]
subgraph REDE_INTERNO["Módulo de Rede (src/rede.rs)"]
TCP["pub struct ConexaoTcp"]
UDP["struct BufferUdp (privado ao módulo)"]
end
subgraph SEGURANCA_INTERNO["Módulo de Segurança (src/seguranca.rs)"]
Cripto["pub(crate) fn criptografar(): Visível em toda a crate"]
Hash["fn gerar_salt(): Privado estrito"]
end
ModuloRede --- REDE_INTERNO
ModuloSeguranca --- SEGURANCA_INTERNO
TCP -->|"pub use rede::ConexaoTcp (Reexportação Fachada)"| ApiPublica["API Pública Limpa da Crate"]
style CrateRoot fill:#e1f5fe,stroke:#03a9f4,stroke-width:2px
style ModuloRede fill:#fff3e0,stroke:#ff9800,stroke-width:2px
style ModuloSeguranca fill:#ede7f6,stroke:#7e57c2,stroke-width:2px
style ApiPublica fill:#e8f5e9,stroke:#4caf50,stroke-width:2px
🏛️ 1. A Filosofia de Modularização no Rust
A medida que sistemas corporativos crescem em complexidade, manter todo o código em um único arquivo ou estrutura plana torna a manutenção inviável. O sistema de módulos do Rust foi desenhado para atender a três objetivos simultâneos:
- Encapsulamento Estrito: No Rust, tudo é privado por padrão. Nenhuma função, struct ou campo vaza para fora do seu escopo a menos que o desenvolvedor utilize explicitamente o modificador
pub. - Navegação Determinística: A árvore de módulos reflete diretamente a estrutura de arquivos no disco, com resolução de caminhos inequívoca (
crate::,super::,self::). - Escala Monorepo: O suporte nativo a Cargo Workspaces permite compilar dezenas de crates interdependentes em paralelo com compartilhamento atômico de dependências.
⚙️ 2. A Estrutura de Arquivos Moderna (Edição 2021)
A partir da edição 2018 e consolidada na 2021, o Rust eliminou a obrigatoriedade de arquivos mod.rs antigos. A convenção moderna adota:
src/
├── main.rs <- Crate Root do binário
├── rede.rs <- Declaração do módulo 'rede'
└── rede/ <- Diretório para submódulos de 'rede'
├── tcp.rs <- Submódulo 'rede::tcp'
└── dns.rs <- Submódulo 'rede::dns'
No src/main.rs:
// Declara o módulo 'rede' que o compilador busca em 'src/rede.rs'
pub mod rede;
fn main() {
rede::tcp::conectar("127.0.0.1:8080");
}
🔒 3. Os Níveis de Visibilidade e Controle de Acesso
O Rust oferece controle cirúrgico de visibilidade para construir interfaces bem arquitetadas:
| Modificador de Visibilidade | Escopo de Acesso Permitido |
|---|---|
| (Nenhum - Padrão) | Privado: Acessível apenas dentro do módulo atual e de seus filhos |
pub |
Público Total: Acessível por qualquer módulo e por crates externas |
pub(crate) |
Escopo de Crate: Visível em qualquer arquivo dentro da crate atual, mas invisível externamente |
pub(super) |
Escopo Pai: Visível exclusivamente dentro do módulo pai imediato |
pub(in caminho) |
Caminho Restrito: Visível apenas dentro do submódulo especificado |
Exemplo de Encapsulamento com Structs:
Em structs públicas, seus campos permanecem privados a menos que sejam explicitamente marcados com pub:
pub struct CredencialAuth {
pub usuario: String, // Campo público
chave_secreta: String // Campo PRIVADO: impede instanciação direta e mutação indevida!
}
impl CredencialAuth {
// Construtor obrigatório para controlar a criação de 'chave_secreta'
pub fn new(usuario: &str, segredo: &str) -> Self {
Self {
usuario: String::from(usuario),
chave_secreta: String::from(segredo),
}
}
}
🚪 4. Reexportação de Fachada com pub use
Muitas vezes, a organização interna de arquivos de uma biblioteca possui diretórios profundos (ex: crate::subsistema::protocolo::drivers::conexao::DriverTcp), mas o usuário final da biblioteca deseja apenas minha_crate::DriverTcp.
Utiliza-se pub use para criar uma API externa limpa (Façade Pattern):
// Em src/lib.rs:
pub mod subsistema;
// Reexportação que simplifica a vida do consumidor:
pub use subsistema::protocolo::drivers::conexao::DriverTcp;
🏢 5. Cargo Workspaces para Arquiteturas Corporativas
Quando um projeto é composto por múltiplos serviços e bibliotecas compartilhadas, utiliza-se um Cargo Workspace. Um workspace compartilha o mesmo diretório target/ de compilação e um único arquivo Cargo.lock:
# Cargo.toml (Na raiz do repositório)
[workspace]
members = [
"crates/kernel-core",
"crates/network-engine",
"services/api-gateway",
"apps/cli-admin",
]
resolver = "2"
Vantagens do Workspace:
- Compilação Incremental Compartilhada: Se a crate
kernel-corefor compilada por um serviço, os demais a reutilizam sem recompilar. - Versões Unificadas: Garante que todas as crates usem rigorosamente as mesmas versões de dependências externas (como
serdeoutokio).
⚠️ 6. Armadilhas Comuns e Mensagens do Compilador
- Esquecer
pubem Campos de Structs Públicas (E0616):- Marcar
pub struct MinhaStructnão torna seus campos públicos! Se tentar acessarinstancia.campode outro módulo, o compilador acusará:field is private. - Correção: Adicione
pubantes de cada campo que deve ser exposto.
- Marcar
- Confundir
usecom Inclusão de Código:- O comando
mod arquivo;é quem diz ao compilador para ler e compilar o arquivo. - O comando
use caminho::Item;é apenas um atalho sintático para não precisar digitar o caminho completo. Nunca useusesem ter declarado o módulo correspondente commod.
- O comando
🛡️ 7. Boas Práticas de Arquitetura em Rust
- Projete APIs com Visibilidade Mínima: Comece tudo como privado. Só promova para
pub(crate)se múltiplos módulos precisarem daquele recurso, e só promova parapubse for parte formal do contrato da biblioteca. - Separe
lib.rsdemain.rs: Crie o núcleo da sua aplicação dentro de uma biblioteca (lib.rs) e use omain.rsapenas como um cliente de inicialização magro (thin client). Isso viabiliza testes de integração completos e reutilização por outras ferramentas.
📋 8. Cheat-Sheet: Resumo Executivo
// Declaração de módulo
pub mod servico;
// Importação e atalho
use crate::servico::Processador;
pub use crate::servico::Processador; // Reexporta
// Visibilidade de crate
pub(crate) fn interno() { /* ... */ }