En el campo de la ingeniería de software, la calidad de un sistema no depende únicamente de que cumpla su funcionalidad inicial, sino también de que pueda evolucionar, mantenerse y adaptarse a nuevos requerimientos sin que ello implique un alto costo o riesgo de introducir errores.
Robert C. Martin, Ing. de software
En este contexto, Robert C. Martin, conocido como Uncle Bob, propuso un conjunto de principios de diseño orientado a objetos denominados SOLID. Estos principios constituyen una conjunto de recomendaciones para el desarrollo de software flexible, robusto y con bajo acoplamiento.
En esta primera parte estudiaremos los dos primeros principios:
- Single Responsibility Principle (SRP) – Principio de Responsabilidad Única.
- Open/Closed Principle (OCP) – Principio Abierto/Cerrado.
Ambos principios buscan garantizar la claridad estructural y la extensibilidad del sistema, dos características esenciales en proyectos de software.
1. Principio de Responsabilidad Única (SRP)
1.1 Definición
El Principio de Responsabilidad Única (SRP) establece que una clase debe tener una sola razón para cambiar. Dicho de otra forma, cada clase o módulo dentro de un sistema debe ocuparse únicamente de una responsabilidad o función específica.
1.2 Fundamentación teórica
Este principio se relaciona con el concepto de alta cohesión en diseño de software. Una clase cohesionada concentra sus atributos y métodos en torno a un único propósito, lo que facilita su comprensión y minimiza la propagación de cambios. Cuando una clase asume múltiples responsabilidades, se incrementa la probabilidad de efectos colaterales ante una modificación.
1.3 Ejemplo ilustrativo
Diseño deficiente (violación del SRP):
class Reporte {
void generarReporte() { ... }
void guardarEnArchivo() { ... }
void enviarPorCorreo() { ... }
}
Aquí la clase Reporte
asume múltiples responsabilidades: generar el contenido, persistirlo en almacenamiento y distribuirlo. Cada cambio en cualquiera de esas tareas obliga a modificar la misma clase.
Diseño mejorado (respeta SRP):
class Reporte {
void generarReporte() { ... }
}
class Archivador {
void guardar(Reporte r) { ... }
}
class EnviarCorreo {
void enviar(Reporte r) { ... }
}
En este caso, cada clase se centra en una única responsabilidad, lo cual facilita la mantenibilidad y permite reutilizar componentes de manera independiente.
1.4 Beneficios
- Claridad conceptual: favorece que los estudiantes comprendan el propósito de cada clase.
- Mantenibilidad: se reducen las dependencias innecesarias.
- Pruebas unitarias más simples: cada clase puede validarse de manera aislada.
2. Principio Abierto/Cerrado (OCP)
2.1 Definición
Bertrand Meyer, Ing. de software
“Las entidades de software (clases, módulos, funciones, etc.) deben estar abiertas para su extensión, pero cerradas para su modificación.”
(Bertrand Meyer, 1988, libro Object-Oriented Software Construction)
Esto significa que un sistema debe poder incorporar nuevas funcionalidades sin necesidad de alterar su código ya existente, preservando así su estabilidad.
2.2 Fundamentación teórica
Este principio promueve el uso de abstracciones e interfaces, permitiendo que el sistema sea extensible mediante la creación de nuevas implementaciones. En la práctica, se busca que el código probado y estable no se modifique al añadir nuevos requerimientos, reduciendo la introducción de defectos.
2.3 Ejemplo ilustrativo
Diseño deficiente (violación del OCP):
class Calculadora {
double calcularArea(String figura, double dato) {
if(figura.equals("cuadrado")) {
return dato * dato;
} else if(figura.equals("circulo")) {
return Math.PI * dato * dato;
}
return 0;
}
}
Aquí, cada vez que se incorpora una nueva figura geométrica (triángulo, rectángulo, etc.), la clase debe modificarse, lo cual genera un código rígido y poco escalable.
Diseño mejorado (respeta OCP):
interface Figura {
double calcularArea();
}
class Cuadrado implements Figura {
double lado;
Cuadrado(double lado){ this.lado = lado; }
public double calcularArea(){ return lado * lado; }
}
class Circulo implements Figura {
double radio;
Circulo(double radio){ this.radio = radio; }
public double calcularArea(){ return Math.PI * radio * radio; }
}
class Calculadora {
double calcular(Figura f) {
return f.calcularArea();
}
}
En este modelo, la clase Calculadora
no requiere modificaciones cuando se agregan nuevas figuras. Basta con crear una nueva clase que implemente la interfaz Figura
.
3.4 Beneficios
- Extensibilidad: se facilita la incorporación de nuevas funcionalidades.
- Reducción de errores: al no modificar código probado, se disminuyen los riesgos.
- Fomento del polimorfismo: los estudiantes aprenden a aplicar un concepto central de la programación orientada a objetos.
4. Conclusión
El Principio de Responsabilidad Única y el Principio Abierto/Cerrado representan pilares fundamentales en el diseño de software orientado a objetos.
- El primero se centra en la claridad estructural y la cohesión interna de las clases.
- El segundo busca optimizar la extensibilidad y estabilidad del sistema frente a cambios.
En donde es fundamental el uso del OCP YA QUE NOS DA BENEFICIOS COMO LA EXTENSIBILIDAD, reducción de errores y polimorfismo y ya que estamos que es polimorfismo 😞
Si quiero aplicar metodologías agiles como SCRUM o XP que principios es mas recomendable aplicar?
SOLID está enfocado solamente en facilitar el mantenimiento del desarrollo a futuro o qué otras ventajas ofrece además de orden en la estructura?