Con dominio y casos de uso listos, tocaba la capa que el usuario realmente toca: el CLI.
Read this chapter in English: EN
Aquí la pregunta era simple: ¿queremos una CLI que “funcione” o una CLI que la gente quiera usar sin pelearse con ella?
Código de referencia:
Parser fuerte con clap
#
Subcomandos definidos:
add {title}list {--status}done {id}todo {id}delete {id}
Además, --output table|json como flag global.
Por qué ValueEnum en vez de parse manual
#
StatusArg y OutputFormat son enums con ValueEnum.
Podríamos recibir strings y validar con if/match propio. El problema es que eso duplica lógica de validación y te obliga a mantener mensajes de error a mano.
Con clap, valores inválidos fallan en borde de entrada, antes de ejecutar lógica de negocio.
UUID como tipo de entrada, no como texto tardío #
En done/todo/delete, id entra como Uuid directamente.
Esto evita mover validación de formato a use cases, donde ya deberíamos estar hablando de negocio y no de parsing.
Salida dual: table para humanos, json para máquinas #
En muchas CLI se imprime texto bonito y luego alguien intenta automatizar y descubre que no hay contrato estable.
Aquí resolvimos eso desde diseño:
table: lectura rápida en terminal.json: payload estable para scripts.
Ejemplo de uso:
cargo run -- list
cargo run -- --output json list --status doneCaso interesante: delete
#
delete devuelve una semántica idempotente visible:
deleted = truesi encontró y borró,deleted = falsesi no existía.
En JSON además devolvemos message estructurado. En table, una salida corta y legible.
Eso hace que el mismo comando sirva para operador humano y para pipeline CI/CD sin hacks de parsing.
Orquestación en main.rs
#
run() hace tres cosas y no más:
- parsea comando,
- instancia repositorio,
- despacha al use case correspondiente.
No hay reglas de negocio ahí. Solo cableado.
Cuando run() falla, main() imprime en stderr y sale con código 1. Contrato de CLI limpio y estándar.
Complemento con historial del repo #
Este capítulo se conecta muy bien con este commit:
Si lo revisas, se ve claramente el salto de “CLI funcional” a “CLI usable por humanos y scripts”.
Cierre #
Una CLI robusta no se mide por cuántos comandos tiene, sino por qué tan predecible es su contrato.
En el cierre de la serie vamos al último bloque: persistencia JSON, tests y deuda técnica explícita.