====== 02 - Diagrama de clases ======
El **diagrama de clases** es un diagrama UML que representa las clases de un sistema, sus atributos y métodos, y las **relaciones** entre ellas. Sirve para diseñar antes de codificar, comunicar el diseño y documentar el código existente.
===== 1. La clase =====
Una clase se dibuja como un rectángulo con tres compartimentos: nombre, atributos y métodos.
┌──────────────────────────────┐
│ Book │
├──────────────────────────────┤
│ - id: long │
│ - title: String │
│ - stockQuantity: int │
├──────────────────────────────┤
│ + decrementStock(): void │
│ + isAvailable(): boolean │
└──────────────────────────────┘
La **visibilidad** se indica con un símbolo antes del nombre:
^ Símbolo ^ Visibilidad ^ En Java ^
| ''+'' | Pública | ''public'' |
| ''-'' | Privada | ''private'' |
| ''#'' | Protegida | ''protected'' |
| ''~'' | De paquete | sin modificador |
En PlantUML:
@startuml
class Book {
- id: long
- title: String
- stockQuantity: int
+ decrementStock(): void
+ isAvailable(): boolean
}
@enduml
===== 2. Relaciones =====
===== 2.1 Dependencia =====
Una **dependencia** existe cuando una clase usa otra de forma puntual: recibe un objeto como parámetro, lo devuelve o lo crea. Es la relación más débil: no guarda referencias.
public class BookPrinter {
public void print(Book book) { /* usa el objeto */ }
}
@startuml
BookPrinter ..> Book : usa
@enduml
La flecha discontinua (''..>'') significa *usa*. Si el diseño de ''Book'' cambia, ''BookPrinter'' puede verse afectado; leer las dependencias de un diagrama indica qué clases hay que revisar al cambiar otra.
===== 2.2 Asociación =====
Una **asociación** es una relación estable: una clase guarda una referencia a otra. La **multiplicidad** indica cuántos objetos participan:
^ Notación ^ Significado ^
| ''1'' | Exactamente uno |
| ''0..1'' | Uno o ninguno |
| ''*'' o ''0..*'' | Cero o muchos |
| ''1..*'' | Al menos uno |
@startuml
class Order
class Book
Order "1" --> "*" Book : contains >
@enduml
public class Order {
private final List books;
}
===== 2.3 Agregación y composición =====
Ambas son asociaciones de *todo-parte*:
^ Relación ^ Significado ^ Ciclo de vida ^
| **Agregación** | La parte pertenece al todo, pero puede existir sin él | Independiente |
| **Composición** | La parte no tiene sentido sin el todo | El todo gestiona la parte |
@startuml
class Team
class Player
class Order
class OrderLine
Team o-- Player : agregación
Order *-- OrderLine : composición
@enduml
Un jugador puede existir fuera del equipo (agregación, rombo hueco ''o--''). Una línea de pedido no existe fuera del pedido (composición, rombo relleno ''*--'').
===== 2.4 Herencia y realización =====
La **herencia** (generalización) conecta una subclase con su superclase; la **realización** conecta una clase con la interfaz que implementa. Ambas se dibujan con flecha hueca: línea continua para herencia y discontinua para interfaces.
@startuml
interface Repository
class BookRepository
class Entity
class Book
Entity <|-- Book
Repository <|.. BookRepository
@enduml
public class Book extends Entity implements Repository { /* ... */ }
===== 3. Leer un diagrama =====
^ Pregunta ^ Dónde mirar ^
| ¿Qué depende de esta clase? | Flechas que apuntan hacia ella |
| ¿De qué depende esta clase? | Flechas que salen de ella |
| ¿Qué se puede cambiar sin romper a otros? | Clases con pocas flechas entrantes |
| ¿Dónde está el núcleo del diseño? | Clases a las que apuntan muchas dependencias |
Las dependencias indican el **impacto** de un cambio: cuantas más clases dependen de una, más cuidado exige modificarla. Esta idea reaparece en las pruebas de arquitectura con **ArchUnit**, que comprueban automáticamente esas reglas en el código.
Antes de dibujar, pregúntate qué debe comunicar el diagrama: los conceptos del dominio y sus relaciones, no cada método interno.