Principios
Una arquitectura se vuelve difícil de mantener cuando sus nombres dejan de explicar lo que ocurre. Por eso DFE no empieza con una lista de patrones, sino con unas pocas reglas que permiten decidir dónde debe vivir cada parte de una operación.
| Principio | Regla |
|---|---|
| Dominio puro | Sin I/O ni dependencias de infraestructura |
| El flow consulta y decide | Lee mediante fx/db, aplica reglas y devuelve el resultado sin persistirlo |
| API ejecuta los cambios | Guarda mediante fx/db y coordina caché, eventos y otros servicios |
fx/db es primitivo |
SELECT, INSERT, UPDATE y DELETE, sin otra capa por encima |
api/ orquesta |
Abre la transacción, llama al flow, guarda el resultado y hace commit |
| Acoplamiento explícito | El flow llama a fx/db por su nombre y el compilador señala lo que cambia |
| Tipos que conservan sus reglas | Cuando una regla merece un tipo, sus constructores y conversiones la comprueban |
| Abstracción con motivo | Un trait aparece cuando existen dos implementaciones reales o un límite claro |
Una consulta que solo obtiene datos no modifica por sí misma el estado del negocio. Un flow puede consultar fx/db para tomar una decisión y devolver el resultado. La escritura queda en API, mediante fx/db. Cuando la regla lo requiere, API mantiene las consultas y la escritura dentro de la misma transacción.
fx/ reúne las interacciones con el exterior, tanto lecturas como escrituras. Cuando hablamos de efectos sobre el sistema, distinguimos los cambios y las acciones de las consultas que solo obtienen información. No usamos la clasificación de efectos de la programación funcional, ni afirmamos que una consulta sea pura. La página de effects desarrolla esta distinción y explica qué coordina el flow y qué queda en api/.
Los nombres flow y fx son deliberados. service, usecase y repository suelen traer consigo interfaces, implementaciones, inyección y mappers antes de que exista una necesidad concreta. En Rust, esa ceremonia puede acabar introduciendo dyn, Arc y lifetimes donde todavía solo había una función que necesitaba hacer su trabajo.
Elegí otros nombres también por eso. Cuando leo service, usecase o repository, tiendo a pensar en las estructuras con las que he trabajado antes, incluso cuando el proyecto todavía no las necesita. Con flow quiero empezar por la operación que hay que resolver; con fx, por lo que necesita leer, escribir o consultar fuera del programa. Los nombres no impiden repetir esos hábitos, pero me ayudan a no darlos por hechos.