Los principios SOLID datan de principios de siglo —del nuevo, no del viejo—, y establecen unas pautas generales para diseñar software más legible, mantenible y escalable. Hasta aquí, todo bien. SOLID son las 5 siglas, de cinco principios.
“S”, de Single Resposibility principle, o lo que
vendría a ser; que cada clase debe tener una sola responsabilidad. Si es de
negocio, ¡es de negocio! no debe incluir lógica de comunicaciones. Nada de
andar metiendo IFs en los
controladores.
La “O”, de Open/Closed
principle, es decir que los objetos o las entidades, deben ser
abiertas para las extensiones, pero cerradas para las modificaciones.
—¡Me perdí,
a otra cosa! ¿Abiertas? ¿Cerradas?
—Entiendo.
Es difícil. Y muchas veces entra en conflicto con otros patrones de diseño.
Algunas veces hay clases abiertas para su modificación ¿un Proxy, por ejemplo?
y otras que no, que las tienes que extender.
Que hagas
las clases de modo que cuamplan con un comportamiento, y que si este comportamiento se amplía, crees otra clase para ello.
Por ejemplo,
si tu jefe te pide que le cambies el comportamiento de algo, no modifiques la
clase existente, ¡ya pasó testing! construye otra. Y a ésta otra, la haces heredar de la primera
y pones todo el código nuevo ahí.
Crecer por
agregación, no por remplazo.
—Pero, ¿y si
alguna clase ya no me sirve? ¿Se ha quedado obsoleta?
—¡Ahí entra el refactoring! Mueve el código a una clase padre, estableces
una nueva línea base (?) y la cierras para su modificación
“L” de Liskov
Substitution Principle, ««Olé, por Barbara Liskov»».
Este principio de sustitución sostiene que una referencia a
una clase padre abstracta, puede ser cambiada por una referencia a una clase “hija”
sin necesidad de conocer sus diferencias. Mmm…
¡Vale! En otras palabras significa, que una clase padre no
debe contener comportamientos o variables que una clase hija no pueda contener.
Por ejemplo, una referencia a una variable del tipo “MedioDeTransporte”, no
puede ser remplazada por otra de una clase hija, “Coche”, si la primera tuviese
un método “volar”.
Sí pones comportamientos en la clase padre que no son
compartidos por el 100% de las clases hijas… ¡Hay tabla! ¡Modifica tu árbol de
herencia!
La “I”, viene de Interface
Segregation Principle, o lo que en la lengua de Cervantes sería; romper las
interfaces grandes en pequeños pedacitos. Nada de métodos @Override vacíos con TODOs
que manchan la pantalla. Si tienes una interfaz general que contiene todo el
comportamiento, la “Segregues” en varias interfaces pequeñitas. Así solo
declarar la tarea que vas a realizar, y en un futuro cercano, reemplazar solo ese
comportamiento y no todo.
Por último, la “D” proviene de “Dependency inversión principle”. Este principio me parece similar o
tiene algo que ver con el principio “L”. Ya que hace referencia a que la
interacción entre todos los módulos (controladores, servicios, repositorios de
objetos, utils) deben ser del tipo interfaz o clases abstractas. Nada de clases
concretas. Pero además introduce otro concepto; el que tiene que haber una
clase en el medio, que cumpla con algún patrón de creación —Factory method,
Abstract Factory, prototype, etc—, que sea el responsable de realizar los “new”
(Instanciar los objetos)
—¡Más clases! ¡El código se vuelve imposible de seguir!
¡Cómo lo debbugeo!
—Ya, sí... en un principio se vuelve más difícil… Pero te
tengo una sorpresa…
—¿Cuál?
—A todo esto último… lo realiza Spring, cuando escribes la anotación
@Autowired. Tú solo preocúpate por declarar
bien tus variables.
—¡Tantas clases no se justifican, la mayoría de las veces!
—Es por eso que no debes apagar el cerebro. Piensa cuáles
funcionalidades pueden cambiar en el futuro y cuáles no.
—¡Las del core del
negocio!
—¡Exacto! Recuerda; clases con una sola responsabilidad, interfaces
pequeñas… sobre las variables; que sean interfaces o abstractas. Crece por
agregación, y sobre lo último… bueno, déjaselo a Spring o analízalo con más
detalle.