1. Disciplinas de Desarrollo
Metodologías y enfoques sistemáticos para construir software de calidad con feedback temprano y orientación al dominio.
1.1 🎯 ¿Qué son las Disciplinas de Desarrollo?
Enfoques metodológicos que establecen cómo escribir código, diseñar sistemas y validar funcionalidad. Van más allá de "escribir tests" hacia culturas de calidad integrada.
¿Por qué? Reducen bugs, facilitan refactoring, alinean código con negocio.
¿Quién? Desarrolladores, testers, arquitectos, product owners (especialmente en BDD/ATDD).
¿Cuánto cuesta? Curva de aprendizaje de 2-4 semanas, ROI positivo desde el primer refactor grande.
1.2 🧪 Disciplinas Principales
| Disciplina | Qué es | Por qué usarlo | Cuándo aplicarlo | Dónde | Cómo implementarlo | Esfuerzo | Herramientas |
|---|---|---|---|---|---|---|---|
| TDD (Test-Driven Development) | Escribir tests antes que el código de producción | Diseño emergente, cobertura 100%, refactoring seguro | En lógica de negocio compleja, funciones puras, algoritmos | Backend, utilidades, servicios | Ciclo Red→Green→Refactor: (1) Test falla, (2) Código mínimo que pase, (3) Refactorizar sin cambiar comportamiento | Alto inicial, reduce bugs 80% | pytest, JUnit 5, Jest, Vitest |
| BDD (Behavior-Driven Development) | Especificaciones ejecutables en lenguaje natural (Given-When-Then) | Colaboración negocio-tech, tests legibles para no-devs | Cuando stakeholders deben validar comportamiento | Features críticas, flujos de usuario | Escenarios Gherkin: Given (contexto), When (acción), Then (resultado esperado). Automatizar con step definitions |
Medio, requiere disciplina en escritura | Cucumber, Behave, SpecFlow |
| ATDD (Acceptance Test-Driven Development) | Definir criterios de aceptación con stakeholders antes de implementar | Alineación negocio-tech, reduce retrabajos | Al inicio de cada feature/story | Features completas (UI + Backend) | Workshop con PO/QA: definir escenarios, escribir tests de aceptación (E2E), implementar hasta que pasen | Medio-Alto, alta claridad de requisitos | FitNesse, Robot Framework, Playwright |
| DDD (Domain-Driven Design) | Modelar software según el dominio de negocio, con lenguaje ubicuo | Código refleja negocio, facilita comunicación con expertos | Dominios complejos (finanzas, salud, logística), sistemas de larga vida | Arquitectura, diseño de servicios | Bounded Contexts, Aggregates, Entities, Value Objects, Domain Events, Event Storming con expertos | Alto, transforma arquitectura | EventStorming, Context Mapper |
| FDD (Feature-Driven Development) | Desarrollo iterativo basado en features de negocio visibles | Entregas incrementales, seguimiento claro | Proyectos grandes con múltiples equipos | Gestión de proyectos, planificación | (1) Modelar dominio, (2) Construir lista de features, (3) Planificar/diseñar/construir por feature en ciclos de 2 semanas | Medio, estructura procesos | Jira, Azure DevOps |
| MDD (Model-Driven Development) | Generar código ejecutable desde modelos abstractos (UML, DSL) | Reduce código boilerplate, documentación visual ejecutable | Dominios con patrones repetitivos (CRUD, ETL) | Generación de código, arquitectura | Crear modelos UML/DSL, transformaciones automáticas con plantillas, validar código generado | Alto en setup, escala bien | Eclipse Modeling, PlantUML, Xtext |
| PBT (Property-Based Testing) | Validar propiedades invariantes con casos aleatorios generados | Descubre edge cases que testing manual no cubre | Algoritmos, parsers, funciones matemáticas, validadores | Lógica compleja, transformaciones de datos | Definir propiedades (reverse(reverse(x)) == x), generar 100s de inputs aleatorios, verificar invariantes |
Medio, alta cobertura efectiva | Hypothesis (Python), fast-check (JS), QuickCheck (Haskell) |
1.3 🔄 Ciclo TDD Detallado
1. RED (Test Falla)
└─> Escribir test mínimo que falle
Ejemplo: test_user_can_login()
2. GREEN (Test Pasa)
└─> Código mínimo que pase el test
Puede ser "feo" o hardcoded
3. REFACTOR (Mejorar)
└─> Limpiar sin cambiar comportamiento
Extraer funciones, eliminar duplicación
4. REPEAT
└─> Siguiente test
Reglas de oro TDD:
- No escribir código de producción sin test que lo requiera
- No escribir más test del necesario para fallar
- No escribir más código del necesario para pasar el test
1.4 📝 Ejemplo BDD (Gherkin)
Feature: Autenticación de usuario
Como usuario registrado
Quiero iniciar sesión con email y contraseña
Para acceder a mi cuenta
Scenario: Login exitoso con credenciales válidas
Given un usuario registrado con email "user@example.com"
And contraseña "SecurePass123"
When el usuario intenta iniciar sesión
Then el sistema debe autenticar al usuario
And redirigir al dashboard
Scenario: Login fallido con contraseña incorrecta
Given un usuario registrado con email "user@example.com"
When el usuario intenta iniciar sesión con contraseña "WrongPass"
Then el sistema debe rechazar la autenticación
And mostrar mensaje "Credenciales inválidas"
1.5 🏗️ DDD: Conceptos Clave
| Concepto | Definición | Ejemplo |
|---|---|---|
| Ubiquitous Language | Vocabulario compartido entre negocio y tech | "Orden" en vez de "Pedido" si negocio dice "Orden" |
| Bounded Context | Límite explícito donde un modelo aplica | Contexto "Ventas" vs "Inventario": "Producto" significa cosas distintas |
| Entity | Objeto con identidad única que persiste | Usuario (ID único, cambia atributos pero sigue siendo el mismo) |
| Value Object | Objeto inmutable definido por sus atributos | Dirección, Money (no tiene ID, se reemplaza completo) |
| Aggregate | Cluster de entidades/VOs con raíz que garantiza invariantes | Orden (raíz) contiene LineItems, total siempre es suma de items |
| Domain Event | Algo que ocurrió en el dominio | OrderPlaced, PaymentReceived, ShipmentDispatched |
| Repository | Abstracción para persistir/recuperar aggregates | OrderRepository.findById(), no expone SQL |
1.6 🧪 Property-Based Testing: Ejemplo
from hypothesis import given, strategies as st
# Propiedad: ordenar dos veces debe ser idempotente
@given(st.lists(st.integers()))
def test_sort_idempotent(lista):
sorted_once = sorted(lista)
sorted_twice = sorted(sorted_once)
assert sorted_once == sorted_twice
# Propiedad: revertir dos veces retorna al original
@given(st.text())
def test_reverse_involution(texto):
assert texto == texto[::-1][::-1]
Ventaja: Hypothesis genera cientos de casos (listas vacías, negativas, duplicados, etc.) automáticamente.
1.7 🎯 ¿Cuándo usar cada disciplina?
| Contexto | Disciplina Recomendada | Razón |
|---|---|---|
| Startup/MVP | TDD + BDD ligero | Velocidad, calidad mínima |
| Sistema legacy | ATDD para features nuevas, tests de regresión | Proteger contra regresiones |
| Dominio complejo (fintech, health) | DDD + Event Storming | Alinear modelo con negocio |
| Múltiples equipos | FDD | Coordinación, features independientes |
| Algoritmos críticos | TDD + PBT | Máxima cobertura de edge cases |
| APIs/Integraciones | Contract Testing + BDD | Validar contratos entre servicios |
1.8 🚫 Anti-patrones
| Anti-patrón | Problema | Solución |
|---|---|---|
| Tests después de código | Bajo coverage, tests sesgados | Adoptar TDD, al menos en lógica crítica |
| Gherkin técnico | Usa implementación en Given/When/Then |
Lenguaje de negocio, sin mencionar clases/DBs |
| Tests lentos | Suite tarda >5 min, nadie la corre | Paralelizar, usar mocks, separar integración de unitarios |
| Aggregates gigantes | Order tiene 50 campos |
Separar en Aggregates más pequeños, contexts |
| Sobre-modelado DDD | Todo es Entity/VO/Aggregate | Usar pragmáticamente, no dogmáticamente |