Los principios SOLID son un conjunto de buenas prácticas en el diseño orientado a objetos que promueven la flexibilidad, mantenibilidad y escalabilidad del software.
En esta lección abordaremos los dos últimos principios:
- Segregación de Interfaces (Interface Segregation Principle, ISP)
- Inversión de Dependencias (Dependency Inversion Principle, DIP)
Ambos están estrechamente relacionados con el manejo de abstracciones y la reducción de acoplamiento entre módulos.
🧩 1. Principio de Segregación de Interfaces (ISP)
1.1 Definición
El Principio de Segregación de Interfaces establece que:
“Ningún cliente debe verse obligado a depender de métodos que no utiliza.”
(Robert C. Martin, 2000)
En otras palabras, una interfaz debe ser específica y cohesionada, no una gran estructura con métodos que algunas clases no necesitan.
1.2 Problema que soluciona
Cuando una interfaz contiene demasiados métodos, las clases que la implementan pueden sobrecargarse con funcionalidades irrelevantes, violando el principio de responsabilidad única.
Esto genera acoplamiento innecesario y fragilidad: un cambio en la interfaz afecta a todas las clases que la implementan, incluso si no usan los métodos modificados.
1.3 Ejemplo ❌ violando ISP
public interface IWorker
{
void Work();
void Eat();
}
public class Robot : IWorker
{
public void Work()
{
Console.WriteLine("El robot está trabajando");
}
public void Eat()
{
throw new NotImplementedException("Un robot no come");
}
}
El Robot
se ve obligado a implementar un método que no necesita, lo que rompe el ISP.
1.4 Ejemplo ✅ aplicando ISP
public interface IWorkable
{
void Work();
}
public interface IEatable
{
void Eat();
}
public class Human : IWorkable, IEatable
{
public void Work() => Console.WriteLine("El humano trabaja");
public void Eat() => Console.WriteLine("El humano come");
}
public class Robot : IWorkable
{
public void Work() => Console.WriteLine("El robot trabaja sin descanso");
}
Ahora, cada clase implementa solo las interfaces que necesita, logrando alta cohesión y bajo acoplamiento.
1.5 Beneficios del ISP
- Aumenta la modularidad del sistema.
- Disminuye el acoplamiento entre clases.
- Permite reutilizar interfaces pequeñas y específicas.
- Facilita las pruebas unitarias y la evolución del código.
🔄 2. Principio de Inversión de Dependencias (DIP)
2.1 Definición
El Principio de Inversión de Dependencias establece que:
“Los módulos de alto nivel no deben depender de los módulos de bajo nivel.
Ambos deben depender de abstracciones.”
(Robert C. Martin, 2000)
Y además:
“Las abstracciones no deben depender de los detalles; los detalles deben depender de las abstracciones.”
2.2 Significado conceptual
Tradicionalmente, los módulos de alto nivel (la lógica de negocio) dependen directamente de los módulos de bajo nivel (implementaciones concretas).
El DIP invierte esta relación mediante el uso de interfaces o clases abstractas, promoviendo un diseño flexible, extensible y fácilmente testeable.
2.3 Ejemplo ❌ sin aplicar DIP
public class EmailService
{
public void SendEmail(string message)
{
Console.WriteLine($"Enviando email: {message}");
}
}
public class Notification
{
private EmailService _emailService = new EmailService();
public void Send(string message)
{
_emailService.SendEmail(message);
}
}
Aquí, Notification
depende directamente de EmailService
.
Si se quisiera cambiar el canal de notificación (por ejemplo, SMS), habría que modificar la clase Notification
, violando el principio.
2.4 Ejemplo ✅ aplicando DIP
public interface IMessageService
{
void SendMessage(string message);
}
public class EmailService : IMessageService
{
public void SendMessage(string message)
{
Console.WriteLine($"Enviando email: {message}");
}
}
public class SmsService : IMessageService
{
public void SendMessage(string message)
{
Console.WriteLine($"Enviando SMS: {message}");
}
}
public class Notification
{
private readonly IMessageService _messageService;
public Notification(IMessageService messageService)
{
_messageService = messageService;
}
public void Send(string message)
{
_messageService.SendMessage(message);
}
}
Ahora, Notification
depende de una abstracción (IMessageService), no de una implementación concreta.
Esto permite inyectar diferentes servicios sin modificar la lógica de alto nivel.
2.5 Beneficios del DIP
- Promueve la flexibilidad y reutilización del código.
- Facilita la inyección de dependencias (IoC).
- Permite sustituir componentes fácilmente (p. ej., Email → SMS).
- Reduce el acoplamiento entre módulos.
- Mejora la testabilidad mediante mocking o stubs.
🧩 3. Comparación y síntesis
Principio | Enfoque | Objetivo principal | Beneficio clave |
---|---|---|---|
ISP | Diseño de interfaces | Evitar que las clases implementen métodos que no usan | Aumenta la cohesión |
DIP | Dependencias entre módulos | Separar alto y bajo nivel mediante abstracciones | Reduce el acoplamiento |
💡 4. Conclusión
Los principios de Segregación de Interfaces (ISP) e Inversión de Dependencias (DIP) son esenciales para construir sistemas robustos y escalables.
Aplicarlos correctamente ayuda a reducir el acoplamiento, incrementar la cohesión, y facilitar la evolución del software sin romper su arquitectura base.
En conjunto, ambos principios fortalecen la arquitectura orientada a objetos y permiten crear código más limpio, mantenible y adaptable.