📘 Introducción: De componentes aislados a sistemas conectados — La evolución de los diagramas de clases
En el mundo del desarrollo de software, los diagramas de clases son más que simples ilustraciones estáticas: son planos vivos que evolucionan junto con el sistema que representan. En cada etapa del desarrollo, desde los requisitos iniciales hasta el mantenimiento posterior al lanzamiento, el nivel de detalle, la estructura y la intención detrás de un diagrama de clases cambian drásticamente. Sin embargo, persiste un error común:componentes aislados.
Considere la clase típica de procesador de pagos —ProcesadorTarjetaCredito, ProcesadorPayPal, yProcesadorStripe — a menudo modelados como entidades independientes y desconectadas en un diagrama de clases. Aunque esto puede ser suficiente durante el diseño inicial, revela un problema más profundo:una falta de integración y claridad comportamental. Estas clases existen aisladas, sin un mecanismo claro para su selección, configuración o flexibilidad en tiempo de ejecución. Como resultado, el diseño se vuelve rígido, difícil de extender y complicado de probar.
Este artículo explora cómo los diagramas de clases deberíanevolucionar a lo largo de las fases de desarrollo — desde modelos conceptuales de alto nivel hasta diseños detallados y listos para la implementación — y cómoconexiones estratégicas entre componentes pueden transformar un sistema fragmentado en una arquitectura cohesiva y escalable. Nos centraremos en un ejemplo del mundo real: el subsistema de procesamiento de pagos — y mostraremos cómo aplicar elPatrón Estrategia, Patrón Fábrica, yinyección de dependencias puede cerrar la brecha entre clases aisladas y un sistema verdaderamente dinámico y mantenible.
A través dediagramas PlantUMLy de ideas prácticas de diseño, aprenderá a:
- Ir más allá de las relaciones estáticas entre clases.
- Modelar el comportamiento del mundo real y las dinámicas en tiempo de ejecución.
- Diseñe sistemas que sean flexibles, extensibles y fáciles de evolucionar.
Al final, verá que un diagrama de clases bien conectado no es solo una herramienta de documentación — es una visión de cómo debería funcionar su software.
Los diagramas de clases son una de las herramientas UML más potentes para modelar sistemas orientados a objetos. Su nivel de detalle cambia significativamente según el etapa de desarrollo. Esta guía lo lleva a través de cuatro etapas clave del desarrollo de software y muestra cómo evolucionan los diagramas de clases en consecuencia.
🧩 1. Etapa 1: Requisitos y diseño conceptual (Fase temprana)
🎯 Propósito:
-
Capturar conceptos de dominio de alto nivel.
-
Identificar entidades clave y sus relaciones.
-
Facilitar la comunicación entre los interesados y los desarrolladores.
🔍 Características:
-
Enfocarse en entidades de dominio y relaciones.
-
Sin métodos ni atributos (o mínimos).
-
Usar generalización, asociación, agregación, y composición.
-
Evite los detalles de implementación (por ejemplo, modificadores de acceso, tipos de datos).
📌 Ejemplo: Sistema de comercio electrónico (nivel conceptual)
@startuml
' Diagrama de clases conceptual - Fase 1: Requisitos
class Cliente {
+nombre: String
+correo: String
}
class Producto {
+nombre: String
+precio: Decimal
}
class Pedido {
+fechaPedido: Date
+estado: String
}
Cliente "1" -- "0..*" Pedido : realiza
Pedido "1" -- "1..*" Producto : contiene
Producto "1" -- "0..*" Pedido : vendido en
nota derecha de Cliente
Representa a un usuario que compra productos
fin nota
nota derecha de Producto
Artículo físico o digital para la venta
fin nota
nota derecha de Pedido
Un registro de transacción
fin nota
@enduml
✅ Casos de uso: Presentar a los interesados, refinar el modelo de dominio y validar con analistas de negocios.
🧱 2. Fase 2: Análisis y diseño de alto nivel (fase intermedia)
🎯 Propósito:
-
Refinar el modelo de dominio para obtener un diseño más estructurado.
-
Introduzca atributos, operaciones básicas, y asociaciones.
-
Comience a identificar interfaces, clases abstractas, y patrones de diseño.
🔍 Características:
-
Agregue atributos y operaciones (con tipos mínimos).
-
Utiliza clases abstractas y interfaces.
-
Introduce multiplicidad y navegabilidad.
-
Empieza a pensar en responsabilidades y cohesión.
📌 Ejemplo: Sistema de comercio electrónico (nivel de análisis)
@startuml
' Diagrama de clases de alto nivel - Etapa 2: Análisis
@startuml
' Diagrama de clases de alto nivel - Etapa 2: Análisis
clase abstracta Orden {
- orderID: String
- orderDate: Date
- status: String
+calcularTotal(): Decimal
+validar(): Boolean
+guardar(): void
}
class Cliente {
- customerID: String
- name: String
- email: String
+agregarOrden(orden: Orden): void
+obtenerOrdenes(): Lista<Orden>
}
class Producto {
- productID: String
- name: String
- price: Decimal
- stockQuantity: Integer
+estaEnStock(): Boolean
+actualizarStock(cantidad: Integer): void
}
class ItemOrden {
- quantity: Integer
- unitPrice: Decimal
+obtenerSubtotal(): Decimal
}
Cliente "1" -- "0..*" Orden : coloca
Orden "1" -- "1..*" ItemOrden : contiene
ItemOrden "1" -- "1" Producto : referencia
Producto "1" -- "0..*" ItemOrden : aparece en
interfaz ProcesadorPago {
+procesarPago(monto: Decimal): Boolean
}
Orden "1" -- "1" ProcesadorPago : utiliza
@enduml
✅ Casos de uso: Revisión de diseño, alineación del equipo y decisiones iniciales de arquitectura.
🔧 3. Etapa 3: Diseño detallado y implementación (fase tardía)
🎯 Propósito:
-
Prepárate para la codificación.
-
Define atributos exactos, métodos, tipos de datos, modificadores de acceso.
-
Incluir restricciones, dependencias, asociaciones, y composición.
-
Usar patrones de diseño (por ejemplo, Factoría, Estrategia, Singleton).
🔍 Características:
-
Firmas completas de métodos y tipos de retorno.
-
Uso de modificadores de acceso (
+,-,#). -
Dependencias, herencia, interfacesestán completamente especificadas.
-
Puede incluir restricciones (por ejemplo,
<<restricción>>).
📌 Ejemplo: Sistema de comercio electrónico (Diseño detallado)
@startuml
' Diagrama de clases detallado - Etapa 3: Implementación
@startuml
' Diagrama de clases detallado - Etapa 3: Implementación
class Customer {
- customerID: String
- name: String
- email: String
- address: String
+addOrder(order: Order): void
+getOrders(): List<Order>
+validateEmail(): Boolean
}
class Order {
- orderID: String
- orderDate: Date
- status: OrderStatus
- total: Decimal
+calculateTotal(): Decimal
+validate(): Boolean
+save(): void
+cancel(): void
}
class OrderItem {
- quantity: Integer
- unitPrice: Decimal
+getSubtotal(): Decimal
}
class Product {
- productID: String
- name: String
- price: Decimal
- stockQuantity: Integer
+isInStock(): Boolean
+updateStock(amount: Integer): void
+getPrice(): Decimal
}
class PaymentProcessor {
+processPayment(amount: Decimal): Boolean
}
class CreditCardProcessor {
+processPayment(amount: Decimal): Boolean
}
class Payment {
- paymentID: String
- amount: Decimal
- method: String
- timestamp: Date
+confirm(): Boolean
}
' Herencia
Customer <|-- PremiumCustomer
' Interfaces
PaymentProcessor <|-- CreditCardProcessor
PaymentProcessor <|-- PayPalProcessor
' Asociaciones
Customer "1" -- "0..*" Order : coloca
Order "1" -- "1..*" OrderItem : contiene
OrderItem "1" -- "1" Product : referencia
Order "1" -- "1" Payment : tiene
PaymentProcessor "1" -- "1" Payment : procesa
' Restricciones
note right of Order
Estado: [Pendiente, Confirmado, Enviado, Cancelado]
end note
note right of Product
El stock debe ser > 0 para poder venderse
end note
@enduml
✅ Casos de uso: Entrega al desarrollador, generación de código, documentación de diseño.
🛠️ 4. Etapa 4: Mantenimiento y evolución (Post-lanzamiento)
🎯 Propósito:
-
Reflejar cambios del mundo realen el sistema.
-
Documentar refactorización, obsolescencias, nuevas características.
-
Apoyar seguimiento de la deuda técnica y comprensión del sistema.
🔍 Características:
-
Puede incluir obsoleto clases/métodos.
-
Mostrar nuevas clases, elementos renombrados, componentes eliminados.
-
Usar esteriotipos (
<<obsoleto>>,<<singleton>>,<<factoría>>). -
A menudo simplificado para mejorar la legibilidad.
📌 Ejemplo: Sistema de comercio electrónico (etapa de mantenimiento)
@startuml
‘ Sistema de pago mejorado: Patrón Estrategia + Patrón Factoría
@startuml
‘ Sistema de pago mejorado: Patrón Estrategia + Patrón Fábrica
‘ Interfaz
class ProcesadorDePagos {
+procesarPago(monto: Decimal): Boolean
}
‘ Estrategias concretas
class ProcesadorDeTarjetaDeCredito {
+procesarPago(monto: Decimal): Boolean
}
class ProcesadorDePayPal {
+procesarPago(monto: Decimal): Boolean
}
class ProcesadorDeStripe {
+procesarPago(monto: Decimal): Boolean
}
‘ Patrón Fábrica
class FabricaDeProcesadoresDePagos {
+crearProcesador(tipo: String): ProcesadorDePagos
+obtenerTiposDisponibles(): Lista<String>
}
‘ Servicio que utiliza la estrategia
class ServicioDeOrdenes {
– procesador: ProcesadorDePagos
+crearOrden(cliente: Cliente, items: Lista<ElementoDeOrden]): Orden
+establecerProcesadorDePagos(procesador: ProcesadorDePagos): void
}
‘ Entidad de pago
class Pago {
– idDePago: String
– monto: Decimal
– method: String
– timestamp: Date
+confirm(): Boolean
}
‘ Cliente y Pedido (simplificado)
class Cliente {
– customerID: String
– name: String
– email: String
+addOrder(order: Pedido): void
+getOrders(): List<Pedido>
}
class Pedido {
– orderID: String
– orderDate: Date
– status: EstadoPedido
– total: Decimal
+calculateTotal(): Decimal
+validate(): Boolean
+save(): void
+cancel(): void
}
‘ Estereotipos para mayor claridad
PaymentProcessor <<interfaz>>
CreditCardProcessor <<estrategia>>
PayPalProcessor <<estrategia>>
StripeProcessor <<estrategia>>
PaymentProcessorFactory <<factoría>>
OrderService <<servicio>>
‘ Herencia: Patrón Estrategia
CreditCardProcessor <|– PaymentProcessor
PayPalProcessor <|– PaymentProcessor
StripeProcessor <|– PaymentProcessor
‘ La fábrica crea procesadores
PaymentProcessorFactory “1” — “1” PaymentProcessor : crea
‘ OrderService utiliza un procesador (inyección de dependencias)
OrderService “1” — “1” PaymentProcessor : utiliza
‘ OrderService utiliza la fábrica para establecer el procesador
OrderService “1” — “1” PaymentProcessorFactory : configura mediante
‘ Payment depende del procesador
Payment “1” — “1” PaymentProcessor : utiliza
‘ Asociaciones
Customer “1” — “0..*” Order : realiza
Order “1” — “1..*” OrderItem : contiene
OrderItem “1” — “1” Product : referencia
Order “1” — “1” Payment : tiene
‘ Restricciones
note right of Order
Estado: [Pendiente, Confirmado, Enviado, Cancelado]
end note
note right of Payment
Método: “Tarjeta de crédito”, “PayPal”, “Stripe”
end note
note right of PaymentProcessorFactory
Tipos admitidos: “Tarjeta de crédito”, “PayPal”, “Stripe”
Puede ampliarse sin modificar OrderService
end note
@enduml
✅ Casos de uso: Incorporación de nuevos desarrolladores, refactorización del sistema, rastros de auditoría.
🔄 Resumen: Evolución de los diagramas de clases
| Etapa | Enfoque | Nivel de detalle | Elementos clave |
|---|---|---|---|
| 1. Requisitos | Conceptos del dominio | Nivel alto | Entidades, asociaciones |
| 2. Análisis | Estructura del sistema | Medio | Atributos, operaciones, interfaces |
| 3. Implementación | Listo para código | Alto | Tipos, modificadores de acceso, patrones |
| 4. Mantenimiento | Evolution del sistema | Adaptativo | Estereotipos, obsolescencias, simplificación |
🛠️ Consejos para usar PlantUML
-
Utilice
@startumly@endumlpara envolver los diagramas. -
Utilice
<<estereotipo>>para patrones de diseño o metadatos. -
Utilice
nota a la derecha depara documentación. -
Utilice
+,-,#para visibilidad (público,privado,protegido). -
Utilice
<<interfaz>>,<<abstracto>>,<<singleton>>para claridad. -
Genere imágenes mediante PlantUML en línea o complementos de IDE (VS Code, IntelliJ).
📚 Pensamientos finales
Los diagramas de clases son no estáticos — ellos evolucionan con el proyecto. Úsalos estratégicamente:
-
Temprano: Comunica con los interesados no técnicos.
-
Medio: Alinea a los desarrolladores sobre la arquitectura.
-
Tarde: Guía la implementación y la calidad del código.
-
Post-lanzamiento: Mantén el conocimiento del sistema.
✅ Consejo profesional: Controla las versiones de tus archivos PlantUML junto con el código — ¡son documentación viva!
✅ Conclusión: Diseñar no solo clases, sino sistemas
Los diagramas de clases son más que diagramas — son mapas de intención, planteamientos de colaboración, y registros vivos de la evolución arquitectónica. Como hemos visto, su valor no está en su forma inicial, sino en cómo se adaptan a lo largo del ciclo de vida del desarrollo — desde las abstracciones de alto nivel de los requisitos hasta los modelos precisos y listos para la implementación del diseño avanzado.
El recorrido desde clases de procesador aisladas hasta un sistema conectado y orientado por estrategias ilustra una verdad fundamental: un buen diseño no se trata solo de definir componentes — se trata de definir cómo trabajan juntos. Cuando CreditCardProcessor, PayPalProcessor, y StripeProcessor se tratan como estrategias intercambiables — orquestadas por una fábrica e inyectadas en servicios — el diagrama deja de ser una instantánea estática. Se convierte en un modelo dinámico de flexibilidad, escalabilidad y mantenibilidad.
Al utilizar patrones como Estrategia, Fábrica, y Inyección de Dependencias, transformamos clases aisladas en un ecosistema cohesivo y extensible. Esto no se trata solo de mejores diagramas — se trata de construir mejores software. Permite a los equipos:
- Agregar nuevos métodos de pago sin tocar el código existente.
- Probar el comportamiento de forma aislada.
- Evolver sistemas con confianza, incluso años después del lanzamiento.
En última instancia, los diagramas de clases más poderosos no son aquellos que muestran cada campo y método en detalle — sino aquellos que cuentan una historia: una historia de colaboración, adaptabilidad y diseño pensado en el futuro.
Así que mientras esbozas tu próximo diagrama de clases, pregúntate:
¿Mis clases solo están definidas — o están conectadas?
¿Están aisladas — o forman parte de un sistema que puede crecer?
Porque al final, los mejores diagramas de clases no solo describen lo que es el sistema — sino que inspiran cómo debería convertirse.







