IF0100 - Programacion OO II

Unidad 5: Arquitectura de Datos Desconectados

Clase 2: Clean Architecture

Jueves, 28 de mayo de 2026 Semana 17 - Jueves (60 minutos) 30 min Teoría 30 min Práctica

E6: Proyecto Final - Hoy (Jueves 28/05/2026)

Objetivos de Aprendizaje

Al finalizar esta clase, seras capaz de:

  • Entender los principios de Clean Architecture
  • Organizar codigo en capas independientes
  • Aplicar la regla de dependencias
  • Estructurar un proyecto con Clean Architecture
  • Separar dominio de infraestructura

Que es Clean Architecture? (15 min)

Clean Architecture (Arquitectura Limpia) es un patron propuesto por Robert C. Martin que organiza el software en capas concentricas.

Principios clave:
  • Independencia de frameworks
  • Testeable sin UI, base de datos, servidor
  • Independencia de UI
  • Independencia de base de datos
  • Independencia de agentes externos

Capas de Clean Architecture (20 min)

                    ┌─────────────────────────────────────────┐
                    │              FRAMEWORKS                 │
                    │       (FastAPI, SQLAlchemy, DB)        │
                    │  ┌─────────────────────────────────┐   │
                    │  │        INTERFACE ADAPTERS        │   │
                    │  │    (Controllers, Gateways)      │   │
                    │  │  ┌───────────────────────────┐  │   │
                    │  │  │    USE CASES / SERVICES   │  │   │
                    │  │  │   (Business Rules)        │  │   │
                    │  │  │  ┌───────────────────┐   │  │   │
                    │  │  │  │    ENTITIES       │   │  │   │
                    │  │  │  │  (Enterprise      │   │  │   │
                    │  │  │  │   Business Rules) │   │  │   │
                    │  │  │  └───────────────────┘   │  │   │
                    │  │  └───────────────────────────┘  │   │
                    │  └─────────────────────────────────┘   │
                    └─────────────────────────────────────────┘

Capas explicadas

CapaResponsabilidadEjemplo
EntitiesReglas de negocio centralesUsuario, Tarea, Proyecto
Use CasesLogica de aplicacionUsuarioService, TareaService
Interface AdaptersConvierten datosControllers, Repositories, DTOs
FrameworksHerramientas externasFastAPI, SQLAlchemy, PostgreSQL

Regla de Dependencias (15 min)

Las dependencias solo pueden apuntar hacia adentro:

Regla: El codigo interno NO debe conocer el codigo externo.
# ❌ INCORRECTO: Entity depende de infraestructura
from sqlalchemy import Column, String  # MAL!

class Usuario:
    username = Column(String(50))  # Entity acoplada a SQLAlchemy


# ✅ CORRECTO: Entity es agnostica
class Usuario:
    def __init__(self, username: str, email: str):
        self.username = username
        self.email = email
    
    def es_valido(self) -> tuple[bool, str]:
        if len(self.username) < 3:
            return False, "Username muy corto"
        if "@" not in self.email:
            return False, "Email invalido"
        return True, "OK"

Estructura del Proyecto (20 min)

taskflow/
├── domain/                    # ENTITIES (Centro)
│   ├── entities.py           # Clases de dominio puras
│   ├── value_objects.py      # Objetos de valor
│   └── exceptions.py         # Excepciones de dominio
│
├── application/               # USE CASES
│   ├── services/             # Logica de aplicacion
│   │   ├── usuario_service.py
│   │   ├── proyecto_service.py
│   │   └── tarea_service.py
│   └── interfaces/           # Contratos (ABC)
│       └── repositories.py
│
├── infrastructure/            # INTERFACE ADAPTERS
│   ├── repositories/         # Implementacion repositorios
│   │   ├── base.py
│   │   └── usuario_repo.py
│   ├── database.py           # Configuracion DB
│   └── adapters/             # Adaptadores externos
│
├── api/                       # FRAMEWORKS
│   ├── routes/               # Endpoints FastAPI
│   ├── dependencies.py       # Inyeccion de dependencias
│   └── schemas/              # Pydantic DTOs
│
└── tests/                     # Tests
    ├── unit/                 # Tests de dominio
    ├── integration/          # Tests de integracion
    └── conftest.py

Ejemplo: Flujo completo

# 1. DOMAIN - Entity pura
class Usuario:
    def __init__(self, username: str, email: str):
        self.username = username
        self.email = email
        self.activo = True

# 2. APPLICATION - Service
class UsuarioService:
    def __init__(self, repo: UsuarioRepository):
        self.repo = repo
    
    def crear_usuario(self, username: str, email: str) -> Usuario:
        if self.repo.existe_username(username):
            raise ValueError("Username ya existe")
        usuario = Usuario(username, email)
        return self.repo.crear(usuario)

# 3. INFRASTRUCTURE - Repository
class UsuarioRepositorySQLAlchemy(UsuarioRepository):
    def crear(self, usuario: Usuario) -> Usuario:
        modelo = UsuarioModel(
            username=usuario.username,
            email=usuario.email
        )
        self.db.add(modelo)
        self.db.commit()
        return usuario

# 4. API - Route
@router.post("/usuarios")
def crear(
    data: UsuarioCreate,
    service: UsuarioService = Depends(get_usuario_service)
):
    return service.crear_usuario(data.username, data.email)

Ejercicio: Refactorizar TaskFlow (15 min)

Reorganiza el proyecto TaskFlow siguiendo Clean Architecture:

  1. Mover modelos de dominio a domain/entities.py
  2. Crear servicios en application/services/
  3. Mover repositorios a infrastructure/repositories/
  4. Crear interfaces en application/interfaces/
E6 Proyecto Final: La arquitectura debe ser Clean Architecture completa.

Resumen

  • Clean Architecture: Organiza codigo en capas concentricas
  • Dependencias hacia adentro: El nucleo no conoce lo externo
  • Entities: Reglas de negocio centrales
  • Use Cases: Logica de aplicacion
  • Interface Adapters: Conversion de datos
  • Frameworks: Herramientas externas
← Anterior: Repository Pattern
Clase 22 de 25
Siguiente: DTOs y Serialización →