strategic · temario
2.1tema 1 de 5

Bounded Contexts

Un bounded context define el límite explícito dentro del cual un modelo de dominio es válido y consistente.

En sistemas complejos, el mismo término puede tener significados distintos según el área del negocio. Una 'Cuenta' en el contexto de facturación puede referirse a un registro contable, mientras que en el contexto de autenticación representa credenciales de acceso. Intentar usar un modelo único para ambos produce conflictos, duplicación y fragilidad.

Un bounded context es el límite lingüístico y conceptual dentro del cual un modelo tiene un significado preciso y coherente. Dentro de ese límite, el lenguaje ubicuo es estable: cada término tiene exactamente una definición y el equipo responsable del contexto lo mantiene de forma independiente.

El límite no es solo técnico (un módulo o servicio), sino organizacional: un bounded context suele coincidir con un equipo, un subdominio o un ciclo de vida de datos independiente. La regla práctica es que si dos áreas del negocio usan la misma palabra con propósitos distintos, casi siempre necesitan contextos separados.

Cada bounded context expone su modelo hacia el exterior únicamente a través de contratos explícitos: eventos de integración, APIs u otros mecanismos de colaboración. El interior del contexto — las clases, invariantes y reglas de negocio — no se comparte directamente con ningún otro contexto.

Un error frecuente es pensar que separar en contextos implica duplicar código. En realidad, dos contextos pueden tener conceptos con el mismo nombre pero con formas distintas; la 'duplicación' es intencional y protege la autonomía de cada modelo.

Al definir bounded contexts, el equipo aplica el principio de responsabilidad única a nivel de modelo: cada contexto es propietario de su modelo, su base de datos (idealmente), su lenguaje y su ciclo de despliegue.

structure.txt
# Bounded context layout (generic)

src/<project>/
├── contexts/
│   ├── <context_a>/               # Bounded Context A
│   │   ├── domain/                # No framework deps
│   │   │   ├── model/
│   │   │   │   ├── <aggregate_a>.py
│   │   │   │   └── <value_object_a>.py
│   │   │   └── repositories/
│   │   │       └── <aggregate_a>_repository.py  # Port (ABC)
│   │   ├── application/
│   │   │   └── commands/
│   │   │       └── <do_something>/
│   │   │           ├── command.py
│   │   │           └── handler.py
│   │   └── infrastructure/
│   │       └── persistence/
│   │           └── sql_<aggregate_a>_repository.py
│   └── <context_b>/               # Bounded Context B
│       ├── domain/
│       │   ├── model/
│       │   │   └── <aggregate_b>.py
│       │   └── repositories/
│       │       └── <aggregate_b>_repository.py
│       ├── application/
│       └── infrastructure/
└── shared_kernel/                 # Shared only by explicit agreement
    └── domain/
        ├── value_object.py
        ├── entity.py
        └── aggregate_root.py

# Rule: contexts/<context_a>/ NEVER imports from contexts/<context_b>/
# Cross-context communication goes through integration events or ACL adapters
project/
contexts· Bounded Contexts root
<context_a>· Bounded Context A
domain· Domain layer — Context A
application· Application layer — Context A
infrastructure· Infrastructure layer — Context A
<context_b>· Bounded Context B
shared_kernel· Shared Kernel

Debugging lab

Detecta y corrige el error o la violación de diseño.

0/5 tests passing0%
  1. 2.1.5.1

    # context_b/domain/model/account.py imports context_a's Account directly: from src.project.contexts.context_a.domain.model.account import Account

  2. 2.1.5.2

    # shared_kernel/domain/order.py — the Order aggregate was placed in shared_kernel: class Order(AggregateRoot): def __init__(self, order_id: OrderId, customer_id: CustomerId): ...

  3. 2.1.5.3

    # context_a's repository port imports context_b's DTO: from src.project.contexts.context_b.application.dtos import ContextBDto class AggregateARepository(ABC): def find_with_b_data(self, id: AggregateAId) -> ContextBDto: ...

  4. 2.1.5.4

    # Two bounded contexts share the same database table: # context_a reads/writes from 'accounts' table # context_b also reads/writes from 'accounts' table directly

  5. 2.1.5.5

    # The bounded context is defined by a single class, not a folder: # context_a has: contexts/all_in_one.py containing ContextAAggregate, ContextBAggregate, ...