La capa de datos
Dónde poner las consultas para que el código no se disperse: una capa de repositorio con operaciones de dominio, probable sin arrancar la aplicación.
Las tres capas
La forma del repositorio
Operaciones con nombre de dominio, igual que los comandos del nivel 14.4:
pub struct Proyectos<'a>(pub &'a Connection);impl Proyectos<'_> { // el nombre dice qué significa, no qué tabla toca pub fn recientes(&self, limite: u32) -> Result<Vec<Proyecto>> { /* … */ } pub fn abrir(&self, id: i64) -> Result<Option<Proyecto>> { /* … */ } pub fn archivar(&self, id: i64) -> Result<()> { /* … */ } // y las operaciones compuestas llevan su transacción dentro pub fn duplicar(&mut self, id: i64) -> Result<i64> { let tx = self.0.unchecked_transaction()?; // copiar el proyecto, sus ajustes y sus elementos — todo o nada tx.commit()?; Ok(nuevo_id) }}La operación compuesta es la razón de que exista esta capa. «Duplicar un proyecto» toca tres tablas y debe ser atómico; si esa lógica vive en un comando, acaba repetida en el segundo sitio que necesite duplicar, y las dos copias divergen.
Por qué se prueba tan bien
La propiedad práctica, y merece aprovecharla:
#[test]fn duplicar_copia_los_elementos() { let conn = Connection::open_in_memory().unwrap(); aplicar_esquema(&conn).unwrap(); // el mismo del nivel 43 let mut repo = Proyectos(&conn); let id = repo.crear("original").unwrap(); repo.añadir_elemento(id, "uno").unwrap(); let copia = repo.duplicar(id).unwrap(); assert_eq!(repo.elementos(copia).unwrap().len(), 1);}Una base en memoria, el esquema real, y milisegundos por prueba. Con eso se pueden cubrir las operaciones compuestas, los casos límite —qué pasa al duplicar algo sin elementos, al archivar algo ya archivado— y las restricciones del nivel 41.3, que es donde de verdad se rompen las cosas.
Y hay un beneficio adicional: estas pruebas se ejecutan en tu integración continua sin escritorio ni almacén —el entorno del nivel 37.4—, así que la parte más delicada de la aplicación queda cubierta en el sitio donde menos cuesta.
Lo que dispersa el código
Tres señales de que la capa se está deshaciendo:
- SQL dentro de un comando. La primera y la más fácil de ver.
- Una consulta repetida en dos sitios con pequeñas diferencias. Casi siempre significa que falta una operación de dominio que las une.
- Y el repositorio devolviendo filas en bruto en vez de tipos del dominio. Si quien llama tiene que saber en qué columna está cada cosa, la capa no está haciendo su trabajo.