ADR-011: Three-Layer ArchitectureΒΆ

Estado: βœ… Accepted Date: 2026-01-29 Deciders: Rodrigo RoldΓ‘n

ContextΒΆ

Arquitectura de cliente HTTP puede organizarse de varias formas:

  1. Monolithic: Todo en un solo mΓ³dulo

  2. Two-layer: Client + Transport

  3. Three-layer: Client + Protocol + Transport

  4. Multi-layer: Muchas capas de abstracciΓ³n

DecisionΒΆ

Arquitectura de 3 capas claramente separadas:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         CLIENT LAYER                    β”‚
β”‚  Session, Request, Response, WebSocket  β”‚  ← API pΓΊblica, lΓ³gica de negocio
β”‚  Responsabilidad: Estado, cookies, auth β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚         PROTOCOL LAYER                  β”‚
β”‚  HttpParser, Headers, Body, URL         β”‚  ← Parsing HTTP/1.1, WebSocket frames
β”‚  Responsabilidad: Protocolo HTTP        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚         TRANSPORT LAYER                 β”‚
β”‚  Connection, ConnectionPool, TLS        β”‚  ← Sockets, TLS, I/O
β”‚  Responsabilidad: Red, conexiones       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Principios:

  • Separation of concerns: Cada capa tiene responsabilidad ΓΊnica

  • Dependency direction: Client β†’ Protocol β†’ Transport (nunca al revΓ©s)

  • Reusability: Protocol layer compartido entre sync y async

  • Testability: Cada capa testeable independientemente

Mapeo a cΓ³digo:

src/reqivo/
β”œβ”€β”€ client/         ← CLIENT LAYER
β”‚   β”œβ”€β”€ session.py
β”‚   β”œβ”€β”€ request.py
β”‚   β”œβ”€β”€ response.py
β”‚   β”œβ”€β”€ websocket.py
β”‚   └── auth.py
β”œβ”€β”€ http/           ← PROTOCOL LAYER
β”‚   β”œβ”€β”€ http11.py
β”‚   β”œβ”€β”€ headers.py
β”‚   β”œβ”€β”€ body.py
β”‚   └── url.py
β”œβ”€β”€ transport/      ← TRANSPORT LAYER
β”‚   β”œβ”€β”€ connection.py
β”‚   β”œβ”€β”€ connection_pool.py
β”‚   └── tls.py
└── utils/          ← Cross-cutting concerns
    β”œβ”€β”€ timing.py
    └── validators.py

ConsequencesΒΆ

Positive βœ…ΒΆ

  1. Clear separation: Cada capa tiene propΓ³sito definido

  2. Testability: Mockear capas inferiores fΓ‘cilmente

  3. Reusability: Protocol layer usado por sync y async

  4. Maintainability: Cambios localizados en capa correcta

  5. Understandability: Estructura clara para nuevos devs

Negative ❌¢

  1. Indirection: MΓ‘s archivos, mΓ‘s imports

  2. Over-engineering: Puede ser excesivo para proyecto pequeΓ±o

  3. Coupling: Capas deben coordinarse cuidadosamente

MitigationsΒΆ

  • Clear interfaces: Cada capa con API bien definida

  • Documentation: Arquitectura documentada en ADR (este doc)

  • Refactoring freedom: Internals pueden reorganizarse

Layer ResponsibilitiesΒΆ

CLIENT LAYER:

  • Estado de sesiΓ³n (cookies, headers, auth)

  • API pΓΊblica de alto nivel

  • GestiΓ³n de connection pool

  • Business logic (redirects, retries)

PROTOCOL LAYER:

  • Parsing HTTP responses

  • ConstrucciΓ³n HTTP requests

  • WebSocket frame handling

  • Protocol compliance (RFC 7230-7235, RFC 6455)

TRANSPORT LAYER:

  • Socket management (TCP)

  • TLS/SSL handshake

  • Timeout enforcement

  • ConexiΓ³n fΓ­sica a servidor

Alternatives ConsideredΒΆ

  1. Monolithic: Rejected. DifΓ­cil mantener y testear.

  2. Two-layer: Rejected. Protocol y transport muy acoplados.

  3. Four+ layers: Rejected. Over-engineering innecesario.

ReferencesΒΆ

  • Clean Architecture (Robert C. Martin)

  • Layered Architecture Pattern