Como vimos en el artículo de los principios SOLID este es el segundo principio.
Significado
Este principio Establece que las clases deben estar abiertas para su extensión, pero cerradas para su modificación.
Ejemplo
Siguiendo con el ejemplo de la clase Persona que vimos en el artículo del principio de responsabilidad única imaginemos que tenemos una lista de personas(array) y queremos imprimir por pantalla las personas que tengan la edad suficiente para conducir un vehículo. Pero debemos tener en cuenta que según el país esta edad puede ser distinta. Para completar este programa crearemos una clase ListaDePersonasMayoresDeEdad que resolverá este problema con la función imprimeConductores().
Para el ejemplo de código en lugar de cargar los datos de personas de la base de datos tendremos una lista que se rellenará en el constructor de la clase ListaDePersonasMayoresDeEdad.
El código de ejemplo quedaría así:
class Persona {
propiedad nombre
propiedad apellidos
propiedad nacionalidad
propiedad fechaDeNacimiento
funcion calculaEdad()
}
class ListaDePersonasMayoresDeEdad {
propiedad listaDePersonas
funcion Constructor() {
listaDePersonas = [
Persona(“Fulano”, “De tal”, Español, 1/5/1981),
Persona(“Mengano”, “De cual”, Mejicano, 3/12/1992),
Persona(“John”, “Doe”, Norteamericano, 13/2/2012),
Persona(“Boris”, “Stalin”, Ruso, 20/9/1999)
]
}
funcion imprimeConductores() {
bucle personaDeLaLista en listaDePersonas {
Si personaDeLaLista.nacionalidad = Español Y personaDeLaLista.calculaEdad() >= 18
entonces imprime(personaDeLaLista)
Si personaDeLaLista.nacionalidad = Norteamericano Y personaDeLaLista.calculaEdad() >= 16
entonces imprime(personaDeLaLista)
Si personaDeLaLista.nacionalidad = Ruso Y personaDeLaLista.calculaEdad() >= 18
entonces imprime(personaDeLaLista)
}
}
}
Este programa no cumple el principio de abierto/cerrado por la sencilla razón de la necesidad de modificar la clase ListaDePersonasMayoresDeEdad cada vez que haya una nacionalidad nueva en nuestra base de datos. La función imprimeConductores() tendría que ser modificada cada vez que en la base de datos apareciese un usuario con una nueva nacionalidad.
Solución
Dependiendo de las características y las capacidades del lenguaje de programación que estemos utilizando la solución puede crearse mediante clases abstractas, protocolos o empleando una solución generalista como la creación de una clase nacionalidad que encapsule ciertos requisitos en la base de datos.
El objetivo de la solución se enfoca en evitar tener que modificar una función o clase en el futuro simplemente porque se agreguen nuevos datos a la base de datos.
Recordemos que este principio nos mueve a extender una clase para evitar estar modificando otra constantemente. Por esa razón podemos extender la clase Persona gracias a la nueva clase Nacionalidad
Veamos el código de esta solución.
class Persona {
propiedad nombre
propiedad apellidos
propiedad nacionalidad
propiedad fechaDeNacimiento
funcion calculaEdad()
}
class Nacionalidad {
propiedad nombreDeNacionalidad
propiedad edadParaConducir
}
class ListaDePersonasMayoresDeEdad {
propiedad listaDePersonas
propiedad nacionalidades
funcion Constructor() {
nacionalidades = [
Nacionalidad(Español , 18),
Nacionalidad(Norteamericano , 21),
Nacionalidad(Mejicano , 15),
Nacionalidad(Ruso , 18),
]
listaDePersonas = [
Persona(“Fulano”, “De tal”, Español, 1/5/1981),
Persona(“Mengano”, “De cual”, Mejicano, 3/12/1992),
Persona(“John”, “Doe”, Norteamericano, 13/2/2012),
Persona(“Boris”, “Stalin”, Ruso, 20/9/1999)
]
}
funcion imprimeConductores() {
bucle personaDeLaLista en listaDePersonas {
Si personaDeLaLista.calculaEdad() >= personaDeLaLista.nacionalidad.edadParaConducir
entonces imprime(personaDeLaLista)
}
}
}
Ahora el bucle que hay en la función imprimeConductores() se ha reducido y es más legible.
Esta solución es más fácil de mantener y facilita que la clase Nacionalidad pueda incorporar más información interesante para nuestra aplicación y su mantenimiento ha mejorado al no existir la necesidad de modificar eternamente una función de una clase concreta dependiendo de qué datos hay en la base de datos.