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<Book> 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.