Diseño con UML

El Lenguaje Unificado de Modelado (UML) es el estándar para visualizar y documentar la arquitectura de tus sistemas antes de programar.

¿Por qué diseñar antes de codear?

Detectá errores de arquitectura antes de escribir una sola línea. Un buen diagrama ahorra horas de refactor y debugging.

Lenguaje Universal

Cualquier desarrollador del mundo puede leer un diagrama UML sin importar el lenguaje del proyecto. Es el estándar de la industria.

¿Qué vas a aprender?

Clases
Atributos y Métodos
Visibilidad (+/-/#)
Asociación
Agregación
Composición
Herencia
Multiplicidad

01. Anatomía de una Clase

Una clase UML se divide en tres compartimentos: nombre, atributos y métodos. La visibilidad se indica con un símbolo antes de cada elemento.

Usuario
- nombre: String
- edad: int
+ email: String
+ login(): boolean
# validarEdad(): void
- hashear(): String

Clase "Usuario" en notación UML estándar

Modificadores de Visibilidad

+
Público (public)
Accesible desde cualquier otra clase del sistema.
-
Privado (private)
Solo accesible dentro de la misma clase. Promueve encapsulamiento.
#
Protegido (protected)
Accesible por la clase y todas sus subclases heredadas.
Usuario.java Equivalente en Java
public class Usuario {

    // Atributos
    private String nombre;
    private int edad;
    public String email;

    // Métodos
    public boolean login() {
        // ...
    }

    protected void validarEdad() {
        // ...
    }

    private String hashear() {
        // ...
    }
}

02. Relaciones entre Clases

La clave está en reconocer la "fuerza" del vínculo. No es lo mismo "conocer" que "ser parte de".

Vínculo débil Vínculo fuerte
Asociación Agregación Composición
Asociación

Vínculo básico

Una clase conoce a otra y mantiene una referencia. Es la relación más genérica: ambas entidades existen y viven de forma completamente independiente.

Conductor.java
public class Conductor {
    private Vehiculo auto;

    public void manejar() {
        auto.arrancar();
    }
}
Conductor
+ manejar()
Vehículo
+ arrancar()

"Un conductor usa un vehículo"

Agregación

"Tiene un" — débil

La parte puede existir de forma independiente. Si el contenedor se destruye, sus partes sobreviven y pueden pertenecer a otro.

Empresa.java
public class Empresa {
    private List<Empleado> staff;

    // Empleados vienen de afuera ◇
    public void contratar(Empleado e) {
        staff.add(e);
    }
}
Empresa
+ contratar()
Empleado
+ trabajar()

"Si la empresa cierra, el empleado sigue existiendo"

Composición

"Es parte de" — fuerte

La parte no puede existir sin el todo. Sus ciclos de vida están completamente atados: si el contenedor muere, todas las partes mueren con él.

Edificio.java
public class Edificio {
    private List<Habitacion> habs;

    // Habitaciones se CREAN dentro ◆
    public Edificio(int n) {
        habs = new ArrayList<>();
        for (int i=0; i<n; i++)
            habs.add(new Habitacion());
    }
}
Edificio
+ construir()
Habitación
+ limpiar()

"Si el edificio se destruye, las habitaciones también"

Comparativa rápida

Relación Símbolo Frase clave ¿Parte sobrevive?
Asociación "A usa B" Sí — independientes
Agregación "A tiene B" — B sobrevive
Composición "B es parte de A" No — muere con A

03. Herencia (Generalización)

Relación "es un". La subclase hereda todos los atributos y métodos de la superclase, y puede extenderlos o sobreescribirlos.

Animal
- nombre: String
+ comer(): void
+ dormir(): void
Perro
- raza: String
+ ladrar(): void
Gato
- pelaje: String
+ maullar(): void
Ave
- plumaje: String
+ volar(): void
La flecha con punta triangular vacía siempre apunta hacia la superclase

💡 Recuerda

Perro "es un" Animal, por eso usa herencia. En cambio, si Perro simplemente "usa" un collar, eso sería una Asociación.

Animal.java Superclase
public class Animal {
    private String nombre;

    public void comer() {
        System.out.println("Comiendo...");
    }

    public void dormir() {
        System.out.println("Zzz...");
    }
}
Perro.java Subclase
public class Perro extends Animal {
    private String raza;

    public void ladrar() {
        System.out.println("Guau!");
    }

    @Override
    public void comer() {
        System.out.println("Perro comiendo");
    }
}

04. Multiplicidad

Indica cuántas instancias participan en cada extremo de una relación. Se escribe sobre la línea, cerca de cada clase.

1

Exactamente uno

0..1

Cero o uno

*

Cero o más

1..*

Uno o más

Ejemplo: Sistema Universitario

Carrera
- nombre: String
1 1..*
Materia
- codigo: int
* *
Alumno
- legajo: int

"Una carrera tiene 1 o más materias. Una materia puede tener muchos alumnos y viceversa."

¿Cómo leer la multiplicidad?

A 1 ——— * B Un A se relaciona con muchos B
A * ——— * B Muchos A se relacionan con muchos B (N:M)
A 1 ——— 1 B Exactamente un A con exactamente un B (1:1)
A 1 ——— 0..1 B Un A con cero o un B (opcional)
Carrera.java
public class Carrera {
    private String nombre;

    // 1 carrera → 1..* materias
    private List<Materia>
        materias;
}
Materia.java
public class Materia {
    private int codigo;

    // * materias ↔ * alumnos
    private List<Alumno>
        alumnos;
}
Alumno.java
public class Alumno {
    private int legajo;

    // * alumnos ↔ * materias
    private List<Materia>
        materias;
}

¡Ya dominás los diagramas!

Un buen diseño UML ahorra horas de debugging. Practica dibujando las relaciones de tu próximo proyecto.

Volver a Cursos