Principio Objetivo Beneficio
SRP Una responsabilidad por clase Código más cohesivo y mantenible
OCP Abierto para extensión, cerrado para modificación Menos riesgo al agregar funcionalidades
LSP Subclases intercambiables con superclases Polimorfismo seguro
ISP Interfaces específicas y pequeñas Menos dependencias innecesarias
DIP Depender de abstracciones Código más flexible y testeable

Single Responsibility Principle (SRP)

Principio

“Una clase debe tener una sola razón para cambiar”

Propósito

Buscar que cada clase tenga una única responsabilidad bien definida, evitando:

  • Clases que hacen demasiadas cosas
  • Alto acoplamiento entre funcionalidades
  • Dificultades para testing y mantenimiento

Diagrama

classDiagram
    namespace ViolacionSRP {
        class UserManager {
            <<Viola SRP>>
            +validateUser(user)
            +saveUser(user)
            +sendWelcomeEmail(user)
            +logUserCreation(user)
            +generateReport(user)
        }
    }
    
    namespace AplicacionCorrecta {
        class UserController {
            +createUser(request)
            +updateUser(id, request)
        }
        
        class UserValidator {
            +validate(user)
        }
        
        class UserRepository {
            +save(user)
            +findById(id)
        }
        
        class EmailService {
            +sendWelcomeEmail(user)
        }
        
        class AuditService {
            +logUserCreation(user)
        }
    }
    
    UserController --> UserValidator
    UserController --> UserRepository
    UserController --> EmailService
    UserController --> AuditService

Open/Closed Principle (OCP)

Principio

“Las clases deben estar abiertas para extensión, cerradas para modificación”

Propósito

Lograr que el código sea extensible sin modificar lo existente, evitando:

  • Romper funcionalidad probada al agregar features
  • Riesgo en despliegues por cambios en código estable
  • Dificultad para agregar nuevas funcionalidades

Diagrama

classDiagram
    namespace ViolacionOCP {
        class DiscountCalculator {
            <<Viola OCP>>
            +calculateDiscount(order, type)
            -calculateStudentDiscount()
            -calculateSeniorDiscount()
            -calculateVipDiscount()
        }
    }
    
    namespace AplicacionCorrecta {
        class DiscountStrategy {
            <<interface>>
            +calculateDiscount(order)
            +isApplicable(customer)
        }
        
        class StudentDiscountStrategy {
            +calculateDiscount(order)
            +isApplicable(customer)
        }
        
        class SeniorDiscountStrategy {
            +calculateDiscount(order)
            +isApplicable(customer)
        }
        
        class VipDiscountStrategy {
            +calculateDiscount(order)
            +isApplicable(customer)
        }
        
        class DiscountService {
            -strategies: List~DiscountStrategy~
            +calculateBestDiscount(order, customer)
        }
        
    }
    
    DiscountStrategy <|.. StudentDiscountStrategy
    DiscountStrategy <|.. SeniorDiscountStrategy
    DiscountStrategy <|.. VipDiscountStrategy
    DiscountService --> DiscountStrategy

Liskov Substitution Principle (LSP)

Principio

“Los objetos de una superclase deben ser reemplazables por objetos de sus subclases sin alterar el funcionamiento del programa”

Propósito

Garantizar que el polimorfismo funcione correctamente, evitando:

  • Subclases que rompen el contrato de la clase padre
  • Comportamientos inesperados al usar herencia
  • Violaciones de las expectativas de la interfaz

Diagrama

classDiagram
    namespace ViolacionLSP {
        class Bird_Wrong {
            <<Viola LSP>>
            +fly()
        }
        
        class Penguin_Wrong {
            +fly() throws Exception
        }
        
    }
    
    namespace AplicacionCorrecta {
        class Bird {
            <<abstract>>
            +move()
            +eat()
        }
        
        class FlyingBird {
            <<abstract>>
            +fly()
            +move()
        }
        
        class FlightlessBird {
            <<abstract>>
            +walk()
            +move()
        }
        
        class Eagle {
            +fly()
            +move()
        }
        
        class Penguin {
            +walk()
            +swim()
            +move()
        }
    }
    
    Bird_Wrong <|-- Penguin_Wrong
    Bird <|-- FlyingBird
    Bird <|-- FlightlessBird
    FlyingBird <|-- Eagle
    FlightlessBird <|-- Penguin

Interface Segregation Principle (ISP)

Principio

“Los clientes no deben depender de interfaces que no usan”

Propósito

Crear interfaces específicas y cohesivas, evitando:

  • Interfaces “gordas” con demasiados métodos
  • Forzar clases a implementar métodos innecesarios
  • Alto acoplamiento por interfaces demasiado amplias

Diagrama

classDiagram
    namespace ViolacionISP {
        class Worker_Fat {
            <<Viola ISP>>
            +work()
            +eat()
            +sleep()
            +attendMeeting()
            +writeCode()
            +designUI()
        }
        
        class Robot_Forced {
            +work()
            +eat() throws Exception
            +sleep() throws Exception
            +attendMeeting() throws Exception
            +writeCode()
            +designUI() throws Exception
        }
        
    }
    
    namespace AplicacionCorrecta {
        class Workable {
            <<interface>>
            +work()
        }
        
        class Eatable {
            <<interface>>
            +eat()
        }
        
        class Sleepable {
            <<interface>>
            +sleep()
        }
        
        class Programmable {
            <<interface>>
            +writeCode()
        }
        
        class Developer {
            +work()
            +eat()
            +sleep()
            +writeCode()
        }
        
        class Robot {
            +work()
            +writeCode()
        }
    }
    
    Worker_Fat <|.. Robot_Forced
    Workable <|.. Developer
    Eatable <|.. Developer
    Sleepable <|.. Developer
    Programmable <|.. Developer
    Workable <|.. Robot
    Programmable <|.. Robot

Dependency Inversion Principle (DIP)

Principio

“Depende de abstracciones, no de concreciones”

Propósito

Invertir las dependencias hacia abstracciones, evitando:

  • Acoplamiento fuerte a implementaciones concretas
  • Dificultades para testing (mocks/stubs)
  • Poca flexibilidad para cambiar implementaciones

Diagrama

classDiagram
    namespace ViolacionDIP {
        class OrderService_Wrong {
            <<Viola DIP>>
            -repository: MySQLOrderRepository
            -emailService: SMTPEmailService
            +createOrder(order)
        }
        
        class MySQLOrderRepository_Concrete {
            +save(order)
        }
        
        class SMTPEmailService_Concrete {
            +sendConfirmation(email)
        }
        
    }
    
    namespace AplicacionCorrecta {
        class OrderService {
            -repository: OrderRepository
            -emailService: EmailService
            +createOrder(order)
        }
        
        class OrderRepository {
            <<interface>>
            +save(order)
            +findById(id)
        }
        
        class EmailService {
            <<interface>>
            +sendConfirmation(email)
        }
        
        class MySQLOrderRepository {
            +save(order)
            +findById(id)
        }
        
        class MongoOrderRepository {
            +save(order)
            +findById(id)
        }
        
        class SMTPEmailService {
            +sendConfirmation(email)
        }
        
        class SendGridEmailService {
            +sendConfirmation(email)
        }
    }
    
    OrderService_Wrong --> MySQLOrderRepository_Concrete
    OrderService_Wrong --> SMTPEmailService_Concrete
    OrderService --> OrderRepository
    OrderService --> EmailService
    OrderRepository <|.. MySQLOrderRepository
    OrderRepository <|.. MongoOrderRepository
    EmailService <|.. SMTPEmailService
    EmailService <|.. SendGridEmailService