MÓDULO 3 · ARQUITECTURA DE SISTEMAS CONVERSACIONALES · LECCIÓN 4.2 · 30 MIN

Estructura de Carpetas (Screaming Architecture)

Nivel intermedio — organizar el código en carpetas que comuniquen el propósito del sistema, no el framework que usa.

Idea central Si miras el plano de un hospital, ves "salas de operaciones", no "habitaciones rectangulares". Tu código debería hacer lo mismo: la estructura de carpetas debería gritar qué hace el sistema, no qué framework usa.

El problema

Abres un proyecto nuevo. Ves las carpetas controllers, models, services, utils. ¿Qué hace este sistema? No hay forma de saberlo — podría ser un e-commerce, un sistema médico, o un juego. La estructura te dice que usa MVC, pero nada sobre el negocio.

Screaming Architecture

Tu arquitectura debería contarle al lector de qué trata el sistema — no qué frameworks usaste.— Robert C. Martin (parafraseado)

Organizar por feature/dominio en vez de por capa técnica: en lugar de una carpeta controllers con todos los controladores mezclados, cada módulo de negocio (orders, catalog, payments) tiene su propia carpeta con todo lo que necesita dentro.

AspectoPor capa técnicaPor feature/dominio
Navega paraTipo de archivo (controllers)Funcionalidad (orders)
Escala bien paraProyectos pequeñosProyectos medianos/grandes
AcoplamientoAlto (todos los controllers juntos)Bajo (feature es independiente)
Localización de cambiosUn cambio toca 4 carpetasUn cambio toca 1 carpeta

Estructura híbrida recomendada

Feature/módulo por fuera, Clean Architecture por dentro de cada módulo:

src/ ├── modules/ # ← features/bounded contexts │ ├── orders/ │ │ ├── domain/ # entities, ports, events │ │ ├── application/ # use-cases, dtos │ │ ├── infrastructure/ # repos, http, events │ │ └── index.js # ← API pública del módulo │ ├── catalog/ │ └── payments/ ├── shared/ # código verdaderamente compartido └── main.js # composition root

3 reglas de la estructura

Regla 1 — los módulos son independientes: un módulo puede importar el dominio de otro (una interfaz), nunca su infraestructura concreta.

✓ import { PaymentGateway } from '../payments/domain/ports/PaymentGateway.js'
✗ import { StripeGateway } from '../payments/infrastructure/StripeGateway.js'

Regla 2 — cada módulo expone una API pública vía su index.js: exporta use cases y entities, nunca implementaciones de infraestructura.

Regla 3 — shared/ solo contiene código verdaderamente compartido: utilidades genéricas, base classes, infraestructura común — nunca lógica de negocio específica de un módulo.

Cuándo aplicarlo

EstructuraCuándo usarla
Por capa técnicaProyecto pequeño (<5 archivos por tipo), un solo desarrollador
Por feature simpleProyecto mediano, features claros, sin Clean Architecture
Feature + CleanProyecto complejo, múltiples equipos, lógica de negocio rica
Monorepo con packagesMicroservicios o módulos con despliegue independiente
La estructura no sustituye a la disciplina

Organizar por feature no impide que alguien importe directamente la infraestructura de otro módulo — solo lo hace más visible en el code review. Las 3 reglas son convención, no un límite que el lenguaje imponga por sí solo; sin revisión activa del equipo, la estructura "grita" un propósito que el código real puede estar traicionando.

Practica: migra de MVC a features

Tienes un proyecto con estructura tradicional MVC: carpetas controllers/, models/, services/, repositories/, routes/, utils/, cada una con archivos de Orders, Products, Payments mezclados.

Reorganízalo en estructura por features (orders/, products/, payments/), aplicando las 3 reglas de independencia entre módulos.