Cuando todos los niveles de contexto se mezclan
¿Qué te impide ver la visión general cuando cada detalle está disponible a la vez?
Un repositorio ordinario no separa la información por escala: áreas de negocio, operaciones, modelos de datos, orden de llamadas, infraestructura y líneas de código individuales se presentan todas a la vez. La memoria de trabajo tiene que retener hechos de distintos niveles y reconstruir por sí sola las relaciones entre ellos. La atención cambia constantemente entre la estructura del sistema y los detalles locales, de modo que la comprensión se desmorona rápidamente tras una pausa.
Cómo afecta al trabajo la falta de una visión general
Abajo, el mismo conjunto de información se muestra en dos estados: a la izquierda está mezclado, a la derecha está organizado en cinco preguntas secuenciales. Empecemos por la primera: ¿dónde vive la responsabilidad en el sistema?
Primero, un mapa de responsabilidades
¿Dónde vive la responsabilidad?
El primer pilar es un mapa de responsabilidad. Reúne controladores, servicios, modelos de datos, adaptadores de infraestructura y cadenas de llamadas en torno a las grandes áreas del sistema — un armazón al que después se pueden vincular operaciones, datos y código.
Los dominios dividen el sistema por áreas estables de responsabilidad, no por capas técnicas: pedidos, pagos, comunicación y analítica. En lugar de cientos de archivos aparentemente equivalentes aparece una primera topología comprensible.
Qué aporta el mapa de dominios
En el diagrama, cuatro dominios forman el nivel superior de la aplicación. A partir de aquí desplegaremos StoreDomain en secuencia: primero sus Actions, luego el contrato de una operación, su escenario y su implementación concreta.
StoreDomainPosee el carrito, el pedido y el traspaso a la entrega.
BillingDomainPosee pagos, facturas y reembolsos.
MessagingDomainPosee comunicación con el cliente y webhooks.
AnalyticsDomainPosee eventos, mercados e informes comerciales.
El mapa se convierte en un catálogo de capacidades.
¿Qué puede hacer el sistema?
El mapa de dominios muestra dónde reside la responsabilidad, pero aún no dice qué puede hacer el sistema. Para responder a eso, cada dominio se abre en un catálogo de Action, capacidades con nombre que proporciona al resto del sistema.
Un Action es una capacidad pública y nombrada de un dominio. El catálogo no muestra funciones internas, sino las operaciones que un dominio ofrece al resto del sistema, junto con las relaciones dirigidas entre ellas. Cada Action se convierte en un único punto de invocación: quien lo invoca elige por significado la capacidad que necesita, en lugar de ensamblar la operación a partir de métodos separados.
Qué aporta el catálogo de Actions
El diagrama destaca CreateOrderAction, el Action que inicia la creación de un pedido. A su alrededor aparecen los demás Actions de StoreDomain y las relaciones entre ellos. Una operación puede depender de otra, pero las dependencias tienen dirección y nunca se cierran en un ciclo. En este nivel solo vemos los nombres de los Actions y sus relaciones; la entrada, el resultado, el escenario y el código se revelarán después.
CreateOrderActionCrear un pedido: validar, reservar y cargar
→ ChargePaymentAction
GetOrderActionLeer el estado actual de un pedido
CancelOrderActionCancelar un pedido e iniciar un reembolso
→ RefundPaymentAction
ShipOrderActionEnviar un pedido confirmado a reparto
Fijamos la frontera de la operación
¿Qué requiere y promete la operación?
La capacidad ya tiene un nombre y un lugar en el sistema. Para usarlo como caja negra, necesitamos saber exactamente qué datos acepta y qué resultado promete devolver.
Un Contract hace que el límite Action sea tipificado y no sea ambiguo. Params describe todo lo que acepta la operación; Result describe todo lo que debe devolver. El código de llamada depende de esa promesa, no de la forma interna del Action. La implementación puede cambiar siempre que la entrada, la salida y el comportamiento observable sigan siendo compatibles.
Qué aporta el contrato del Action
El familiar CreateOrderAction ahora tiene una firma completa: CreateOrderParams a la izquierda y CreateOrderResult a la derecha. Los campos ya no existen como modelos de datos abstractos; pertenecen a una operación específica con un lugar y propósito conocidos. El interior del Action todavía no es necesario para poder utilizarlo.
CreateOrderParamsitems: list[Item]
currency: str
CreateOrderActionCoordinar la creación de orden detrás de un límite declarado
CreateOrderResultpayment_id: str
status: OrderStatus
Desplegamos la operación como escenario
¿Cómo se desarrolla el escenario?
El contrato fija el principio y el fin de una operación, pero no muestra cómo uno se convierte en el otro. Para ver eso, desplegamos el flujo interno del escenario empresarial.
Un Pipeline hace que el escenario principal del negocio sea lineal y visible: validar la entrada, reservar inventario, cobrar el pago y ensamblar el resultado. Eso no quiere decir que no existan errores, ramificaciones y compensaciones; reciben un lugar explícito en relación con la línea principal. Cada paso también tiene un contrato local: declara lo que lee de Params, State y Context, y lo que agrega a State para etapas posteriores.
Qué aporta el escenario de la operación
El dominio le dio un lugar al escenario, al Action un nombre y al Contract un comienzo y un resultado prometido. El Pipeline agrega orden causal y límites internos. El paso reserve_inventory se aísla como un cambio de estado distinto: recibe datos ya validados y deja reservation_id para que continúe el escenario.
Sólo ahora, el comportamiento concreto
¿Dónde vive el comportamiento concreto?
El Pipeline localiza el comportamiento requerido con precisión y reduce drásticamente el área de búsqueda. Ahora podemos abrir no todo el repositorio o incluso todo el Action, sino un paso cuyo propósito, entrada y salida ya conocemos.
Code es el quinto nivel no porque los detalles no sean importantes, sino porque ahora están rodeados de significado. Sabemos qué dominio posee el comportamiento, qué capacidad implementa Action, qué promete Contract y dónde se ubica reserve_inventory en Pipeline. La implementación se lee como una respuesta local a una tarea concreta en lugar de una entrada a una investigación interminable del repositorio.
Qué aporta aislar el comportamiento en un solo paso
Cuando abrimos reserve_inventory, ya conocemos su intención, entradas y ubicación en el escenario. El principio sigue siendo el mismo: los efectos externos deben pasar a través de los Resource declarados y los Action públicos. La gramática arquitectónica hace que las desviaciones sean visibles y verificables sin pretender que el texto descriptivo por sí solo haga que cualquier derivación sea físicamente imposible.
$ uv run python store/actions/create_order.pyLos cinco niveles no ocultan el código ni reducen el sistema a un diagrama. Conservan el recorrido desde el modelo general hasta un detalle concreto. Quien acaba de llegar construye el contexto de forma progresiva; el arquitecto gestiona la gramática y las fronteras en lugar de cada archivo; y el agente de IA realiza trabajo local dentro de reglas declaradas: las personas diseñan el lenguaje del sistema y la máquina actúa en ese lenguaje.
