Fundamentos de la Programación Orientada a Objetos¶
Este capítulo presenta los fundamentos conceptuales del paradigma orientado a objetos (POO). Se explora la transición desde el paradigma estructurado, se introducen los conceptos esenciales que definen este paradigma, y se desarrollan las heurísticas que permiten identificar objetos a partir de los requerimientos de un sistema.
Introducción: La transición de paradigma¶
El paradigma estructurado (Un pequeño flashback a Programación 1)¶
En Programación 1 se trabajó con el lenguaje C y el paradigma estructurado (también conocido como paradigma procedural o imperativo). Este paradigma se caracteriza por una clara separación entre datos y código:
Datos: Estructurados en registros (
struct), arreglos, tipos primitivos.Código: Organizado en funciones y procedimientos que operan sobre esos datos.
Esta separación implica que los datos son entidades pasivas que esperan ser manipuladas por funciones externas. El siguiente ejemplo en C ilustra este modelo:
// Definición de la estructura de datos
struct Persona {
char nombre[50];
int edad;
char nacionalidad[30];
};
// Función separada que opera sobre la estructura
void saludar(struct Persona p) {
printf("Hola, soy %s\n", p.nombre);
}
// Uso
struct Persona juan = {"Juan", 25, "Argentina"};
saludar(juan); // Función externa que recibe los datosEn este modelo:
Personaes simplemente un contenedor de datos.saludar()es una función independiente que recibe esos datos como parámetro.No existe una conexión lógica o estructural entre la definición de
Personay las operaciones que se pueden realizar sobre una persona.
Este enfoque tiene sentido histórico: las primeras computadoras tenían recursos muy limitados y el paradigma estructurado permitía un control preciso sobre la memoria y el procesamiento. Sin embargo, a medida que los sistemas crecieron en complejidad, las limitaciones de este modelo se hicieron evidentes.
Los límites del paradigma estructurado¶
El paradigma estructurado funciona bien para problemas de complejidad limitada, pero muestra sus debilidades cuando los sistemas crecen. Considerá el siguiente requerimiento:
En el paradigma estructurado, la solución típica involucra múltiples funciones o lógica condicional compleja:
void saludar(struct Persona p) {
if (strcmp(p.nacionalidad, "Argentina") == 0) {
printf("¿Cómo andás?\n");
} else if (strcmp(p.nacionalidad, "España") == 0) {
printf("¿Qué tal?\n");
} else if (strcmp(p.nacionalidad, "Estados Unidos") == 0) {
printf("How are you?\n");
} else if (strcmp(p.nacionalidad, "Japón") == 0) {
printf("*hace una reverencia*\n");
} else {
printf("Hola\n");
}
}Este enfoque presenta algunos problemas estructurales:
Acoplamiento alto: La función
saludar()debe conocer todos los tipos de nacionalidades posibles y sus comportamientos específicos.Violación del principio abierto/cerrado: Agregar una nueva nacionalidad requiere modificar el código existente, introduciendo riesgo de errores.
Responsabilidad mal ubicada: ¿Por qué una función externa debe saber cómo saluda cada nacionalidad? El conocimiento sobre “cómo saluda un argentino” debería residir cerca del concepto “argentino”.
Dispersión del conocimiento: El comportamiento relacionado con “Persona” está fragmentado en múltiples funciones desperdigadas por el código.
Dificultad de mantenimiento: A medida que se agregan más comportamientos (despedirse, presentarse, etc.) y más tipos, la cantidad de código condicional crece exponencialmente.
La crisis del software¶
Estos problemas se manifestaron a gran escala en lo que se conoció como la “crisis del software” en las décadas de 1960 y 1970. Los proyectos de software:
Excedían sistemáticamente sus presupuestos y plazos
Contenían errores difíciles de localizar y corregir
Eran casi imposibles de modificar sin introducir nuevos errores
Tenían código que nadie comprendía completamente
La comunidad académica y la industria buscaron nuevas formas de organizar el código que permitieran manejar la complejidad creciente. De esta búsqueda surgió el paradigma orientado a objetos.
El cambio de mentalidad: de procedimientos a objetos¶
La Programación Orientada a Objetos propone un cambio fundamental en la forma de pensar sobre los programas:
En lugar de pensar “¿qué pasos debo ejecutar para resolver este problema?”, la POO nos invita a pensar “¿qué entidades participan en este problema y cómo interactúan entre sí?”.
Este cambio tiene profundas implicaciones:
Los datos dejan de ser pasivos: En la POO, los datos “saben” qué operaciones pueden realizarse sobre ellos.
El comportamiento se localiza: Cada tipo de dato define su propio comportamiento, eliminando los interminables bloques condicionales.
La responsabilidad se distribuye: En lugar de tener pocas funciones “todopoderosas”, se tienen muchos objetos con responsabilidades acotadas.
La fusión de datos y comportamiento¶
La idea central de la POO es fusionar el dato y el comportamiento en una misma entidad. Esta fusión recibe el nombre de encapsulamiento y constituye la piedra angular del paradigma.
Conceptualmente, el ejemplo de las nacionalidades se resolvería así en POO:
// Uso conceptual:
persona.saludar() // El objeto sabe cómo saludarse a sí mismoLas ventajas de este enfoque son inmediatas:
Cohesión alta: El dato (
nacionalidad) y el comportamiento que depende de él (saludar()) están juntos en la misma unidad.Responsabilidad clara: Cada persona “sabe” cómo saludarse. No hay funciones externas que deban conocer los detalles internos.
Extensibilidad: Se pueden crear variantes especializadas (mediante herencia o composición) sin modificar el código existente.
Ocultamiento de información: Los detalles internos de cómo una persona saluda están ocultos al resto del sistema.
La metáfora de los objetos¶
La palabra “objeto” no es casual. La POO propone modelar los programas como si fueran simulaciones del mundo real, donde entidades con existencia propia interactúan entre sí.
Pensá en un sistema de una biblioteca:
Visión estructurada:
Datos: arreglo de libros, arreglo de socios, arreglo de préstamos
Funciones: prestarLibro(), devolverLibro(), buscarLibro(), etc.Visión orientada a objetos:
Interacciones (comportamiento):
El socio le pide un libro a la biblioteca
La biblioteca verifica disponibilidad
El libro se marca como prestado
Se crea un préstamo que relaciona socio y libro
En la visión orientada a objetos, cada entidad tiene “vida propia”: el libro sabe si está disponible, el socio sabe cuántos préstamos activos tiene, el préstamo sabe cuándo vence. Esta distribución de responsabilidades hace que el sistema sea más fácil de entender, modificar y extender
Conceptos Fundamentales del Paradigma¶
Esta sección presenta los conceptos esenciales que definen el paradigma orientado a objetos. Estos conceptos son universales: aplican independientemente del lenguaje de programación que se utilice.
Clase¶
La clase es una abstracción: existe solo como concepto, como definición. Por sí sola, una clase no ocupa espacio en memoria para almacenar datos concretos; es una especificación de cómo serán los objetos que se creen a partir de ella.
Analogía del mundo real:
Pensá en los planos de una casa. Los planos especifican:
Cuántas habitaciones tendrá la casa
Dónde estarán las ventanas y puertas
Las dimensiones de cada ambiente
Los materiales a utilizar
Pero los planos no son una casa. Son la descripción de cómo construir casas de ese tipo. A partir de los mismos planos se pueden construir múltiples casas, cada una con sus propios habitantes, muebles y decoración.
De la misma manera, una clase Persona describe qué información tiene una persona (nombre, edad, nacionalidad) y qué puede hacer (saludar, presentarse), pero la clase en sí no es ninguna persona en particular.
Objeto¶
Mientras que la clase es la definición, el objeto es la “cosa” real que existe durante la ejecución del programa. Cada objeto:
Ocupa espacio en memoria
Tiene valores concretos en sus atributos
Puede recibir mensajes y responder a ellos
Tiene una existencia temporal: nace, vive y eventualmente muere
Continuando la analogía:
Si la clase Casa es el plano arquitectónico, entonces cada casa construida es un objeto:
Figure 1:Analogía de la casa: la clase como plano y los objetos como construcciones reales.
Ambas casas fueron construidas según los mismos planos, pero son casas diferentes: están en ubicaciones distintas, tienen dueños distintos, pueden tener colores distintos. Modificar una no afecta a la otra.
Atributo¶
Los atributos son las “variables” que cada objeto tiene para almacenar su información. Cada objeto de una clase tiene su propia copia de los atributos con valores potencialmente diferentes.
Características de los atributos:
Están definidos en la clase: La clase especifica qué atributos existen.
Cada objeto tiene su copia: Los valores son independientes entre objetos.
Definen qué se puede “saber” de un objeto: Son las preguntas que se pueden hacer sobre él.
Ejemplo conceptual:
Figure 2:Relación entre la clase Vehículo y sus instancias concretas con valores específicos.
Estado¶
El estado es lo que diferencia a un objeto “recién creado” de uno que ha “vivido” en el sistema. A medida que el objeto recibe mensajes y ejecuta métodos, su estado puede transformarse.
Ejemplo de evolución del estado:
Figure 3:Evolución del estado de un objeto Auto tras recibir mensajes.
Instancia¶
Los términos “objeto” e “instancia” son prácticamente sinónimos, pero se usan en contextos ligeramente diferentes:
Objeto: Enfatiza la entidad en sí misma, su existencia independiente.
Instancia: Enfatiza la relación con la clase de la que proviene.
Ejemplo:
“Juan es un objeto que representa a una persona en nuestro sistema.”
“Juan es una instancia de la clase Persona.”
Ambas frases son correctas y dicen esencialmente lo mismo, pero con diferente énfasis.
El proceso de crear un objeto a partir de una clase se llama instanciación:
Figure 4:Instanciación de la clase Persona para crear el objeto juan.
Método¶
Si los atributos responden a la pregunta “¿qué sabe el objeto?”, los métodos responden a “¿qué puede hacer el objeto?”.
Tipos de métodos según su propósito:
Métodos de consulta: Obtienen información sin modificar el estado.
Ejemplo:
obtenerEdad(),estaEncendido(),calcularArea()
Métodos de modificación: Cambian el estado del objeto.
Ejemplo:
cumplirAnios(),encender(),mover()
Métodos de construcción: Inicializan el objeto al crearlo (constructores).
Ejemplo: Crear una persona con nombre y edad específicos.
Ejemplo conceptual:
Figure 5:Representación de atributos y métodos de la clase CuentaBancaria.
Mensaje¶
La comunicación mediante mensajes es central en la POO. Los objetos no “llaman funciones”; se envían mensajes unos a otros:
Figure 6:Envío de un mensaje de un objeto emisor a un receptor.
Esta forma de pensar tiene implicaciones importantes:
El emisor no sabe cómo se implementa la operación; solo sabe que el receptor puede responder a ese mensaje.
Diferentes objetos pueden responder al mismo mensaje de formas distintas (esto es la base del polimorfismo, que se verá más adelante).
La responsabilidad está en el receptor: Es el objeto receptor quien decide qué hacer con el mensaje.
Ciclo de Vida de los Objetos¶
Todo objeto tiene un ciclo de vida: nace, existe durante un tiempo, y eventualmente deja de existir. Comprender este ciclo es fundamental para diseñar sistemas correctos.
Construcción¶
La construcción es el “nacimiento” del objeto. Es el momento en que pasa de ser una mera posibilidad (la clase) a una realidad concreta (el objeto en memoria).
El constructor:
El constructor es un método especial que se ejecuta automáticamente cuando se crea un objeto. Su responsabilidad es garantizar que el objeto nazca en un estado válido y consistente.
Figure 7:Etapas del proceso de construcción de un nuevo objeto.
Vida del objeto¶
Una vez construido, el objeto “vive” en el sistema:
Recibe mensajes de otros objetos
Ejecuta sus métodos
Modifica su estado
Envía mensajes a otros objetos
Colabora para cumplir los objetivos del sistema
La duración de la vida de un objeto depende de las necesidades del sistema. Algunos objetos viven durante toda la ejecución del programa; otros existen solo brevemente para realizar una tarea específica.
Destrucción¶
La gestión de la destrucción varía según el lenguaje:
Destrucción manual (como en C):
El programador es responsable de liberar la memoria.
Requiere llamadas explícitas como
free().Errores comunes: olvidar liberar (memory leak) o liberar dos veces.
Destrucción automática (Garbage Collection):
El sistema detecta automáticamente cuándo un objeto ya no es accesible.
Un componente llamado “Garbage Collector” (recolector de basura) libera la memoria.
El programador no debe preocuparse por la liberación manual.
Común en lenguajes modernos como Java, Python, C#, Go.
Figure 8:Objeto sin referencias (huérfano) esperando ser recolectado por el Garbage Collector.
Identidad¶
La identidad es un concepto sutil pero fundamental. Considerá este escenario:
Figure 9:Dos objetos con el mismo estado pero diferente identidad física.
Ambos objetos tienen exactamente los mismos valores en todos sus atributos. Sin embargo, son dos objetos diferentes: ocupan diferentes posiciones en memoria y tienen existencias independientes. Si modificamos persona1, persona2 no se ve afectada.
Tipos de igualdad:
Identidad física (¿son el mismo objeto?):
Compara si dos referencias apuntan al mismo objeto en memoria.
Es la igualdad más estricta.
Igualdad lógica (¿representan lo mismo?):
Compara si dos objetos son equivalentes según las reglas del dominio.
Definida por el programador.
Ejemplo:
Identidad física:
persona1 y persona2 son DIFERENTES objetos (diferentes ubicaciones en memoria)
Igualdad lógica (si se define que dos personas son "iguales" cuando tienen el mismo DNI):
persona1 y persona2 serían IGUALES (mismo DNI: "12345678")Abstracción¶
La abstracción es quizás el concepto más importante de todo el paradigma, porque está en la base de todas las decisiones de diseño. Sin abstracción, sería imposible modelar sistemas complejos.
La necesidad de abstraer¶
El mundo real es infinitamente complejo. Una persona tiene:
Nombre, apellido, edad, DNI
Color de pelo, color de ojos, altura, peso
Huella dactilar, ADN, tipo de sangre
Dirección, teléfono, email
Historial médico, educación, trabajo
Preferencias, hobbies, relaciones familiares
Millones de características más...
Es imposible (e innecesario) representar toda esta complejidad en un sistema de software. La abstracción permite seleccionar solo aquellas características que son relevantes para el objetivo específico del sistema.
La abstracción es contextual¶
Considerá cómo se modelaría una “Persona” en diferentes sistemas:
Sistema de gestión universitaria:
// Irrelevantes: color de pelo, altura, peso, tipo de sangre...Sistema de control de acceso a un gimnasio:
// Irrelevantes: DNI, carrera universitaria, email...Sistema de donación de sangre:
// Irrelevantes: legajo universitario, huella dactilar...Observá cómo la misma entidad del mundo real (una persona) se modela de formas radicalmente diferentes según el propósito del sistema.
Niveles de abstracción¶
La abstracción opera en múltiples niveles:
Abstracción de datos: Decidir qué atributos son relevantes.
¿El color de pelo es importante? ¿La altura? ¿El peso?
Abstracción de comportamiento: Decidir qué operaciones son relevantes.
¿Una persona debe poder “saludar”? ¿“caminar”? ¿“respirar”?
Abstracción de relaciones: Decidir qué conexiones entre entidades son relevantes.
¿Importa quiénes son los padres de una persona? ¿Sus amigos? ¿Su jefe?
El proceso de abstracción¶
Abstraer es un proceso de filtrado consciente:
Figure 10:El proceso de filtrado de detalles para obtener un modelo abstracto.
El Encapsulamiento¶
Fusión de datos y comportamiento¶
Ya vimos que la POO fusiona datos y comportamiento. Esta fusión tiene consecuencias importantes:
Figure 11:Comparación entre la separación de datos/funciones y la unidad objeto (encapsulamiento).
Ocultamiento de información¶
El segundo aspecto del encapsulamiento es igualmente importante: ocultar los detalles de implementación.
¿Por qué ocultar?
Protección: Impide que código externo corrompa el estado del objeto.
Flexibilidad: Permite cambiar la implementación interna sin afectar al código que usa el objeto.
Simplicidad: El usuario del objeto solo ve lo que necesita saber.
Modelado de Objetos: Heurísticas de Análisis¶
Una de las habilidades más importantes en la programación orientada a objetos es identificar objetos y su comportamiento a partir de los requerimientos de un sistema. Esta sección presenta técnicas prácticas para realizar esta transformación del “texto” al “modelo”.
Del problema al modelo¶
Cuando se enfrenta un problema nuevo, la primera tarea es identificar:
¿Qué entidades participan en el problema?
¿Qué información caracteriza a cada entidad?
¿Qué operaciones realizan las entidades?
¿Cómo interactúan entre sí?
Las heurísticas de análisis son “reglas del pulgar” que ayudan a responder estas preguntas de manera sistemática.
La Heurística Lingüística¶
La heurística lingüística es una técnica que permite identificar candidatos a clases y métodos mediante el análisis del lenguaje natural usado en la descripción del problema.
Análisis de Sustantivos¶
Proceso:
Leer el texto del requerimiento.
Identificar todos los sustantivos.
Para cada sustantivo, preguntarse:
¿Es una “cosa” con existencia propia? → Posible clase
¿Es una característica de otra cosa? → Posible atributo
Ejemplo de análisis:
“El sistema debe permitir que un cliente realice una reserva de un vehículo especificando la fecha de inicio y la fecha de fin. El vehículo tiene una patente, una marca y un modelo.”
Sustantivos identificados y análisis inicial:
| Sustantivo | ¿Clase o Atributo? | Razonamiento |
|---|---|---|
| Cliente | ¿Clase? | Tiene existencia propia, realiza acciones |
| Reserva | ¿Clase? | Es una “cosa” que relaciona cliente y vehículo |
| Vehículo | ¿Clase? | Tiene existencia propia, tiene características |
| Fecha | ¿Clase o Atributo? | ¿Es simple o compleja? |
| Patente | ¿Atributo? | Es una característica del vehículo |
| Marca | ¿Atributo? | Es una característica del vehículo |
| Modelo | ¿Atributo? | Es una característica del vehículo |
Análisis de Verbos¶
Proceso:
Identificar todos los verbos de acción.
Para cada verbo, preguntarse:
¿Quién realiza esta acción? → Posible clase que tiene el método
¿Sobre qué/quién se realiza? → Posibles parámetros o colaboradores
Continuando el ejemplo:
“El sistema debe permitir que un cliente realice una reserva de un vehículo especificando la fecha de inicio y la fecha de fin. El vehículo puede verificar su disponibilidad en un período dado.”
Verbos identificados:
| Verbo | Acción | ¿Quién la realiza? | Método candidato |
|---|---|---|---|
| Realice | Crear una reserva | Cliente (o Sistema) | realizarReserva() |
| Verificar | Comprobar disponibilidad | Vehículo | verificarDisponibilidad() |
Modelo preliminar:
Figure 12:Modelo preliminar resultante del análisis lingüístico inicial.
Aplicación de Filtros: Refinando el modelo¶
El análisis lingüístico produce una lista de candidatos, pero no todos ellos deben convertirse en elementos del modelo final. Los filtros permiten refinar el diseño eliminando elementos innecesarios o transformándolos apropiadamente.
El Filtro de Abstracción¶
Este filtro aplica directamente el principio de abstracción: solo modelar lo que es relevante para el problema en cuestión.
Ejemplo:
“El sistema debe registrar personas con su nombre, DNI, fecha de nacimiento, color de pelo y equipo de fútbol favorito para gestionar el acceso a un edificio corporativo.”
Aplicando el filtro de abstracción para un sistema de control de acceso:
| Sustantivo | ¿Relevante? | Justificación |
|---|---|---|
| Nombre | ✅ Sí | Identificación del usuario |
| DNI | ✅ Sí | Identificación única |
| Fecha de nacimiento | ⚠️ Dudoso | ¿Se requiere verificar edad? |
| Color de pelo | ❌ No | Irrelevante para acceso |
| Equipo de fútbol favorito | ❌ No | Completamente irrelevante |
Modelo filtrado:
Figure 13:Modelo filtrado de Persona para un sistema de control de acceso.
El Filtro de Complejidad: ¿Valor simple o Clase nueva?¶
Esta es una de las decisiones de diseño más difíciles para programadores novatos. La regla general:
Preguntas guía:
¿El concepto tiene múltiples componentes relacionados?
¿El concepto tiene operaciones propias que se le pueden aplicar?
¿La validación del concepto es compleja?
¿Se repite la misma lógica relacionada con este concepto en múltiples lugares?
Si la respuesta es sí a una o más preguntas, considerar crear una clase independiente.
Ejemplo 1: Fecha de nacimiento
¿fechaNacimiento debe ser un texto simple o una clase?
Figure 14:Comparación entre representar la fecha como un valor simple vs. una clase independiente.
La Opción B es superior porque:
La lógica de fechas está encapsulada en un solo lugar.
Se pueden reutilizar las operaciones de Fecha en todo el sistema.
La validación está centralizada.
Ejemplo 2: DNI
¿El DNI debe ser un texto simple o una clase?
Análisis:
¿Tiene múltiples componentes? → En Argentina, no.
¿Tiene operaciones propias? → Validación de formato, formateo con puntos.
¿La validación es compleja? → Moderadamente (longitud, solo dígitos).
¿Se repite la lógica? → Posiblemente.
Decisión: Depende del contexto. Si el sistema necesita validar y formatear DNIs frecuentemente, una clase DNI es apropiada. Si solo se guarda y muestra, un texto puede bastar.
Figure 15:Estructura de la clase DNI con sus métodos de validación y formateo.
Criterios de decisión resumidos¶
| Situación | Decisión sugerida |
|---|---|
| Solo almacena un valor, sin operaciones | Atributo primitivo |
| Múltiples valores relacionados | Clase nueva |
| Requiere validación compleja | Clase nueva |
| Tiene operaciones específicas | Clase nueva |
| La lógica se repite en varios lugares | Clase nueva |
| Es un concepto del dominio con “vida propia” | Clase nueva |
Identificación de Relaciones¶
Además de clases y atributos, el análisis debe identificar las relaciones entre clases.
Tipos de relaciones comunes:
Asociación: Una clase “conoce” o “usa” a otra.
Agregación: Una clase “contiene” a otras (relación todo-parte débil).
Composición: Una clase “está compuesta por” otras (relación todo-parte fuerte).
Dependencia: Una clase “usa temporalmente” a otra.
Ejemplo rápido:
“Una biblioteca tiene muchos libros. Cada libro tiene un autor. Los socios pueden tomar préstamos de libros.”
Ejemplo Completo de Análisis¶
Requerimiento:
“Una veterinaria necesita gestionar la atención de mascotas. Cada mascota tiene un nombre, una especie, una raza y una fecha de nacimiento. Las mascotas pertenecen a dueños que tienen nombre, teléfono y dirección. Los veterinarios de la clínica realizan consultas a las mascotas, registrando la fecha, el motivo, el diagnóstico y el tratamiento indicado.”
Paso 1: Identificar sustantivos
| Sustantivo | Primera impresión |
|---|---|
| Veterinaria | Clase (el sistema) |
| Mascotas | Clase |
| Nombre | Atributo |
| Especie | ¿Atributo o Clase? |
| Raza | Atributo |
| Fecha de nacimiento | ¿Atributo o Clase? |
| Dueños | Clase |
| Teléfono | Atributo |
| Dirección | ¿Atributo o Clase? |
| Veterinarios | Clase |
| Consultas | Clase |
| Fecha | ¿Atributo o Clase? |
| Motivo | Atributo |
| Diagnóstico | Atributo |
| Tratamiento | ¿Atributo o Clase? |
Paso 2: Identificar verbos
| Verbo | Acción | Actor probable |
|---|---|---|
| Gestionar | Coordinar atención | Veterinaria (sistema) |
| Pertenecen | Relación mascota-dueño | Relación |
| Realizan | Hacer consultas | Veterinario |
| Registrando | Guardar información | Consulta |
Paso 3: Aplicar filtros
Filtro de abstracción: Todos los elementos parecen relevantes para el objetivo.
Filtro de complejidad:
Especie: Valor simple (texto: “Perro”, “Gato”, etc.)Fecha de nacimiento: Usar fecha del sistemaDirección: Clase si tiene calle, número, ciudad, CP; texto simple si no importa la estructuraTratamiento: Podría ser texto o clase si incluye medicamentos, dosis, duración
Paso 4: Modelo resultante
Actividad Práctica: Cazadores y Auditores¶
Posible resolución:
Figure 16:Comparación de abstracciones para sistemas de mantenimiento y viáticos.
Principios Adicionales del Paradigma¶
Colaboración entre Objetos¶
En un sistema orientado a objetos bien diseñado, ningún objeto hace todo el trabajo solo. Los objetos colaboran entre sí, cada uno aportando su especialidad.
Ejemplo de colaboración:
La Factura no sabe cómo calcular el precio de un producto; delega esa responsabilidad en Producto. La LineaFactura no sabe el nombre del cliente; esa información está en Cliente. Cada objeto hace lo suyo y colabora con los demás.
El Principio de Responsabilidad Única¶
Este principio, formulado por Robert C. Martin, es una guía fundamental para diseñar clases cohesivas.
Ejemplo de violación y diseño mejorado:
Figure 17:Refactorización de una clase con múltiples responsabilidades hacia un diseño que cumple el SRP.
Ahora cada clase tiene una única responsabilidad y una única razón para cambiar.
Cohesión y Acoplamiento¶
Dos métricas fundamentales para evaluar la calidad de un diseño orientado a objetos son la cohesión y el acoplamiento.
Cohesión: Mide qué tan relacionados están los elementos dentro de una clase.
Alta cohesión (deseable): Todos los atributos y métodos trabajan juntos hacia un propósito común.
Baja cohesión (problemática): La clase hace cosas poco relacionadas entre sí.
Acoplamiento: Mide qué tan dependiente es una clase de otras clases.
Bajo acoplamiento (deseable): Las clases pueden funcionar y cambiar con independencia relativa.
Alto acoplamiento (problemático): Un cambio en una clase requiere cambios en muchas otras.
Figure 18:Comparación entre una clase altamente cohesiva y una clase de utilidades con baja cohesión.
Resumen¶
Este capítulo ha presentado los fundamentos conceptuales del paradigma orientado a objetos:
La transición de paradigma:
El paradigma estructurado separa datos y código.
El paradigma OO los fusiona en objetos.
Los objetos colaboran enviándose mensajes.
Conceptos fundamentales:
Clase: Molde o plantilla que define estructura y comportamiento.
Objeto: Instancia concreta con estado, comportamiento e identidad.
Atributo: Información que caracteriza al objeto.
Estado: Valores específicos de los atributos en un momento dado.
Método: Operación que el objeto puede realizar.
Mensaje: Comunicación entre objetos.
Ciclo de vida:
Construcción: Creación del objeto con estado inicial válido.
Vida: El objeto existe, recibe mensajes, modifica su estado.
Destrucción: Liberación de recursos (manual o automática).
Identidad: Física (mismo objeto) vs. lógica (equivalencia semántica).
Abstracción y Encapsulamiento:
La abstracción selecciona solo lo relevante para el objetivo.
El encapsulamiento fusiona datos y comportamiento y oculta detalles (ver Encapsulamiento: Protegiendo el Estado).
Heurísticas de análisis:
Sustantivos → Clases o Atributos.
Verbos → Métodos.
Filtro de abstracción: eliminar lo irrelevante.
Filtro de complejidad: decidir entre primitivo y clase nueva (implementación en Sintaxis de Clases y Objetos).
Principios de diseño:
Los objetos colaboran, ninguno hace todo (ver Tipos de Relaciones).
Responsabilidad única: una razón para cambiar (ver Principio de Responsabilidad Única (S)).
Alta cohesión, bajo acoplamiento (ver Principio de Inversión de Dependencias (D)).
Lecturas Recomendadas¶
Meyer, B. (1997). Object-Oriented Software Construction (2nd ed.). Prentice Hall. — Una referencia fundamental sobre los principios de la POO.
Martin, R. C. (2003). Agile Software Development: Principles, Patterns, and Practices. Prentice Hall. — Excelente cobertura de principios de diseño OO (SOLID).
Gamma, E., Helm, R., Johnson, R., & Vlissides, J. (1994). Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley. — El libro clásico de patrones de diseño.
Wirfs-Brock, R., & McKean, A. (2002). Object Design: Roles, Responsibilities, and Collaborations. Addison-Wesley. — Enfoque en diseño basado en responsabilidades.
Ejercicios¶
Solution to Exercise 1
a) Falso. Una clase NO es un objeto; es una definición o especificación. La clase describe cómo serán los objetos, pero ella misma no es un objeto.
b) Falso. Dos objetos de la misma clase tienen la misma ESTRUCTURA (los mismos atributos), pero cada uno tiene sus PROPIOS valores. Juan y María son ambos instancias de Persona, pero tienen nombres diferentes.
c) Verdadero. El encapsulamiento tiene dos aspectos: fusionar datos y comportamiento, y ocultar los detalles de implementación. El usuario del objeto solo ve la interfaz pública.
d) Falso. La abstracción es SUBJETIVA y CONTEXTUAL. Depende del objetivo del sistema. Una persona se modela diferente en un sistema universitario que en un gimnasio.
e) Falso. Dos objetos con el mismo estado siguen siendo OBJETOS DIFERENTES (diferente identidad física). Pueden ser EQUIVALENTES según algún criterio de igualdad lógica, pero no son “el mismo objeto”.
Solution to Exercise 2
Sustantivos identificados:
| Sustantivo | Clasificación | Justificación |
|---|---|---|
| Hospital | Clase | Sistema coordinador |
| Citas médicas | Clase | Entidad central con relaciones |
| Pacientes | Clase | Entidad con comportamiento propio |
| Nombre | Atributo | Dato simple |
| DNI | Atributo/Clase | Simple si solo se guarda, Clase si hay validación |
| Obra social | ¿Atributo/Clase? | Podría tener código, nombre, cobertura |
| Teléfono | Atributo | Dato simple |
| Médicos | Clase | Entidad con comportamiento propio |
| Matrícula | Atributo | Identificador simple |
| Especialidad | ¿Atributo/Clase? | Simple si es texto, Clase si tiene más datos |
| Fecha y hora | Atributo | Usar tipo temporal del lenguaje |
| Consultorio | ¿Atributo/Clase? | Clase si tiene ubicación, capacidad, equipamiento |
Verbos identificados:
| Verbo | Actor | Método candidato |
|---|---|---|
| Solicitar | Paciente | solicitarCita(medico, fecha) |
| Cancelar | Paciente | cancelarCita(cita) |
| Confirmar | Médico | confirmarCita(cita) |
| Reprogramar | Médico | reprogramarCita(cita, nuevaFecha) |
Modelo propuesto:
Figure 19:Modelo de clases propuesto para la resolución del ejercicio del Hospital.
Solution to Exercise 3
a) Temperatura → Clase
Tiene múltiples componentes: valor numérico + unidad (°C, °F, K).
Operaciones: convertir entre unidades, verificar si está en rango, comparar.
Validaciones: temperaturas imposibles (< -273.15°C).
b) Precio → Clase
Tiene múltiples componentes: monto + moneda.
Operaciones: convertir monedas, aplicar descuentos, sumar precios.
Un sistema de e-commerce que opere en múltiples países necesita manejar monedas.
c) Dirección de email → Clase o Valor simple, depende
Si solo se guarda y envía: valor simple (texto).
Si se valida formato, se extrae dominio, se verifica existencia: clase.
Para newsletter básico: probablemente texto sea suficiente.
d) Coordenadas GPS → Clase
Múltiples componentes: latitud + longitud.
Operaciones: calcular distancia entre puntos, verificar si está en zona.
Para delivery, es crítico poder calcular distancias y rutas.
e) Nombre de archivo → Clase o Valor simple, depende
Si solo se guarda: valor simple (texto).
Si se necesita extraer extensión, validar caracteres permitidos, generar nombre único: clase.
Sistema de gestión documental: probablemente clase para manejar extensiones, versionado, etc.
Solution to Exercise 4
Figure 20:Comparación de modelos para el concepto “Libro” en diferentes contextos de aplicación.
Observación clave: El mismo concepto del mundo real (un libro) produce modelos completamente diferentes según el objetivo del sistema. Esto demuestra que la abstracción es contextual.
Próximo paso¶
Para seguir, conviene pasar a el material siguiente, donde el recorrido continúa sobre esta base.