Módulos en Sword
En Sword, un módulo agrupa piezas relacionadas de una misma capacidad de la aplicación, como controllers, components y providers.
Qué problema resuelven
Cuando una aplicación crece, registrar todo directamente en main.rs deja de ser mantenible. Los módulos permiten:
- agrupar funcionalidad relacionada
- encapsular el registro de dependencias
- separar responsabilidades por dominio
- mantener una arquitectura estable a medida que la app crece
Trait Module
El contrato base es:
pub trait Module {
fn register_controllers(controllers: &ControllerRegistry) {}
fn register_components(components: &ComponentRegistry) {}
async fn register_providers(config: &Config, providers: &ProviderRegistry) {}
}Todos los métodos tienen implementación por defecto vacía.
Qué registra cada método
register_controllers(...)
Registra puntos de entrada externos: HTTP, Socket.IO y otros tipos de controller soportados por el framework.
fn register_controllers(controllers: &ControllerRegistry) {
controllers.register::<UsersController>();
}register_components(...)
Registra estructuras #[injectable] que deben construirse desde el contenedor de dependencias.
fn register_components(components: &ComponentRegistry) {
components.register::<UserRepository>();
components.register::<UsersService>();
}register_providers(...)
Registra estructuras #[injectable(provider)], normalmente conexiones o clientes externos: base de datos, cache o servicios remotos.
Este método es async.
async fn register_providers(config: &Config, providers: &ProviderRegistry) {
let db_config = config.expect::<DatabaseConfig>();
providers.register(
Database::new(db_config)
.await
.expect("Failed to create Database provider"),
);
}Ejemplo de módulo
use sword::prelude::*;
pub struct UsersModule;
impl Module for UsersModule {
fn register_components(components: &ComponentRegistry) {
components.register::<UserRepository>();
components.register::<UsersService>();
}
fn register_controllers(controllers: &ControllerRegistry) {
controllers.register::<UsersController>();
}
}Registro en la aplicación
Los módulos se registran con with_module::<M>() en ApplicationBuilder.
#[sword::main]
async fn main() {
let app = Application::builder()
.with_module::<SharedModule>()
.with_module::<UsersModule>()
.build();
app.run().await;
}Comportamiento de with_module
Cada llamada a with_module::<M>() ejecuta el registro del módulo en este orden:
register_providers(...)register_components(...)register_controllers(...)
Ese orden describe el registro interno del módulo, no la resolución final de dependencias.
La construcción efectiva de components y la resolución del contenedor ocurren después, durante build(), cuando Sword ejecuta el proceso global de construcción del contenedor con todos los módulos ya registrados.
Separación de responsabilidades
Expone una interfaz externa.
Ejemplos: endpoint HTTP, namespace Socket.IO.Lógica interna autoconstruida por DI.
Ejemplos: servicio de dominio, repositorio, hasher.Recurso externo o inicialización async.
Ejemplos: base de datos, cliente Redis, SDK externo.Estructura habitual
Una estructura habitual es:
users/
controller.rs
service.rs
repository.rs
mod.rsY en mod.rs:
pub struct UsersModule;
impl Module for UsersModule {
// registro del dominio users
}Criterio de partición
- cuando un área del dominio tiene controllers y dependencias propias
- cuando conviene aislar registro y responsabilidades
- cuando
main.rsempieza a acumular wiring de múltiples capacidades

